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.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
57 #include "wine/port.h"
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
76 #include "wine/unicode.h"
79 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
85 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
86 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
88 /****************************************************************************
91 * Takes p_iVal (which is in little endian) and returns it
92 * in the host machine's byte order.
94 #ifdef WORDS_BIGENDIAN
95 static WORD
FromLEWord(WORD p_iVal
)
97 return (((p_iVal
& 0x00FF) << 8) |
98 ((p_iVal
& 0xFF00) >> 8));
102 static DWORD
FromLEDWord(DWORD p_iVal
)
104 return (((p_iVal
& 0x000000FF) << 24) |
105 ((p_iVal
& 0x0000FF00) << 8) |
106 ((p_iVal
& 0x00FF0000) >> 8) |
107 ((p_iVal
& 0xFF000000) >> 24));
110 #define FromLEWord(X) (X)
111 #define FromLEDWord(X) (X)
115 /****************************************************************************
118 * Fix byte order in any structure if necessary
120 #ifdef WORDS_BIGENDIAN
121 static void FromLEWords(void *p_Val
, int p_iSize
)
125 p_iSize
/= sizeof(WORD
);
128 *Val
= FromLEWord(*Val
);
135 static void FromLEDWords(void *p_Val
, int p_iSize
)
139 p_iSize
/= sizeof(DWORD
);
142 *Val
= FromLEDWord(*Val
);
148 #define FromLEWords(X,Y) /*nothing*/
149 #define FromLEDWords(X,Y) /*nothing*/
153 * Find a typelib key which matches a requested maj.min version.
155 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
157 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
164 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
165 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
167 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
170 len
= sizeof(key_name
);
172 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
176 if (sscanf(key_name
, "%u.%u", &v_maj
, &v_min
) == 2)
178 TRACE("found %s: %u.%u\n", debugstr_w(buffer
), v_maj
, v_min
);
185 break; /* exact match */
187 if (v_min
> best_min
) best_min
= v_min
;
190 len
= sizeof(key_name
);
201 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
202 /* buffer must be at least 60 characters long */
203 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
205 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
206 static const WCHAR VersionFormatW
[] = {'\\','%','u','.','%','u',0};
208 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
209 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
210 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
214 /* get the path of an interface key, in the form "Interface\\<guid>" */
215 /* buffer must be at least 50 characters long */
216 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
218 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
220 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
221 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
225 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
226 /* buffer must be at least 16 characters long */
227 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
229 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
230 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
231 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
233 sprintfW( buffer
, LcidFormatW
, lcid
);
236 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
237 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
239 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
245 static int TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
248 /****************************************************************************
249 * QueryPathOfRegTypeLib [OLEAUT32.164]
251 * Gets the path to a registered type library.
254 * guid [I] referenced guid
255 * wMaj [I] major version
256 * wMin [I] minor version
258 * path [O] path of typelib
262 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
263 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
266 HRESULT WINAPI
QueryPathOfRegTypeLib(
273 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
277 WCHAR Path
[MAX_PATH
];
280 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
282 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
283 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
285 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
286 if (res
== ERROR_FILE_NOT_FOUND
)
288 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
289 return TYPE_E_LIBNOTREGISTERED
;
291 else if (res
!= ERROR_SUCCESS
)
293 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
294 return TYPE_E_REGISTRYACCESS
;
299 LONG dwPathLen
= sizeof(Path
);
301 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
303 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
307 else if (myLCID
== lcid
)
309 /* try with sub-langid */
310 myLCID
= SUBLANGID(lcid
);
312 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
314 /* try with system langid */
324 *path
= SysAllocString( Path
);
329 TRACE_(typelib
)("-- 0x%08x\n", hr
);
333 /******************************************************************************
334 * CreateTypeLib [OLEAUT32.160] creates a typelib
340 HRESULT WINAPI
CreateTypeLib(
341 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
343 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
347 /******************************************************************************
348 * LoadTypeLib [OLEAUT32.161]
350 * Loads a type library
353 * szFile [I] Name of file to load from.
354 * pptLib [O] Pointer that receives ITypeLib object on success.
361 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
363 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
365 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
366 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
369 /******************************************************************************
370 * LoadTypeLibEx [OLEAUT32.183]
372 * Loads and optionally registers a type library
378 HRESULT WINAPI
LoadTypeLibEx(
379 LPCOLESTR szFile
, /* [in] Name of file to load from */
380 REGKIND regkind
, /* [in] Specify kind of registration */
381 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
383 WCHAR szPath
[MAX_PATH
+1];
386 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
390 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
395 case REGKIND_DEFAULT
:
396 /* don't register typelibs supplied with full path. Experimentation confirms the following */
397 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
398 (szFile
[0] && (szFile
[1] == ':'))) break;
399 /* else fall-through */
401 case REGKIND_REGISTER
:
402 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
404 IUnknown_Release(*pptLib
);
412 TRACE(" returns %08x\n",res
);
416 /******************************************************************************
417 * LoadRegTypeLib [OLEAUT32.162]
419 * Loads a registered type library.
422 * rguid [I] GUID of the registered type library.
423 * wVerMajor [I] major version.
424 * wVerMinor [I] minor version.
425 * lcid [I] locale ID.
426 * ppTLib [O] pointer that receives an ITypeLib object on success.
430 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
433 HRESULT WINAPI
LoadRegTypeLib(
445 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
449 res
= LoadTypeLib(bstr
, ppTLib
);
453 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
459 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
460 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
461 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
462 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
463 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
464 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
466 /******************************************************************************
467 * RegisterTypeLib [OLEAUT32.163]
468 * Adds information about a type library to the System Registry
470 * Docs: ITypeLib FAR * ptlib
471 * Docs: OLECHAR FAR* szFullPath
472 * Docs: OLECHAR FAR* szHelpDir
478 HRESULT WINAPI
RegisterTypeLib(
479 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
480 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
481 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
484 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
485 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
486 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
496 if (ptlib
== NULL
|| szFullPath
== NULL
)
499 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
502 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
505 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
506 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
510 /* Set the human-readable name of the typelib */
511 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
513 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
514 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
522 /* Make up the name of the typelib path subkey */
523 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
525 /* Create the typelib path subkey */
526 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
527 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
529 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
530 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
538 /* Create the flags subkey */
539 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
540 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
542 /* FIXME: is %u correct? */
543 static const WCHAR formatW
[] = {'%','u',0};
545 sprintfW(buf
, formatW
, attr
->wLibFlags
);
546 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
547 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
555 /* create the helpdir subkey */
556 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
557 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
559 BOOL freeHelpDir
= FALSE
;
562 /* if we created a new key, and helpDir was null, set the helpdir
563 to the directory which contains the typelib. However,
564 if we just opened an existing key, we leave the helpdir alone */
565 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
566 szHelpDir
= SysAllocString(szFullPath
);
567 pIndexStr
= strrchrW(szHelpDir
, '\\');
574 /* if we have an szHelpDir, set it! */
575 if (szHelpDir
!= NULL
) {
576 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
577 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
583 if (freeHelpDir
) SysFreeString(szHelpDir
);
595 /* register OLE Automation-compatible interfaces for this typelib */
596 types
= ITypeLib_GetTypeInfoCount(ptlib
);
597 for (tidx
=0; tidx
<types
; tidx
++) {
598 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
599 LPOLESTR name
= NULL
;
600 ITypeInfo
*tinfo
= NULL
;
602 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
605 case TKIND_INTERFACE
:
606 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
607 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
611 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
612 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
616 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
621 TYPEATTR
*tattr
= NULL
;
622 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
625 TRACE_(typelib
)("guid=%s, flags=%04x (",
626 debugstr_guid(&tattr
->guid
),
629 if (TRACE_ON(typelib
)) {
630 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
650 if (tattr
->wTypeFlags
& (TYPEFLAG_FOLEAUTOMATION
|TYPEFLAG_FDUAL
|TYPEFLAG_FDISPATCHABLE
))
652 /* register interface<->typelib coupling */
653 get_interface_key( &tattr
->guid
, keyName
);
654 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
655 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
658 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
659 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
661 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 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
, ProxyStubClsid32W
, 0, NULL
, 0,
669 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
670 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
671 (const BYTE
*)PSOA
, sizeof PSOA
);
675 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
676 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
679 static const WCHAR fmtver
[] = {'%','u','.','%','u',0 };
680 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
682 StringFromGUID2(&attr
->guid
, buffer
, 40);
683 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
684 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
685 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
686 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
687 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
695 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
698 ITypeInfo_Release(tinfo
);
705 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
711 /******************************************************************************
712 * UnRegisterTypeLib [OLEAUT32.186]
713 * Removes information about a type library from the System Registry
720 HRESULT WINAPI
UnRegisterTypeLib(
721 REFGUID libid
, /* [in] Guid of the library */
722 WORD wVerMajor
, /* [in] major version */
723 WORD wVerMinor
, /* [in] minor version */
724 LCID lcid
, /* [in] locale id */
727 BSTR tlibPath
= NULL
;
730 WCHAR subKeyName
[50];
733 BOOL deleteOtherStuff
;
736 TYPEATTR
* typeAttr
= NULL
;
738 ITypeInfo
* typeInfo
= NULL
;
739 ITypeLib
* typeLib
= NULL
;
742 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
744 /* Create the path to the key */
745 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
747 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
749 TRACE("Unsupported syskind %i\n", syskind
);
750 result
= E_INVALIDARG
;
754 /* get the path to the typelib on disk */
755 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
756 result
= E_INVALIDARG
;
760 /* Try and open the key to the type library. */
761 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
762 result
= E_INVALIDARG
;
766 /* Try and load the type library */
767 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
768 result
= TYPE_E_INVALIDSTATE
;
772 /* remove any types registered with this typelib */
773 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
774 for (i
=0; i
<numTypes
; i
++) {
775 /* get the kind of type */
776 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
780 /* skip non-interfaces, and get type info for the type */
781 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
784 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
787 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
791 /* the path to the type */
792 get_interface_key( &typeAttr
->guid
, subKeyName
);
794 /* Delete its bits */
795 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
) {
798 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
799 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
800 RegDeleteKeyW(subKey
, TypeLibW
);
803 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
806 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
808 if (typeInfo
) ITypeInfo_Release(typeInfo
);
812 /* Now, delete the type library path subkey */
813 get_lcid_subkey( lcid
, syskind
, subKeyName
);
814 RegDeleteKeyW(key
, subKeyName
);
815 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
816 RegDeleteKeyW(key
, subKeyName
);
818 /* check if there is anything besides the FLAGS/HELPDIR keys.
819 If there is, we don't delete them */
820 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
821 deleteOtherStuff
= TRUE
;
823 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
824 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
826 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
827 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
828 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
829 deleteOtherStuff
= FALSE
;
833 /* only delete the other parts of the key if we're absolutely sure */
834 if (deleteOtherStuff
) {
835 RegDeleteKeyW(key
, FLAGSW
);
836 RegDeleteKeyW(key
, HELPDIRW
);
840 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
841 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
842 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
846 if (tlibPath
) SysFreeString(tlibPath
);
847 if (typeLib
) ITypeLib_Release(typeLib
);
848 if (subKey
) RegCloseKey(subKey
);
849 if (key
) RegCloseKey(key
);
853 /*======================= ITypeLib implementation =======================*/
855 typedef struct tagTLBCustData
859 struct tagTLBCustData
* next
;
862 /* data structure for import typelibs */
863 typedef struct tagTLBImpLib
865 int offset
; /* offset in the file (MSFT)
866 offset in nametable (SLTG)
867 just used to identify library while reading
869 GUID guid
; /* libid */
870 BSTR name
; /* name */
872 LCID lcid
; /* lcid of imported typelib */
874 WORD wVersionMajor
; /* major version number */
875 WORD wVersionMinor
; /* minor version number */
877 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
878 NULL if not yet loaded */
879 struct tagTLBImpLib
* next
;
882 /* internal ITypeLib data */
883 typedef struct tagITypeLibImpl
885 const ITypeLib2Vtbl
*lpVtbl
;
886 const ITypeCompVtbl
*lpVtblTypeComp
;
888 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
890 /* strings can be stored in tlb as multibyte strings BUT they are *always*
891 * exported to the application as a UNICODE string.
897 unsigned long dwHelpContext
;
898 int TypeInfoCount
; /* nr of typeinfo's in librarry */
899 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
900 int ctCustData
; /* number of items in cust data list */
901 TLBCustData
* pCustData
; /* linked list to cust data */
902 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
903 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
904 libary. Only used while read MSFT
907 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
908 struct tagITypeLibImpl
*next
, *prev
;
913 static const ITypeLib2Vtbl tlbvt
;
914 static const ITypeCompVtbl tlbtcvt
;
916 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
918 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
921 /* ITypeLib methods */
922 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
923 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
925 /*======================= ITypeInfo implementation =======================*/
927 /* data for referenced types */
928 typedef struct tagTLBRefType
930 INT index
; /* Type index for internal ref or for external ref
931 it the format is SLTG. -2 indicates to
934 GUID guid
; /* guid of the referenced type */
935 /* if index == TLB_REF_USE_GUID */
937 HREFTYPE reference
; /* The href of this ref */
938 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
939 TLB_REF_INTERNAL for internal refs
940 TLB_REF_NOT_FOUND for broken refs */
942 struct tagTLBRefType
* next
;
945 #define TLB_REF_USE_GUID -2
947 #define TLB_REF_INTERNAL (void*)-2
948 #define TLB_REF_NOT_FOUND (void*)-1
950 /* internal Parameter data */
951 typedef struct tagTLBParDesc
955 TLBCustData
* pCustData
; /* linked list to cust data */
958 /* internal Function data */
959 typedef struct tagTLBFuncDesc
961 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
962 BSTR Name
; /* the name of this function */
963 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
965 int HelpStringContext
;
967 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
969 TLBCustData
* pCustData
; /* linked list to cust data; */
970 struct tagTLBFuncDesc
* next
;
973 /* internal Variable data */
974 typedef struct tagTLBVarDesc
976 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
977 BSTR Name
; /* the name of this variable */
979 int HelpStringContext
; /* FIXME: where? */
982 TLBCustData
* pCustData
;/* linked list to cust data; */
983 struct tagTLBVarDesc
* next
;
986 /* internal implemented interface data */
987 typedef struct tagTLBImplType
989 HREFTYPE hRef
; /* hRef of interface */
990 int implflags
; /* IMPLFLAG_*s */
992 TLBCustData
* pCustData
;/* linked list to custom data; */
993 struct tagTLBImplType
*next
;
996 /* internal TypeInfo data */
997 typedef struct tagITypeInfoImpl
999 const ITypeInfo2Vtbl
*lpVtbl
;
1000 const ITypeCompVtbl
*lpVtblTypeComp
;
1002 BOOL no_free_data
; /* don't free data structurees */
1003 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1004 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1005 int index
; /* index in this typelib; */
1006 HREFTYPE hreftype
; /* hreftype for app object binding */
1007 /* type libs seem to store the doc strings in ascii
1008 * so why should we do it in unicode?
1013 unsigned long dwHelpContext
;
1014 unsigned long dwHelpStringContext
;
1017 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
1020 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
1022 /* Implemented Interfaces */
1023 TLBImplType
* impltypelist
;
1025 TLBRefType
* reflist
;
1027 TLBCustData
* pCustData
; /* linked list to cust data; */
1028 struct tagITypeInfoImpl
* next
;
1031 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1033 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1036 static const ITypeInfo2Vtbl tinfvt
;
1037 static const ITypeCompVtbl tcompvt
;
1039 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
1041 typedef struct tagTLBContext
1043 unsigned int oStart
; /* start of TLB in file */
1044 unsigned int pos
; /* current pos */
1045 unsigned int length
; /* total length */
1046 void *mapping
; /* memory mapping */
1047 MSFT_SegDir
* pTblDir
;
1048 ITypeLibImpl
* pLibInfo
;
1052 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
1057 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1058 if (pTD
->vt
& VT_RESERVED
)
1059 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1060 if (pTD
->vt
& VT_BYREF
)
1061 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1062 if (pTD
->vt
& VT_ARRAY
)
1063 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1064 if (pTD
->vt
& VT_VECTOR
)
1065 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1066 switch(pTD
->vt
& VT_TYPEMASK
) {
1067 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1068 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1069 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1070 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1071 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1072 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1073 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1074 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1075 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1076 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1077 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1078 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1079 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1080 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1081 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1082 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1083 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1084 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1085 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1086 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1087 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1088 pTD
->u
.hreftype
); break;
1089 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1090 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1092 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1093 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1095 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1096 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1097 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1100 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1104 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1106 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1107 dump_TypeDesc(&edesc
->tdesc
,buf
);
1108 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1109 MESSAGE("\t\tu.paramdesc.wParamFlags");
1110 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1111 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1112 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1113 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1114 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1115 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1116 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1117 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1118 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1120 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1122 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1123 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1124 MESSAGE("Param %d:\n",i
);
1125 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1127 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1128 switch (funcdesc
->funckind
) {
1129 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1130 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1131 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1132 case FUNC_STATIC
: MESSAGE("static");break;
1133 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1134 default: MESSAGE("unknown");break;
1136 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1137 switch (funcdesc
->invkind
) {
1138 case INVOKE_FUNC
: MESSAGE("func");break;
1139 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1140 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1141 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1143 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1144 switch (funcdesc
->callconv
) {
1145 case CC_CDECL
: MESSAGE("cdecl");break;
1146 case CC_PASCAL
: MESSAGE("pascal");break;
1147 case CC_STDCALL
: MESSAGE("stdcall");break;
1148 case CC_SYSCALL
: MESSAGE("syscall");break;
1151 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1152 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1153 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1155 MESSAGE("\telemdescFunc (return value type):\n");
1156 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1159 static const char * typekind_desc
[] =
1172 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1175 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1176 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1177 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1180 dump_FUNCDESC(&(pfd
->funcdesc
));
1182 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1183 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1185 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
)
1189 dump_TLBFuncDescOne(pfd
);
1193 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
)
1197 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1202 static void dump_TLBImpLib(const TLBImpLib
*import
)
1204 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1205 debugstr_w(import
->name
));
1206 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1207 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1210 static void dump_TLBRefType(const TLBRefType
* prt
)
1214 TRACE_(typelib
)("href:0x%08x\n", prt
->reference
);
1215 if(prt
->index
== -1)
1216 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1218 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1220 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1221 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1222 TRACE_(typelib
)("in lib\n");
1223 dump_TLBImpLib(prt
->pImpTLInfo
);
1229 static void dump_TLBImplType(const TLBImplType
* impl
)
1233 "implementing/inheriting interface hRef = %x implflags %x\n",
1234 impl
->hRef
, impl
->implflags
);
1239 void dump_Variant(const VARIANT
* pvar
)
1243 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1247 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1248 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1250 TRACE(",%p", V_BYREF(pvar
));
1252 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1254 TRACE(",%p", V_ARRAY(pvar
));
1256 else switch (V_TYPE(pvar
))
1258 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1259 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1260 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1261 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1263 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1265 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1266 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1267 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1268 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1269 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1270 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1271 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1272 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1273 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1274 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1275 V_CY(pvar
).s
.Lo
); break;
1277 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1278 TRACE(",<invalid>");
1280 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1281 st
.wHour
, st
.wMinute
, st
.wSecond
);
1285 case VT_USERDEFINED
:
1287 case VT_NULL
: break;
1288 default: TRACE(",?"); break;
1294 static void dump_DispParms(const DISPPARAMS
* pdp
)
1298 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1300 if (pdp
->cNamedArgs
)
1301 TRACE("named args:\n");
1302 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1303 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1307 for (index
= 0; index
< pdp
->cArgs
; index
++)
1308 dump_Variant( &pdp
->rgvarg
[index
] );
1311 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1313 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1314 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1315 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1316 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1317 TRACE("fct:%u var:%u impl:%u\n",
1318 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1319 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1320 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1321 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1323 dump_TLBFuncDesc(pty
->funclist
);
1324 dump_TLBVarDesc(pty
->varlist
);
1325 dump_TLBImplType(pty
->impltypelist
);
1328 static void dump_VARDESC(const VARDESC
*v
)
1330 MESSAGE("memid %d\n",v
->memid
);
1331 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1332 MESSAGE("oInst %d\n",v
->u
.oInst
);
1333 dump_ELEMDESC(&(v
->elemdescVar
));
1334 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1335 MESSAGE("varkind %d\n",v
->varkind
);
1338 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1340 /* VT_LPWSTR is largest type that */
1341 /* may appear in type description*/
1342 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1343 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1344 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1345 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1346 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1347 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1351 static void TLB_abort(void)
1355 static void * TLB_Alloc(unsigned size
)
1358 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1360 ERR("cannot allocate memory\n");
1365 static void TLB_Free(void * ptr
)
1367 HeapFree(GetProcessHeap(), 0, ptr
);
1370 /* returns the size required for a deep copy of a typedesc into a
1372 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1376 if (alloc_initial_space
)
1377 size
+= sizeof(TYPEDESC
);
1383 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1386 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1387 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1393 /* deep copy a typedesc into a flat buffer */
1394 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1399 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1408 dest
->u
.lptdesc
= buffer
;
1409 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1412 dest
->u
.lpadesc
= buffer
;
1413 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1414 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1415 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1421 /**********************************************************************
1423 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1425 static inline unsigned int MSFT_Tell(TLBContext
*pcx
)
1430 static inline void MSFT_Seek(TLBContext
*pcx
, long where
)
1432 if (where
!= DO_NOT_SEEK
)
1434 where
+= pcx
->oStart
;
1435 if (where
> pcx
->length
)
1438 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1446 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1448 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1449 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1451 MSFT_Seek(pcx
, where
);
1452 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1453 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1458 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1463 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1464 FromLEDWords(buffer
, ret
);
1469 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1474 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1475 FromLEWords(buffer
, ret
);
1480 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1482 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1483 memset(pGuid
,0, sizeof(GUID
));
1486 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1487 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1488 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1489 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1490 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1493 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1495 MSFT_NameIntro niName
;
1499 ERR_(typelib
)("bad offset %d\n", offset
);
1503 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1504 pcx
->pTblDir
->pNametab
.offset
+offset
);
1506 return niName
.hreftype
;
1509 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1512 MSFT_NameIntro niName
;
1514 BSTR bstrName
= NULL
;
1518 ERR_(typelib
)("bad offset %d\n", offset
);
1521 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1522 pcx
->pTblDir
->pNametab
.offset
+offset
);
1523 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1524 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1525 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1526 name
[niName
.namelen
& 0xff]='\0';
1528 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1531 /* no invalid characters in string */
1534 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1536 /* don't check for invalid character since this has been done previously */
1537 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1541 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1545 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1552 if(offset
<0) return NULL
;
1553 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1554 if(length
<= 0) return 0;
1555 string
=TLB_Alloc(length
+1);
1556 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1557 string
[length
]='\0';
1559 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1560 string
, -1, NULL
, 0);
1562 /* no invalid characters in string */
1565 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1567 /* don't check for invalid character since this has been done previously */
1568 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1572 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1576 * read a value and fill a VARIANT structure
1578 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1582 TRACE_(typelib
)("\n");
1584 if(offset
<0) { /* data are packed in here */
1585 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1586 V_I4(pVar
) = offset
& 0x3ffffff;
1589 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1590 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1591 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1592 switch (V_VT(pVar
)){
1593 case VT_EMPTY
: /* FIXME: is this right? */
1594 case VT_NULL
: /* FIXME: is this right? */
1595 case VT_I2
: /* this should not happen */
1606 case VT_VOID
: /* FIXME: is this right? */
1614 case VT_DECIMAL
: /* FIXME: is this right? */
1617 /* pointer types with known behaviour */
1620 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1623 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1626 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1628 nullPos
= MSFT_Tell(pcx
);
1629 size
= nullPos
- origPos
;
1630 MSFT_Seek(pcx
, origPos
);
1632 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1633 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1634 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1635 /* FIXME: do we need a AtoW conversion here? */
1636 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1637 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1641 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1648 case VT_USERDEFINED
:
1654 case VT_STREAMED_OBJECT
:
1655 case VT_STORED_OBJECT
:
1656 case VT_BLOB_OBJECT
:
1661 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1665 if(size
>0) /* (big|small) endian correct? */
1666 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1670 * create a linked list with custom data
1672 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1678 TRACE_(typelib
)("\n");
1682 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1683 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1684 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1685 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1686 /* add new custom data at head of the list */
1687 pNew
->next
=*ppCustData
;
1689 offset
= entry
.next
;
1694 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1698 pTd
->vt
=type
& VT_TYPEMASK
;
1700 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1702 if(pTd
->vt
== VT_USERDEFINED
)
1703 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1705 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1708 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1710 /* resolve referenced type if any */
1713 switch (lpTypeDesc
->vt
)
1716 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1720 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1723 case VT_USERDEFINED
:
1724 MSFT_DoRefType(pcx
, pTI
,
1725 lpTypeDesc
->u
.hreftype
);
1737 MSFT_DoFuncs(TLBContext
* pcx
,
1742 TLBFuncDesc
** pptfd
)
1745 * member information is stored in a data structure at offset
1746 * indicated by the memoffset field of the typeinfo structure
1747 * There are several distinctive parts.
1748 * The first part starts with a field that holds the total length
1749 * of this (first) part excluding this field. Then follow the records,
1750 * for each member there is one record.
1752 * The first entry is always the length of the record (including this
1754 * The rest of the record depends on the type of the member. If there is
1755 * a field indicating the member type (function, variable, interface, etc)
1756 * I have not found it yet. At this time we depend on the information
1757 * in the type info and the usual order how things are stored.
1759 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1762 * Third is an equal sized array with file offsets to the name entry
1765 * The fourth and last (?) part is an array with offsets to the records
1766 * in the first part of this file segment.
1769 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1770 int recoffset
= offset
+ sizeof(INT
);
1772 char *recbuf
= HeapAlloc(GetProcessHeap(), 0, 0xffff);
1773 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1774 TLBFuncDesc
*ptfd_prev
= NULL
;
1776 TRACE_(typelib
)("\n");
1778 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1780 for ( i
= 0; i
< cFuncs
; i
++ )
1782 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1784 /* name, eventually add to a hash table */
1785 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1786 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1788 /* nameoffset is sometimes -1 on the second half of a propget/propput
1789 * pair of functions */
1790 if ((nameoffset
== -1) && (i
> 0))
1791 (*pptfd
)->Name
= SysAllocString(ptfd_prev
->Name
);
1793 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1795 /* read the function information record */
1796 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1798 reclength
&= 0xffff;
1800 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1802 /* do the attributes */
1803 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1806 if ( nrattributes
> 0 )
1808 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1810 if ( nrattributes
> 1 )
1812 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1813 pFuncRec
->OptAttr
[1]) ;
1815 if ( nrattributes
> 2 )
1817 if ( pFuncRec
->FKCCIC
& 0x2000 )
1819 (*pptfd
)->Entry
= SysAllocString((WCHAR
*)pFuncRec
->OptAttr
[2]);
1823 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1824 pFuncRec
->OptAttr
[2]);
1826 if( nrattributes
> 5 )
1828 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1830 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1833 pFuncRec
->OptAttr
[6],
1834 &(*pptfd
)->pCustData
);
1841 /* fill the FuncDesc Structure */
1842 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1843 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1845 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1846 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1847 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1848 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1849 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1850 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1851 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1855 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1857 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
);
1859 /* do the parameters/arguments */
1860 if(pFuncRec
->nrargs
)
1863 MSFT_ParameterInfo paraminfo
;
1865 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1866 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1868 (*pptfd
)->pParamDesc
=
1869 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1871 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1872 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1874 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1876 ELEMDESC
*elemdesc
= &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1883 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1886 if (paraminfo
.oName
== -1)
1887 /* this occurs for [propput] or [propget] methods, so
1888 * we should just set the name of the parameter to the
1889 * name of the method. */
1890 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1892 (*pptfd
)->pParamDesc
[j
].Name
=
1893 MSFT_ReadName( pcx
, paraminfo
.oName
);
1894 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1896 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
1899 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
1900 (pFuncRec
->FKCCIC
& 0x1000) )
1902 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1904 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1906 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
1908 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1909 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1911 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1915 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
1917 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1920 pFuncRec
->OptAttr
[7+j
],
1921 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1924 /* SEEK value = jump to offset,
1925 * from there jump to the end of record,
1926 * go back by (j-1) arguments
1928 MSFT_ReadLEDWords( ¶minfo
,
1929 sizeof(MSFT_ParameterInfo
), pcx
,
1930 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1931 * sizeof(MSFT_ParameterInfo
)));
1935 /* scode is not used: archaic win16 stuff FIXME: right? */
1936 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1937 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1940 pptfd
= & ((*pptfd
)->next
);
1941 recoffset
+= reclength
;
1943 HeapFree(GetProcessHeap(), 0, recbuf
);
1946 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1947 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1949 int infolen
, nameoffset
, reclength
;
1951 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1955 TRACE_(typelib
)("\n");
1957 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1958 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1959 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1960 recoffset
+= offset
+sizeof(INT
);
1961 for(i
=0;i
<cVars
;i
++){
1962 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1963 /* name, eventually add to a hash table */
1964 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1965 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1966 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1967 /* read the variable information record */
1968 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1970 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1972 if(reclength
>(6*sizeof(INT
)) )
1973 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1974 if(reclength
>(7*sizeof(INT
)) )
1975 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1976 if(reclength
>(8*sizeof(INT
)) )
1977 if(reclength
>(9*sizeof(INT
)) )
1978 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1979 /* fill the VarDesc Structure */
1980 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1981 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
1982 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1983 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1984 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1985 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1986 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1987 if(pVarRec
->VarKind
== VAR_CONST
){
1988 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1989 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1990 pVarRec
->OffsValue
, pcx
);
1992 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1993 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptvd
)->vardesc
.elemdescVar
.tdesc
);
1994 pptvd
=&((*pptvd
)->next
);
1995 recoffset
+= reclength
;
1998 /* fill in data for a hreftype (offset). When the referenced type is contained
1999 * in the typelib, it's just an (file) offset in the type info base dir.
2000 * If comes from import, it's an offset+1 in the ImpInfo table
2002 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
2006 TLBRefType
**ppRefType
= &pTI
->reflist
;
2008 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2011 if((*ppRefType
)->reference
== offset
)
2013 ppRefType
= &(*ppRefType
)->next
;
2016 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2017 sizeof(**ppRefType
));
2019 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2020 /* external typelib */
2021 MSFT_ImpInfo impinfo
;
2022 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
2024 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2026 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2027 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2028 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
2029 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
2030 pImpLib
=pImpLib
->next
;
2033 (*ppRefType
)->reference
=offset
;
2034 (*ppRefType
)->pImpTLInfo
= pImpLib
;
2035 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2036 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
2037 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType
)->guid
));
2038 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
2040 (*ppRefType
)->index
= impinfo
.oGuid
;
2042 ERR("Cannot find a reference\n");
2043 (*ppRefType
)->reference
=-1;
2044 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
2047 /* in this typelib */
2048 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
2049 (*ppRefType
)->reference
=offset
;
2050 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
2054 /* process Implemented Interfaces of a com class */
2055 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2059 MSFT_RefRecord refrec
;
2060 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2062 TRACE_(typelib
)("\n");
2064 for(i
=0;i
<count
;i
++){
2065 if(offset
<0) break; /* paranoia */
2066 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2067 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2068 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
2069 (*ppImpl
)->hRef
= refrec
.reftype
;
2070 (*ppImpl
)->implflags
=refrec
.flags
;
2071 (*ppImpl
)->ctCustData
=
2072 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2073 offset
=refrec
.onext
;
2074 ppImpl
=&((*ppImpl
)->next
);
2078 * process a typeinfo record
2080 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2084 ITypeLibImpl
* pLibInfo
)
2086 MSFT_TypeInfoBase tiBase
;
2087 ITypeInfoImpl
*ptiRet
;
2089 TRACE_(typelib
)("count=%u\n", count
);
2091 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2092 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2093 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2095 /* this is where we are coming from */
2096 ptiRet
->pTypeLib
= pLibInfo
;
2097 ptiRet
->index
=count
;
2098 /* fill in the typeattr fields */
2100 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2101 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2102 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2103 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2104 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2105 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2106 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2107 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2108 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2109 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2110 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2111 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2112 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2113 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2114 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2115 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2118 /* IDLDESC idldescType; *//* never saw this one != zero */
2120 /* name, eventually add to a hash table */
2121 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2122 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2123 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2125 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2126 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2127 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2129 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2130 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2132 /* note: InfoType's Help file and HelpStringDll come from the containing
2133 * library. Further HelpString and Docstring appear to be the same thing :(
2136 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2137 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2138 ptiRet
->TypeAttr
.cVars
,
2139 tiBase
.memoffset
, & ptiRet
->funclist
);
2141 if(ptiRet
->TypeAttr
.cVars
>0 )
2142 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2143 ptiRet
->TypeAttr
.cVars
,
2144 tiBase
.memoffset
, & ptiRet
->varlist
);
2145 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2146 switch(ptiRet
->TypeAttr
.typekind
)
2149 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2152 case TKIND_DISPATCH
:
2153 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2155 if (tiBase
.datatype1
!= -1)
2157 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2158 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2162 MSFT_DoRefType(pcx
, ptiRet
, dispatch_href
);
2163 ptiRet
->impltypelist
->hRef
= dispatch_href
;
2167 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2168 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2169 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2174 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2176 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2177 debugstr_w(ptiRet
->Name
),
2178 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2179 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2184 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2185 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2186 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2189 static ITypeLibImpl
*tlb_cache_first
;
2190 static CRITICAL_SECTION cache_section
;
2191 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2193 0, 0, &cache_section
,
2194 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2195 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2197 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2200 /****************************************************************************
2203 * find the type of the typelib file and map the typelib resource into
2206 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2207 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2208 static int TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2210 ITypeLibImpl
*entry
;
2211 int ret
= TYPE_E_CANTLOADLIBRARY
;
2217 lstrcpynW(pszPath
, pszFileName
, cchPath
);
2219 /* first try loading as a dll and access the typelib as a resource */
2220 hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2221 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2224 /* it may have been specified with resource index appended to the
2225 * path, so remove it and try again */
2226 const WCHAR
*pIndexStr
= strrchrW(pszFileName
, '\\');
2227 if(pIndexStr
&& pIndexStr
!= pszFileName
&& *++pIndexStr
!= '\0')
2229 index
= atoiW(pIndexStr
);
2230 pszPath
[pIndexStr
- pszFileName
- 1] = '\0';
2232 hinstDLL
= LoadLibraryExW(pszPath
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2233 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2237 /* get the path to the specified typelib file */
2240 /* otherwise, try loading as a regular file */
2241 if (!SearchPathW(NULL
, pszFileName
, NULL
, cchPath
, pszPath
, NULL
))
2242 return TYPE_E_CANTLOADLIBRARY
;
2245 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2247 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2248 EnterCriticalSection(&cache_section
);
2249 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2251 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2253 TRACE("cache hit\n");
2254 *ppTypeLib
= (ITypeLib2
*)entry
;
2255 ITypeLib_AddRef(*ppTypeLib
);
2256 LeaveCriticalSection(&cache_section
);
2257 FreeLibrary(hinstDLL
);
2261 LeaveCriticalSection(&cache_section
);
2263 /* now actually load and parse the typelib */
2266 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2267 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2270 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2273 LPVOID pBase
= LockResource(hGlobal
);
2274 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2278 /* try to load as incore resource */
2279 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2280 if (dwSignature
== MSFT_SIGNATURE
)
2281 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2282 else if (dwSignature
== SLTG_SIGNATURE
)
2283 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2285 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2287 FreeResource( hGlobal
);
2290 FreeLibrary(hinstDLL
);
2294 HANDLE hFile
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2295 if (INVALID_HANDLE_VALUE
!= hFile
)
2297 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2300 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2303 /* retrieve file size */
2304 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2305 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2307 if (dwSignature
== MSFT_SIGNATURE
)
2308 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2309 else if (dwSignature
== SLTG_SIGNATURE
)
2310 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2312 UnmapViewOfFile(pBase
);
2314 CloseHandle(hMapping
);
2321 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2323 TRACE("adding to cache\n");
2324 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath
)+1) * sizeof(WCHAR
));
2325 lstrcpyW(impl
->path
, pszPath
);
2326 /* We should really canonicalise the path here. */
2327 impl
->index
= index
;
2329 /* FIXME: check if it has added already in the meantime */
2330 EnterCriticalSection(&cache_section
);
2331 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2333 tlb_cache_first
= impl
;
2334 LeaveCriticalSection(&cache_section
);
2337 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2342 /*================== ITypeLib(2) Methods ===================================*/
2344 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2346 ITypeLibImpl
* pTypeLibImpl
;
2348 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2349 if (!pTypeLibImpl
) return NULL
;
2351 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2352 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2353 pTypeLibImpl
->ref
= 1;
2355 return pTypeLibImpl
;
2358 /****************************************************************************
2359 * ITypeLib2_Constructor_MSFT
2361 * loading an MSFT typelib from an in-memory image
2363 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2367 MSFT_Header tlbHeader
;
2368 MSFT_SegDir tlbSegDir
;
2369 ITypeLibImpl
* pTypeLibImpl
;
2371 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
2373 pTypeLibImpl
= TypeLibImpl_Constructor();
2374 if (!pTypeLibImpl
) return NULL
;
2376 /* get pointer to beginning of typelib data */
2380 cx
.pLibInfo
= pTypeLibImpl
;
2381 cx
.length
= dwTLBLength
;
2384 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2385 TRACE_(typelib
)("header:\n");
2386 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2387 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2388 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2391 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
2393 /* there is a small amount of information here until the next important
2395 * the segment directory . Try to calculate the amount of data */
2396 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2398 /* now read the segment directory */
2399 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2400 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2401 cx
.pTblDir
= &tlbSegDir
;
2403 /* just check two entries */
2404 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2406 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2407 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2411 /* now fill our internal data */
2412 /* TLIBATTR fields */
2413 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2415 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2416 /* Windows seems to have zero here, is this correct? */
2417 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2418 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2420 pTypeLibImpl
->LibAttr
.lcid
= 0;
2422 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2423 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2424 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2425 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2427 /* name, eventually add to a hash table */
2428 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2431 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2432 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2434 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2437 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2438 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2441 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2444 if(tlbHeader
.CustomDataOffset
>= 0)
2446 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2449 /* fill in typedescriptions */
2450 if(tlbSegDir
.pTypdescTab
.length
> 0)
2452 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2454 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2455 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2458 /* FIXME: add several sanity checks here */
2459 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2460 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2462 /* FIXME: check safearray */
2464 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2466 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2468 else if(td
[0] == VT_CARRAY
)
2470 /* array descr table here */
2471 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2473 else if(td
[0] == VT_USERDEFINED
)
2475 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2477 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2480 /* second time around to fill the array subscript info */
2483 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2484 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2486 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2487 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2490 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2492 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2494 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2496 for(j
= 0; j
<td
[2]; j
++)
2498 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2499 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2500 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2501 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2506 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2507 ERR("didn't find array description data\n");
2512 /* imported type libs */
2513 if(tlbSegDir
.pImpFiles
.offset
>0)
2515 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2516 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2519 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2524 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2525 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2526 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2528 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2529 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2530 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2531 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2534 name
= TLB_Alloc(size
+1);
2535 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2536 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2537 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2538 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2541 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2542 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2544 ppImpLib
= &(*ppImpLib
)->next
;
2549 if(tlbHeader
.nrtypeinfos
>= 0 )
2551 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2552 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2555 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2557 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, tlbHeader
.dispatchpos
, pTypeLibImpl
);
2559 ppTI
= &((*ppTI
)->next
);
2560 (pTypeLibImpl
->TypeInfoCount
)++;
2564 TRACE("(%p)\n", pTypeLibImpl
);
2565 return (ITypeLib2
*) pTypeLibImpl
;
2569 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2575 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2576 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2577 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2578 ret
= SysAllocString(nameW
);
2579 HeapFree(GetProcessHeap(), 0, nameW
);
2583 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2589 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2590 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2594 guid
->Data4
[0] = s
>> 8;
2595 guid
->Data4
[1] = s
& 0xff;
2598 for(i
= 0; i
< 6; i
++) {
2599 memcpy(b
, str
+ 24 + 2 * i
, 2);
2600 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2605 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2612 bytelen
= *(WORD
*)ptr
;
2613 if(bytelen
== 0xffff) return 2;
2614 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2615 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2616 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2617 *pBstr
= SysAllocStringLen(nameW
, len
);
2618 HeapFree(GetProcessHeap(), 0, nameW
);
2622 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2627 bytelen
= *(WORD
*)ptr
;
2628 if(bytelen
== 0xffff) return 2;
2629 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2630 memcpy(*str
, ptr
+ 2, bytelen
);
2631 (*str
)[bytelen
] = '\0';
2635 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2637 char *ptr
= pLibBlk
;
2640 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2641 FIXME("libblk magic = %04x\n", w
);
2646 if((w
= *(WORD
*)ptr
) != 0xffff) {
2647 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2652 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2654 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2656 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2659 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2662 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2663 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2665 pTypeLibImpl
->LibAttr
.lcid
= 0;
2668 ptr
+= 4; /* skip res12 */
2670 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2673 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2676 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2679 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2680 ptr
+= sizeof(GUID
);
2682 return ptr
- (char*)pLibBlk
;
2685 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
)
2690 if((*pType
& 0xe00) == 0xe00) {
2692 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2694 pTD
= pTD
->u
.lptdesc
;
2696 switch(*pType
& 0x3f) {
2699 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2701 pTD
= pTD
->u
.lptdesc
;
2704 case VT_USERDEFINED
:
2705 pTD
->vt
= VT_USERDEFINED
;
2706 pTD
->u
.hreftype
= *(++pType
) / 4;
2712 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2715 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2717 pTD
->vt
= VT_CARRAY
;
2718 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2720 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2721 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2722 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2723 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2725 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2731 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2735 pTD
->vt
= VT_SAFEARRAY
;
2736 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2738 pTD
= pTD
->u
.lptdesc
;
2742 pTD
->vt
= *pType
& 0x3f;
2751 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2753 /* Handle [in/out] first */
2754 if((*pType
& 0xc000) == 0xc000)
2755 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2756 else if(*pType
& 0x8000)
2757 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2758 else if(*pType
& 0x4000)
2759 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2761 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2764 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2767 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2769 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
);
2773 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2778 TLBRefType
**ppRefType
;
2780 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2781 FIXME("Ref magic = %x\n", pRef
->magic
);
2784 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2786 ppRefType
= &pTI
->reflist
;
2787 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2789 unsigned int lib_offs
, type_num
;
2791 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2792 sizeof(**ppRefType
));
2794 name
+= SLTG_ReadStringA(name
, &refname
);
2795 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2796 FIXME("Can't sscanf ref\n");
2797 if(lib_offs
!= 0xffff) {
2798 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2801 if((*import
)->offset
== lib_offs
)
2803 import
= &(*import
)->next
;
2806 char fname
[MAX_PATH
+1];
2809 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2811 (*import
)->offset
= lib_offs
;
2812 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2814 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
2815 &(*import
)->wVersionMajor
,
2816 &(*import
)->wVersionMinor
,
2817 &(*import
)->lcid
, fname
) != 4) {
2818 FIXME("can't sscanf ref %s\n",
2819 pNameTable
+ lib_offs
+ 40);
2821 len
= strlen(fname
);
2822 if(fname
[len
-1] != '#')
2823 FIXME("fname = %s\n", fname
);
2824 fname
[len
-1] = '\0';
2825 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2827 (*ppRefType
)->pImpTLInfo
= *import
;
2828 } else { /* internal ref */
2829 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2831 (*ppRefType
)->reference
= ref
;
2832 (*ppRefType
)->index
= type_num
;
2834 HeapFree(GetProcessHeap(), 0, refname
);
2835 ppRefType
= &(*ppRefType
)->next
;
2837 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2838 FIXME("End of ref block magic = %x\n", *name
);
2839 dump_TLBRefType(pTI
->reflist
);
2842 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2845 SLTG_ImplInfo
*info
;
2846 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2847 /* I don't really get this structure, usually it's 0x16 bytes
2848 long, but iuser.tlb contains some that are 0x18 bytes long.
2849 That's ok because we can use the next ptr to jump to the next
2850 one. But how do we know the length of the last one? The WORD
2851 at offs 0x8 might be the clue. For now I'm just assuming that
2852 the last one is the regular 0x16 bytes. */
2854 info
= (SLTG_ImplInfo
*)pBlk
;
2856 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2857 sizeof(**ppImplType
));
2858 (*ppImplType
)->hRef
= info
->ref
;
2859 (*ppImplType
)->implflags
= info
->impltypeflags
;
2860 pTI
->TypeAttr
.cImplTypes
++;
2861 ppImplType
= &(*ppImplType
)->next
;
2863 if(info
->next
== 0xffff)
2866 FIXME("Interface inheriting more than one interface\n");
2867 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2869 info
++; /* see comment at top of function */
2873 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
, char *pNameTable
)
2875 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2876 BSTR bstrPrevName
= NULL
;
2877 SLTG_Variable
*pItem
;
2882 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
2883 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++) {
2885 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2886 sizeof(**ppVarDesc
));
2887 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2889 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
2890 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
2891 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
2895 if (pItem
->name
== 0xfffe)
2896 (*ppVarDesc
)->Name
= SysAllocString(bstrPrevName
);
2898 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2900 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
2901 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
2903 if (pItem
->flags
& 0x40) {
2904 TRACE_(typelib
)("VAR_DISPATCH\n");
2905 (*ppVarDesc
)->vardesc
.varkind
= VAR_DISPATCH
;
2907 else if (pItem
->flags
& 0x10) {
2908 TRACE_(typelib
)("VAR_CONST\n");
2909 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2910 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2912 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2913 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2914 *(INT
*)(pBlk
+ pItem
->byte_offs
);
2917 TRACE_(typelib
)("VAR_PERINSTANCE\n");
2918 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2919 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2922 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
2923 (*ppVarDesc
)->vardesc
.wVarFlags
= pItem
->varflags
;
2925 if (pItem
->flags
& 0x80)
2926 (*ppVarDesc
)->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
2928 if(pItem
->flags
& 0x02)
2929 pType
= &pItem
->type
;
2931 pType
= (WORD
*)(pBlk
+ pItem
->type
);
2933 if (pItem
->flags
& ~0xd2)
2934 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xd2);
2936 SLTG_DoElem(pType
, pBlk
,
2937 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2939 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2941 bstrPrevName
= (*ppVarDesc
)->Name
;
2942 ppVarDesc
= &((*ppVarDesc
)->next
);
2944 pTI
->TypeAttr
.cVars
= cVars
;
2947 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cFuncs
, char *pNameTable
)
2949 SLTG_Function
*pFunc
;
2951 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2953 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
;
2954 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++) {
2959 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2960 sizeof(**ppFuncDesc
));
2962 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
2963 case SLTG_FUNCTION_MAGIC
:
2964 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
2966 case SLTG_DISPATCH_FUNCTION_MAGIC
:
2967 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_DISPATCH
;
2969 case SLTG_STATIC_FUNCTION_MAGIC
:
2970 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_STATIC
;
2973 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
2974 HeapFree(GetProcessHeap(), 0, *ppFuncDesc
);
2978 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2980 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2981 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2982 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2983 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2984 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2985 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2987 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
2988 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2990 if(pFunc
->retnextopt
& 0x80)
2991 pType
= &pFunc
->rettype
;
2993 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
2995 SLTG_DoElem(pType
, pBlk
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2997 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2998 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2999 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
3000 (*ppFuncDesc
)->pParamDesc
=
3001 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3002 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
3004 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3006 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
3007 char *paramName
= pNameTable
+ *pArg
;
3009 /* If arg type follows then paramName points to the 2nd
3010 letter of the name, else the next WORD is an offset to
3011 the arg type and paramName points to the first letter.
3012 So let's take one char off paramName and see if we're
3013 pointing at an alpha-numeric char. However if *pArg is
3014 0xffff or 0xfffe then the param has no name, the former
3015 meaning that the next WORD is the type, the latter
3016 meaning the the next WORD is an offset to the type. */
3021 else if(*pArg
== 0xfffe) {
3025 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3030 if(HaveOffs
) { /* the next word is an offset to type */
3031 pType
= (WORD
*)(pBlk
+ *pArg
);
3032 SLTG_DoElem(pType
, pBlk
,
3033 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
3038 pArg
= SLTG_DoElem(pArg
, pBlk
,
3039 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
3042 /* Are we an optional param ? */
3043 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
3044 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
3045 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3048 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
3049 TLB_MultiByteToBSTR(paramName
);
3053 ppFuncDesc
= &((*ppFuncDesc
)->next
);
3054 if(pFunc
->next
== 0xffff) break;
3056 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3059 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3060 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3061 SLTG_TypeInfoTail
*pTITail
)
3063 char *pFirstItem
, *pNextItem
;
3065 if(pTIHeader
->href_table
!= 0xffffffff) {
3066 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3070 pFirstItem
= pNextItem
= pBlk
;
3072 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3073 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
3078 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3079 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3080 SLTG_TypeInfoTail
*pTITail
)
3082 char *pFirstItem
, *pNextItem
;
3084 if(pTIHeader
->href_table
!= 0xffffffff) {
3085 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3089 pFirstItem
= pNextItem
= pBlk
;
3091 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3092 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
3095 if (pTITail
->funcs_off
!= 0xffff)
3096 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3098 if (TRACE_ON(typelib
))
3099 dump_TLBFuncDesc(pTI
->funclist
);
3102 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3103 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3104 SLTG_TypeInfoTail
*pTITail
)
3106 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3109 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3110 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3111 SLTG_TypeInfoTail
*pTITail
)
3115 if (pTITail
->simple_alias
) {
3116 /* if simple alias, no more processing required */
3117 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3121 if(pTIHeader
->href_table
!= 0xffffffff) {
3122 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3126 /* otherwise it is an offset to a type */
3127 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3129 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
);
3132 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3133 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3134 SLTG_TypeInfoTail
*pTITail
)
3136 if (pTIHeader
->href_table
!= 0xffffffff)
3137 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3140 if (pTITail
->vars_off
!= 0xffff)
3141 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3143 if (pTITail
->funcs_off
!= 0xffff)
3144 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3146 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3147 * of dispinterface functons including the IDispatch ones, so
3148 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3149 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3151 if (TRACE_ON(typelib
))
3152 dump_TLBFuncDesc(pTI
->funclist
);
3155 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3156 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3157 SLTG_TypeInfoTail
*pTITail
)
3159 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3162 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3163 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3164 SLTG_TypeInfoTail
*pTITail
)
3166 if (pTIHeader
->href_table
!= 0xffffffff)
3167 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3170 if (pTITail
->vars_off
!= 0xffff)
3171 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3173 if (pTITail
->funcs_off
!= 0xffff)
3174 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3177 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3178 managable copy of it into this */
3191 } SLTG_InternalOtherTypeInfo
;
3193 /****************************************************************************
3194 * ITypeLib2_Constructor_SLTG
3196 * loading a SLTG typelib from an in-memory image
3198 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3200 ITypeLibImpl
*pTypeLibImpl
;
3201 SLTG_Header
*pHeader
;
3202 SLTG_BlkEntry
*pBlkEntry
;
3206 LPVOID pBlk
, pFirstBlk
;
3207 SLTG_LibBlk
*pLibBlk
;
3208 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3209 char *pAfterOTIBlks
= NULL
;
3210 char *pNameTable
, *ptr
;
3213 ITypeInfoImpl
**ppTypeInfoImpl
;
3215 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3218 pTypeLibImpl
= TypeLibImpl_Constructor();
3219 if (!pTypeLibImpl
) return NULL
;
3223 TRACE_(typelib
)("header:\n");
3224 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3225 pHeader
->nrOfFileBlks
);
3226 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3227 FIXME("Header type magic 0x%08x not supported.\n",
3228 pHeader
->SLTG_magic
);
3232 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3233 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3235 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3236 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3238 /* Next we have a magic block */
3239 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3241 /* Let's see if we're still in sync */
3242 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3243 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3244 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3247 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3248 sizeof(SLTG_DIR_MAGIC
))) {
3249 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3253 pIndex
= (SLTG_Index
*)(pMagic
+1);
3255 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3257 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3259 /* We'll set up a ptr to the main library block, which is the last one. */
3261 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3262 pBlkEntry
[order
].next
!= 0;
3263 order
= pBlkEntry
[order
].next
- 1, i
++) {
3264 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3268 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3270 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3275 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3277 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3278 sizeof(*pOtherTypeInfoBlks
) *
3279 pTypeLibImpl
->TypeInfoCount
);
3282 ptr
= (char*)pLibBlk
+ len
;
3284 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3288 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3290 w
= *(WORD
*)(ptr
+ 2);
3293 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3295 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3296 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3298 w
= *(WORD
*)(ptr
+ 4 + len
);
3300 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3302 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3304 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3305 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3307 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3308 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3309 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3311 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3313 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3316 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3317 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3318 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3319 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3320 len
+= sizeof(SLTG_OtherTypeInfo
);
3324 pAfterOTIBlks
= ptr
;
3326 /* Skip this WORD and get the next DWORD */
3327 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3329 /* Now add this to pLibBLk look at what we're pointing at and
3330 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3331 dust and we should be pointing at the beginning of the name
3334 pNameTable
= (char*)pLibBlk
+ len
;
3336 switch(*(WORD
*)pNameTable
) {
3343 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3347 pNameTable
+= 0x216;
3351 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3353 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3356 /* Hopefully we now have enough ptrs set up to actually read in
3357 some TypeInfos. It's not clear which order to do them in, so
3358 I'll just follow the links along the BlkEntry chain and read
3359 them in the order in which they are in the file */
3361 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3363 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3364 pBlkEntry
[order
].next
!= 0;
3365 order
= pBlkEntry
[order
].next
- 1, i
++) {
3367 SLTG_TypeInfoHeader
*pTIHeader
;
3368 SLTG_TypeInfoTail
*pTITail
;
3369 SLTG_MemberHeader
*pMemHeader
;
3371 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3372 pOtherTypeInfoBlks
[i
].index_name
)) {
3373 FIXME("Index strings don't match\n");
3378 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3379 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3382 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3383 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
3385 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3386 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3387 (*ppTypeInfoImpl
)->index
= i
;
3388 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3389 pOtherTypeInfoBlks
[i
].name_offs
+
3391 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3392 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3394 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3395 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3396 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3397 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3398 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3400 if((pTIHeader
->typeflags1
& 7) != 2)
3401 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3402 if(pTIHeader
->typeflags3
!= 2)
3403 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3405 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3406 debugstr_w((*ppTypeInfoImpl
)->Name
),
3407 typekind_desc
[pTIHeader
->typekind
],
3408 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3409 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3411 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
3413 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
3415 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3416 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3417 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3419 switch(pTIHeader
->typekind
) {
3421 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3422 pTIHeader
, pTITail
);
3426 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3427 pTIHeader
, pTITail
);
3430 case TKIND_INTERFACE
:
3431 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3432 pTIHeader
, pTITail
);
3436 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3437 pTIHeader
, pTITail
);
3441 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3442 pTIHeader
, pTITail
);
3445 case TKIND_DISPATCH
:
3446 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3447 pTIHeader
, pTITail
);
3451 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3452 pTIHeader
, pTITail
);
3456 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3461 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3462 but we've already set those */
3463 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3478 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3479 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3482 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3483 FIXME("Somehow processed %d TypeInfos\n", i
);
3487 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3488 return (ITypeLib2
*)pTypeLibImpl
;
3491 /* ITypeLib::QueryInterface
3493 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3498 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3500 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3503 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3504 IsEqualIID(riid
,&IID_ITypeLib
)||
3505 IsEqualIID(riid
,&IID_ITypeLib2
))
3512 ITypeLib2_AddRef(iface
);
3513 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3516 TRACE("-- Interface: E_NOINTERFACE\n");
3517 return E_NOINTERFACE
;
3522 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3524 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3525 ULONG ref
= InterlockedIncrement(&This
->ref
);
3527 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
3532 /* ITypeLib::Release
3534 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3536 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3537 ULONG ref
= InterlockedDecrement(&This
->ref
);
3539 TRACE("(%p)->(%u)\n",This
, ref
);
3543 TLBImpLib
*pImpLib
, *pImpLibNext
;
3544 TLBCustData
*pCustData
, *pCustDataNext
;
3546 /* remove cache entry */
3549 TRACE("removing from cache list\n");
3550 EnterCriticalSection(&cache_section
);
3551 if (This
->next
) This
->next
->prev
= This
->prev
;
3552 if (This
->prev
) This
->prev
->next
= This
->next
;
3553 else tlb_cache_first
= This
->next
;
3554 LeaveCriticalSection(&cache_section
);
3555 HeapFree(GetProcessHeap(), 0, This
->path
);
3557 TRACE(" destroying ITypeLib(%p)\n",This
);
3561 SysFreeString(This
->Name
);
3565 if (This
->DocString
)
3567 SysFreeString(This
->DocString
);
3568 This
->DocString
= NULL
;
3573 SysFreeString(This
->HelpFile
);
3574 This
->HelpFile
= NULL
;
3577 if (This
->HelpStringDll
)
3579 SysFreeString(This
->HelpStringDll
);
3580 This
->HelpStringDll
= NULL
;
3583 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
3585 VariantClear(&pCustData
->data
);
3587 pCustDataNext
= pCustData
->next
;
3588 TLB_Free(pCustData
);
3591 /* FIXME: free arrays inside elements of This->pTypeDesc */
3592 TLB_Free(This
->pTypeDesc
);
3594 for (pImpLib
= This
->pImpLibs
; pImpLib
; pImpLib
= pImpLibNext
)
3596 if (pImpLib
->pImpTypeLib
)
3597 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
3598 TLB_Free(pImpLib
->name
);
3600 pImpLibNext
= pImpLib
->next
;
3604 if (This
->pTypeInfo
) /* can be NULL */
3605 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3606 HeapFree(GetProcessHeap(),0,This
);
3613 /* ITypeLib::GetTypeInfoCount
3615 * Returns the number of type descriptions in the type library
3617 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3619 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3620 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3621 return This
->TypeInfoCount
;
3624 /* ITypeLib::GetTypeInfo
3626 * retrieves the specified type description in the library.
3628 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3631 ITypeInfo
**ppTInfo
)
3635 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3636 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3638 TRACE("(%p)->(index=%d)\n", This
, index
);
3640 if (!ppTInfo
) return E_INVALIDARG
;
3642 /* search element n in list */
3643 for(i
=0; i
< index
; i
++)
3645 pTypeInfo
= pTypeInfo
->next
;
3648 TRACE("-- element not found\n");
3649 return TYPE_E_ELEMENTNOTFOUND
;
3653 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3655 ITypeInfo_AddRef(*ppTInfo
);
3656 TRACE("-- found (%p)\n",*ppTInfo
);
3661 /* ITypeLibs::GetTypeInfoType
3663 * Retrieves the type of a type description.
3665 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3670 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3672 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3674 if ((ITypeLib2_fnGetTypeInfoCount(iface
) < index
+ 1) || (index
< 0))
3675 return TYPE_E_ELEMENTNOTFOUND
;
3677 TRACE("(%p) index %d\n", This
, index
);
3679 if(!pTKind
) return E_INVALIDARG
;
3681 /* search element n in list */
3682 for(i
=0; i
< index
; i
++)
3686 TRACE("-- element not found\n");
3687 return TYPE_E_ELEMENTNOTFOUND
;
3689 pTInfo
= pTInfo
->next
;
3692 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3693 TRACE("-- found Type (%d)\n", *pTKind
);
3697 /* ITypeLib::GetTypeInfoOfGuid
3699 * Retrieves the type description that corresponds to the specified GUID.
3702 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3705 ITypeInfo
**ppTInfo
)
3707 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3708 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3710 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3714 WARN("-- element not found\n");
3715 return TYPE_E_ELEMENTNOTFOUND
;
3718 /* search linked list for guid */
3719 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3721 pTypeInfo
= pTypeInfo
->next
;
3725 /* end of list reached */
3726 WARN("-- element not found\n");
3727 return TYPE_E_ELEMENTNOTFOUND
;
3731 TRACE("-- found (%p, %s)\n",
3733 debugstr_w(pTypeInfo
->Name
));
3735 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3736 ITypeInfo_AddRef(*ppTInfo
);
3740 /* ITypeLib::GetLibAttr
3742 * Retrieves the structure that contains the library's attributes.
3745 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3747 LPTLIBATTR
*ppTLibAttr
)
3749 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3750 TRACE("(%p)\n",This
);
3751 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3752 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3756 /* ITypeLib::GetTypeComp
3758 * Enables a client compiler to bind to a library's types, variables,
3759 * constants, and global functions.
3762 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3764 ITypeComp
**ppTComp
)
3766 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3768 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3769 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3770 ITypeComp_AddRef(*ppTComp
);
3775 /* ITypeLib::GetDocumentation
3777 * Retrieves the library's documentation string, the complete Help file name
3778 * and path, and the context identifier for the library Help topic in the Help
3781 * On a successful return all non-null BSTR pointers will have been set,
3784 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3788 BSTR
*pBstrDocString
,
3789 DWORD
*pdwHelpContext
,
3790 BSTR
*pBstrHelpFile
)
3792 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3794 HRESULT result
= E_INVALIDARG
;
3799 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3801 pBstrName
, pBstrDocString
,
3802 pdwHelpContext
, pBstrHelpFile
);
3806 /* documentation for the typelib */
3811 if(!(*pBstrName
= SysAllocString(This
->Name
)))
3819 if (This
->DocString
)
3821 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
3824 else if (This
->Name
)
3826 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
3830 *pBstrDocString
= NULL
;
3834 *pdwHelpContext
= This
->dwHelpContext
;
3840 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
3844 *pBstrHelpFile
= NULL
;
3851 /* for a typeinfo */
3852 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3854 if(SUCCEEDED(result
))
3856 result
= ITypeInfo_GetDocumentation(pTInfo
,
3860 pdwHelpContext
, pBstrHelpFile
);
3862 ITypeInfo_Release(pTInfo
);
3867 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3869 if (pBstrName
) SysFreeString (*pBstrName
);
3871 return STG_E_INSUFFICIENTMEMORY
;
3876 * Indicates whether a passed-in string contains the name of a type or member
3877 * described in the library.
3880 static HRESULT WINAPI
ITypeLib2_fnIsName(
3886 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3887 ITypeInfoImpl
*pTInfo
;
3888 TLBFuncDesc
*pFInfo
;
3891 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3893 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3897 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3898 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3899 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3900 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3901 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3902 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3903 goto ITypeLib2_fnIsName_exit
;
3905 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3906 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3911 ITypeLib2_fnIsName_exit
:
3912 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3913 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3918 /* ITypeLib::FindName
3920 * Finds occurrences of a type description in a type library. This may be used
3921 * to quickly verify that a name exists in a type library.
3924 static HRESULT WINAPI
ITypeLib2_fnFindName(
3928 ITypeInfo
**ppTInfo
,
3932 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3933 ITypeInfoImpl
*pTInfo
;
3934 TLBFuncDesc
*pFInfo
;
3937 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3939 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3940 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3941 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3942 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3943 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
3944 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3945 goto ITypeLib2_fnFindName_exit
;
3948 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3949 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3951 ITypeLib2_fnFindName_exit
:
3952 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3953 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3956 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3957 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3964 /* ITypeLib::ReleaseTLibAttr
3966 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3969 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3971 TLIBATTR
*pTLibAttr
)
3973 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3974 TRACE("freeing (%p)\n",This
);
3975 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3979 /* ITypeLib2::GetCustData
3981 * gets the custom data
3983 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3988 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3989 TLBCustData
*pCData
;
3991 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3993 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3996 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4000 VariantInit( pVarVal
);
4001 VariantCopy( pVarVal
, &pCData
->data
);
4004 return E_INVALIDARG
; /* FIXME: correct? */
4007 /* ITypeLib2::GetLibStatistics
4009 * Returns statistics about a type library that are required for efficient
4010 * sizing of hash tables.
4013 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4015 ULONG
*pcUniqueNames
,
4016 ULONG
*pcchUniqueNames
)
4018 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4020 FIXME("(%p): stub!\n", This
);
4022 if(pcUniqueNames
) *pcUniqueNames
=1;
4023 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4027 /* ITypeLib2::GetDocumentation2
4029 * Retrieves the library's documentation string, the complete Help file name
4030 * and path, the localization context to use, and the context ID for the
4031 * library Help topic in the Help file.
4034 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4038 BSTR
*pbstrHelpString
,
4039 DWORD
*pdwHelpStringContext
,
4040 BSTR
*pbstrHelpStringDll
)
4042 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4046 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4048 /* the help string should be obtained from the helpstringdll,
4049 * using the _DLLGetDocumentation function, based on the supplied
4050 * lcid. Nice to do sometime...
4054 /* documentation for the typelib */
4056 *pbstrHelpString
=SysAllocString(This
->DocString
);
4057 if(pdwHelpStringContext
)
4058 *pdwHelpStringContext
=This
->dwHelpContext
;
4059 if(pbstrHelpStringDll
)
4060 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4066 /* for a typeinfo */
4067 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4069 if(SUCCEEDED(result
))
4071 ITypeInfo2
* pTInfo2
;
4072 result
= ITypeInfo_QueryInterface(pTInfo
,
4074 (LPVOID
*) &pTInfo2
);
4076 if(SUCCEEDED(result
))
4078 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4082 pdwHelpStringContext
,
4083 pbstrHelpStringDll
);
4085 ITypeInfo2_Release(pTInfo2
);
4088 ITypeInfo_Release(pTInfo
);
4094 /* ITypeLib2::GetAllCustData
4096 * Gets all custom data items for the library.
4099 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4101 CUSTDATA
*pCustData
)
4103 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4104 TLBCustData
*pCData
;
4106 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4107 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4108 if(pCustData
->prgCustData
){
4109 pCustData
->cCustData
=This
->ctCustData
;
4110 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4111 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4112 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4115 ERR(" OUT OF MEMORY!\n");
4116 return E_OUTOFMEMORY
;
4121 static const ITypeLib2Vtbl tlbvt
= {
4122 ITypeLib2_fnQueryInterface
,
4124 ITypeLib2_fnRelease
,
4125 ITypeLib2_fnGetTypeInfoCount
,
4126 ITypeLib2_fnGetTypeInfo
,
4127 ITypeLib2_fnGetTypeInfoType
,
4128 ITypeLib2_fnGetTypeInfoOfGuid
,
4129 ITypeLib2_fnGetLibAttr
,
4130 ITypeLib2_fnGetTypeComp
,
4131 ITypeLib2_fnGetDocumentation
,
4133 ITypeLib2_fnFindName
,
4134 ITypeLib2_fnReleaseTLibAttr
,
4136 ITypeLib2_fnGetCustData
,
4137 ITypeLib2_fnGetLibStatistics
,
4138 ITypeLib2_fnGetDocumentation2
,
4139 ITypeLib2_fnGetAllCustData
4143 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4145 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4147 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4150 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4152 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4154 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4157 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4159 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4161 return ITypeLib2_Release((ITypeLib2
*)This
);
4164 static HRESULT WINAPI
ITypeLibComp_fnBind(
4169 ITypeInfo
** ppTInfo
,
4170 DESCKIND
* pDescKind
,
4173 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4174 ITypeInfoImpl
*pTypeInfo
;
4176 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4178 *pDescKind
= DESCKIND_NONE
;
4179 pBindPtr
->lptcomp
= NULL
;
4182 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4184 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4186 /* FIXME: check wFlags here? */
4187 /* FIXME: we should use a hash table to look this info up using lHash
4188 * instead of an O(n) search */
4189 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4190 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4192 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4194 *pDescKind
= DESCKIND_TYPECOMP
;
4195 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4196 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4197 TRACE("module or enum: %s\n", debugstr_w(szName
));
4202 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4203 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4205 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4208 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4209 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4211 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4216 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4217 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4219 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4221 ITypeInfo
*subtypeinfo
;
4223 DESCKIND subdesckind
;
4225 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4226 &subtypeinfo
, &subdesckind
, &subbindptr
);
4227 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4229 TYPEDESC tdesc_appobject
=
4232 (TYPEDESC
*)pTypeInfo
->hreftype
4236 const VARDESC vardesc_appobject
=
4239 NULL
, /* lpstrSchema */
4254 VAR_STATIC
/* varkind */
4257 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4259 /* cleanup things filled in by Bind call so we can put our
4260 * application object data in there instead */
4261 switch (subdesckind
)
4263 case DESCKIND_FUNCDESC
:
4264 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4266 case DESCKIND_VARDESC
:
4267 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4272 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4274 if (pTypeInfo
->hreftype
== -1)
4275 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4277 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4281 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4282 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4283 ITypeInfo_AddRef(*ppTInfo
);
4289 TRACE("name not found %s\n", debugstr_w(szName
));
4293 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4297 ITypeInfo
** ppTInfo
,
4298 ITypeComp
** ppTComp
)
4300 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4304 static const ITypeCompVtbl tlbtcvt
=
4307 ITypeLibComp_fnQueryInterface
,
4308 ITypeLibComp_fnAddRef
,
4309 ITypeLibComp_fnRelease
,
4311 ITypeLibComp_fnBind
,
4312 ITypeLibComp_fnBindType
4315 /*================== ITypeInfo(2) Methods ===================================*/
4316 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4318 ITypeInfoImpl
* pTypeInfoImpl
;
4320 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4323 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4324 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4325 pTypeInfoImpl
->ref
=1;
4326 pTypeInfoImpl
->hreftype
= -1;
4327 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
4328 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
4330 TRACE("(%p)\n", pTypeInfoImpl
);
4331 return (ITypeInfo2
*) pTypeInfoImpl
;
4334 /* ITypeInfo::QueryInterface
4336 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4341 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4343 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4346 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4347 IsEqualIID(riid
,&IID_ITypeInfo
)||
4348 IsEqualIID(riid
,&IID_ITypeInfo2
))
4352 ITypeInfo_AddRef(iface
);
4353 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4356 TRACE("-- Interface: E_NOINTERFACE\n");
4357 return E_NOINTERFACE
;
4360 /* ITypeInfo::AddRef
4362 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4364 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4365 ULONG ref
= InterlockedIncrement(&This
->ref
);
4367 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4369 TRACE("(%p)->ref is %u\n",This
, ref
);
4373 /* ITypeInfo::Release
4375 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4377 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4378 ULONG ref
= InterlockedDecrement(&This
->ref
);
4380 TRACE("(%p)->(%u)\n",This
, ref
);
4383 /* We don't release ITypeLib when ref=0 because
4384 it means that function is called by ITypeLib2_Release */
4385 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4387 TLBFuncDesc
*pFInfo
, *pFInfoNext
;
4388 TLBVarDesc
*pVInfo
, *pVInfoNext
;
4389 TLBImplType
*pImpl
, *pImplNext
;
4390 TLBRefType
*pRefType
,*pRefTypeNext
;
4391 TLBCustData
*pCustData
, *pCustDataNext
;
4393 TRACE("destroying ITypeInfo(%p)\n",This
);
4395 if (This
->no_free_data
)
4400 SysFreeString(This
->Name
);
4404 if (This
->DocString
)
4406 SysFreeString(This
->DocString
);
4407 This
->DocString
= 0;
4412 SysFreeString(This
->DllName
);
4416 for (pFInfo
= This
->funclist
; pFInfo
; pFInfo
= pFInfoNext
)
4419 for(i
= 0;i
< pFInfo
->funcdesc
.cParams
; i
++)
4421 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[i
];
4422 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4424 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4425 TLB_Free(elemdesc
->u
.paramdesc
.pparamdescex
);
4427 SysFreeString(pFInfo
->pParamDesc
[i
].Name
);
4429 TLB_Free(pFInfo
->funcdesc
.lprgelemdescParam
);
4430 TLB_Free(pFInfo
->pParamDesc
);
4431 for (pCustData
= This
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
4433 VariantClear(&pCustData
->data
);
4435 pCustDataNext
= pCustData
->next
;
4436 TLB_Free(pCustData
);
4438 SysFreeString(pFInfo
->Entry
);
4439 SysFreeString(pFInfo
->HelpString
);
4440 SysFreeString(pFInfo
->Name
);
4442 pFInfoNext
= pFInfo
->next
;
4445 for (pVInfo
= This
->varlist
; pVInfo
; pVInfo
= pVInfoNext
)
4447 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
4449 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
4450 TLB_Free(pVInfo
->vardesc
.u
.lpvarValue
);
4452 SysFreeString(pVInfo
->Name
);
4453 pVInfoNext
= pVInfo
->next
;
4456 for(pImpl
= This
->impltypelist
; pImpl
; pImpl
= pImplNext
)
4458 for (pCustData
= pImpl
->pCustData
; pCustData
; pCustData
= pCustDataNext
)
4460 VariantClear(&pCustData
->data
);
4462 pCustDataNext
= pCustData
->next
;
4463 TLB_Free(pCustData
);
4465 pImplNext
= pImpl
->next
;
4468 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefTypeNext
)
4470 pRefTypeNext
= pRefType
->next
;
4473 TLB_Free(This
->pCustData
);
4478 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4481 HeapFree(GetProcessHeap(),0,This
);
4487 /* ITypeInfo::GetTypeAttr
4489 * Retrieves a TYPEATTR structure that contains the attributes of the type
4493 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4494 LPTYPEATTR
*ppTypeAttr
)
4496 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4499 TRACE("(%p)\n",This
);
4501 size
= sizeof(**ppTypeAttr
);
4502 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4503 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
4505 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
4507 return E_OUTOFMEMORY
;
4509 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4511 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4512 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
4513 &This
->TypeAttr
.tdescAlias
, (void *)(*ppTypeAttr
+ 1));
4515 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
4516 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4518 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4519 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4524 /* ITypeInfo::GetTypeComp
4526 * Retrieves the ITypeComp interface for the type description, which enables a
4527 * client compiler to bind to the type description's members.
4530 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4531 ITypeComp
* *ppTComp
)
4533 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4535 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4537 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4538 ITypeComp_AddRef(*ppTComp
);
4542 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
4544 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
4545 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4546 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
4550 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
4552 memcpy(dest
, src
, sizeof(ELEMDESC
));
4553 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
4554 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4556 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
4557 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
4558 *buffer
+= sizeof(PARAMDESCEX
);
4559 memcpy(pparamdescex_dest
, pparamdescex_src
, sizeof(PARAMDESCEX
));
4560 VariantInit(&pparamdescex_dest
->varDefaultValue
);
4561 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
4562 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
4565 dest
->u
.paramdesc
.pparamdescex
= NULL
;
4569 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
4571 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4572 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4575 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
4579 SIZE_T size
= sizeof(*src
);
4583 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4584 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
4585 for (i
= 0; i
< src
->cParams
; i
++)
4587 size
+= sizeof(ELEMDESC
);
4588 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
4591 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
4592 if (!dest
) return E_OUTOFMEMORY
;
4594 memcpy(dest
, src
, sizeof(FUNCDESC
));
4595 buffer
= (char *)(dest
+ 1);
4597 dest
->lprgscode
= (SCODE
*)buffer
;
4598 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
4599 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4601 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
4604 SysFreeString((BSTR
)dest
);
4608 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
4609 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
4610 for (i
= 0; i
< src
->cParams
; i
++)
4612 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
4618 /* undo the above actions */
4619 for (i
= i
- 1; i
>= 0; i
--)
4620 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
4621 TLB_FreeElemDesc(&dest
->elemdescFunc
);
4622 SysFreeString((BSTR
)dest
);
4626 /* special treatment for dispinterfaces: this makes functions appear
4627 * to return their [retval] value when it is really returning an
4629 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
4631 if (dest
->cParams
&&
4632 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
4634 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
4635 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
4637 ERR("elemdesc should have started with VT_PTR instead of:\n");
4639 dump_ELEMDESC(elemdesc
);
4640 return E_UNEXPECTED
;
4643 /* copy last parameter to the return value. we are using a flat
4644 * buffer so there is no danger of leaking memory in
4646 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
4648 /* remove the last parameter */
4652 /* otherwise this function is made to appear to have no return
4654 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
4662 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
4664 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4665 const TLBFuncDesc
*pFDesc
;
4668 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4673 *ppFuncDesc
= &pFDesc
->funcdesc
;
4677 return E_INVALIDARG
;
4680 /* internal function to make the inherited interfaces' methods appear
4681 * part of the interface */
4682 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
4683 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
)
4685 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4688 UINT implemented_funcs
= 0;
4693 for (i
= 0; i
< This
->TypeAttr
.cImplTypes
; i
++)
4696 ITypeInfo
*pSubTypeInfo
;
4699 hr
= ITypeInfo_GetRefTypeOfImplType(iface
, i
, &href
);
4702 hr
= ITypeInfo_GetRefTypeInfo(iface
, href
, &pSubTypeInfo
);
4706 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
4710 implemented_funcs
+= sub_funcs
;
4711 ITypeInfo_Release(pSubTypeInfo
);
4717 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
4719 if (index
< implemented_funcs
)
4720 return E_INVALIDARG
;
4721 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
4725 /* ITypeInfo::GetFuncDesc
4727 * Retrieves the FUNCDESC structure that contains information about a
4728 * specified function.
4731 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4732 LPFUNCDESC
*ppFuncDesc
)
4734 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4735 const FUNCDESC
*internal_funcdesc
;
4738 TRACE("(%p) index %d\n", This
, index
);
4740 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
4741 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
4742 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
4743 &internal_funcdesc
, NULL
);
4745 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
4746 &internal_funcdesc
);
4749 WARN("description for function %d not found\n", index
);
4753 return TLB_AllocAndInitFuncDesc(
4756 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
4759 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
4763 SIZE_T size
= sizeof(*src
);
4766 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
4767 if (src
->varkind
== VAR_CONST
)
4768 size
+= sizeof(VARIANT
);
4769 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
4771 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
4772 if (!dest
) return E_OUTOFMEMORY
;
4775 buffer
= (char *)(dest
+ 1);
4776 if (src
->lpstrSchema
)
4779 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
4780 len
= strlenW(src
->lpstrSchema
);
4781 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
4782 buffer
+= (len
+ 1) * sizeof(WCHAR
);
4785 if (src
->varkind
== VAR_CONST
)
4789 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
4790 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
4791 buffer
+= sizeof(VARIANT
);
4792 VariantInit(dest
->u
.lpvarValue
);
4793 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
4796 SysFreeString((BSTR
)dest_ptr
);
4800 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
4803 if (src
->varkind
== VAR_CONST
)
4804 VariantClear(dest
->u
.lpvarValue
);
4805 SysFreeString((BSTR
)dest
);
4812 /* ITypeInfo::GetVarDesc
4814 * Retrieves a VARDESC structure that describes the specified variable.
4817 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4818 LPVARDESC
*ppVarDesc
)
4820 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4822 const TLBVarDesc
*pVDesc
;
4824 TRACE("(%p) index %d\n", This
, index
);
4826 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4830 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
4832 return E_INVALIDARG
;
4835 /* ITypeInfo_GetNames
4837 * Retrieves the variable with the specified member ID (or the name of the
4838 * property or method and its parameters) that correspond to the specified
4841 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4842 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4844 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4845 const TLBFuncDesc
*pFDesc
;
4846 const TLBVarDesc
*pVDesc
;
4848 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
4849 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4852 /* function found, now return function and parameter names */
4853 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4856 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4858 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4864 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4867 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4872 if(This
->TypeAttr
.cImplTypes
&&
4873 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4874 /* recursive search */
4877 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4879 if(SUCCEEDED(result
))
4881 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4882 ITypeInfo_Release(pTInfo
);
4885 WARN("Could not search inherited interface!\n");
4889 WARN("no names found\n");
4892 return TYPE_E_ELEMENTNOTFOUND
;
4899 /* ITypeInfo::GetRefTypeOfImplType
4901 * If a type description describes a COM class, it retrieves the type
4902 * description of the implemented interface types. For an interface,
4903 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4907 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4912 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4915 const TLBImplType
*pImpl
= This
->impltypelist
;
4917 TRACE("(%p) index %d\n", This
, index
);
4918 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4922 /* only valid on dual interfaces;
4923 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4925 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4927 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4928 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4934 hr
= TYPE_E_ELEMENTNOTFOUND
;
4939 /* get element n from linked list */
4940 for(i
=0; pImpl
&& i
<index
; i
++)
4942 pImpl
= pImpl
->next
;
4946 *pRefType
= pImpl
->hRef
;
4948 hr
= TYPE_E_ELEMENTNOTFOUND
;
4954 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
4956 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
4962 /* ITypeInfo::GetImplTypeFlags
4964 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4965 * or base interface in a type description.
4967 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4968 UINT index
, INT
*pImplTypeFlags
)
4970 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4974 TRACE("(%p) index %d\n", This
, index
);
4975 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4976 i
++, pImpl
=pImpl
->next
)
4978 if(i
==index
&& pImpl
){
4979 *pImplTypeFlags
=pImpl
->implflags
;
4983 return TYPE_E_ELEMENTNOTFOUND
;
4987 * Maps between member names and member IDs, and parameter names and
4990 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4991 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4993 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4994 const TLBFuncDesc
*pFDesc
;
4995 const TLBVarDesc
*pVDesc
;
4999 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5002 /* init out parameters in case of failure */
5003 for (i
= 0; i
< cNames
; i
++)
5004 pMemId
[i
] = MEMBERID_NIL
;
5006 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
5008 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5009 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5010 for(i
=1; i
< cNames
; i
++){
5011 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5012 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5014 if( j
<pFDesc
->funcdesc
.cParams
)
5017 ret
=DISP_E_UNKNOWNNAME
;
5019 TRACE("-- 0x%08x\n", ret
);
5023 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
5024 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
5025 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
5029 /* not found, see if it can be found in an inherited interface */
5030 if(This
->TypeAttr
.cImplTypes
) {
5031 /* recursive search */
5033 ret
=ITypeInfo_GetRefTypeInfo(iface
,
5034 This
->impltypelist
->hRef
, &pTInfo
);
5036 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5037 ITypeInfo_Release(pTInfo
);
5040 WARN("Could not search inherited interface!\n");
5042 WARN("no names found\n");
5043 return DISP_E_UNKNOWNNAME
;
5046 /* ITypeInfo::Invoke
5048 * Invokes a method, or accesses a property of an object, that implements the
5049 * interface described by the type description.
5052 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5055 if (TRACE_ON(ole
)) {
5057 TRACE("Calling %p(",func
);
5058 for (i
=0;i
<nrargs
;i
++) TRACE("%08x,",args
[i
]);
5070 res
= func(args
[0]);
5073 res
= func(args
[0],args
[1]);
5076 res
= func(args
[0],args
[1],args
[2]);
5079 res
= func(args
[0],args
[1],args
[2],args
[3]);
5082 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
5085 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
5088 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
5091 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
5094 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
5097 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
5100 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
5103 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]);
5106 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]);
5109 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]);
5112 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]);
5115 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]);
5118 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]);
5121 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]);
5124 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]);
5127 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]);
5130 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]);
5133 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]);
5136 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]);
5139 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
5145 FIXME("unsupported calling convention %d\n",callconv
);
5149 TRACE("returns %08x\n",res
);
5153 extern int _argsize(DWORD vt
);
5155 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5158 ITypeInfo
*tinfo2
= NULL
;
5159 TYPEATTR
*tattr
= NULL
;
5161 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5164 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5166 tdesc
->u
.hreftype
, hr
);
5169 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5172 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5173 ITypeInfo_Release(tinfo2
);
5177 switch (tattr
->typekind
)
5184 tdesc
= &tattr
->tdescAlias
;
5185 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5188 case TKIND_INTERFACE
:
5189 if (IsEqualIID(&IID_IDispatch
, &tattr
->guid
))
5195 case TKIND_DISPATCH
:
5204 FIXME("TKIND_RECORD unhandled.\n");
5209 FIXME("TKIND_UNION unhandled.\n");
5214 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5218 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5219 ITypeInfo_Release(tinfo2
);
5223 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5227 /* enforce only one level of pointer indirection */
5228 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5230 tdesc
= tdesc
->u
.lptdesc
;
5232 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5233 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5234 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5235 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5236 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5238 VARTYPE vt_userdefined
= 0;
5239 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5240 if (tdesc
->vt
== VT_PTR
)
5242 vt_userdefined
= VT_BYREF
;
5243 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5245 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5247 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5248 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5250 *vt
|= vt_userdefined
;
5262 case VT_USERDEFINED
:
5263 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5270 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5271 hr
= DISP_E_BADVARTYPE
;
5275 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
5284 /***********************************************************************
5285 * DispCallFunc (OLEAUT32.@)
5287 * Invokes a function of the specifed calling convention, passing the
5288 * specified arguments and returns the result.
5291 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5292 * oVft [I] The offset in the vtable. See notes.
5293 * cc [I] Calling convention of the function to call.
5294 * vtReturn [I] The return type of the function.
5295 * cActuals [I] Number of parameters.
5296 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5297 * prgpvarg [I] The arguments to pass.
5298 * pvargResult [O] The return value of the function. Can be NULL.
5302 * Failure: HRESULT code.
5305 * The HRESULT return value of this function is not affected by the return
5306 * value of the user supplied function, which is returned in pvargResult.
5308 * If pvInstance is NULL then a non-object function is to be called and oVft
5309 * is the address of the function to call.
5311 * The cc parameter can be one of the following values:
5324 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
5325 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
5327 int i
, argsize
, argspos
;
5331 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5332 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
5333 pvargResult
, V_VT(pvargResult
));
5337 argsize
++; /* for This pointer */
5339 for (i
=0;i
<cActuals
;i
++)
5341 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
5342 dump_Variant(prgpvarg
[i
]);
5343 argsize
+= _argsize(prgvt
[i
]);
5345 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
5350 args
[0] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
5354 for (i
=0;i
<cActuals
;i
++)
5356 VARIANT
*arg
= prgpvarg
[i
];
5357 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
5358 if (prgvt
[i
] == VT_VARIANT
)
5359 memcpy(&args
[argspos
], arg
, _argsize(prgvt
[i
]) * sizeof(DWORD
));
5361 memcpy(&args
[argspos
], &V_NONE(arg
), _argsize(prgvt
[i
]) * sizeof(DWORD
));
5362 argspos
+= _argsize(prgvt
[i
]);
5367 FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
5368 hres
= _invoke(vtable
[oVft
/sizeof(void *)], cc
, argsize
, args
);
5371 /* if we aren't invoking an object then the function pointer is stored
5373 hres
= _invoke((FARPROC
)oVft
, cc
, argsize
, args
);
5375 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
5377 TRACE("Method returned 0x%08x\n",hres
);
5378 V_VT(pvargResult
) = vtReturn
;
5379 V_UI4(pvargResult
) = hres
;
5382 HeapFree(GetProcessHeap(),0,args
);
5386 #define INVBUF_ELEMENT_SIZE \
5387 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5388 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5389 ((VARIANTARG *)(buffer))
5390 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5391 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5392 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5393 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5394 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5395 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5397 static HRESULT WINAPI
ITypeInfo_fnInvoke(
5402 DISPPARAMS
*pDispParams
,
5403 VARIANT
*pVarResult
,
5404 EXCEPINFO
*pExcepInfo
,
5407 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5409 unsigned int var_index
;
5412 const TLBFuncDesc
*pFuncInfo
;
5414 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5415 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
5420 ERR("NULL pDispParams not allowed\n");
5421 return E_INVALIDARG
;
5424 dump_DispParms(pDispParams
);
5426 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
5428 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5429 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
5430 return E_INVALIDARG
;
5433 /* we do this instead of using GetFuncDesc since it will return a fake
5434 * FUNCDESC for dispinterfaces and we want the real function description */
5435 for (pFuncInfo
= This
->funclist
; pFuncInfo
; pFuncInfo
=pFuncInfo
->next
)
5436 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
5437 (wFlags
& pFuncInfo
->funcdesc
.invkind
))
5441 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
5445 TRACE("invoking:\n");
5446 dump_TLBFuncDescOne(pFuncInfo
);
5449 switch (func_desc
->funckind
) {
5450 case FUNC_PUREVIRTUAL
:
5451 case FUNC_VIRTUAL
: {
5452 void *buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
5454 VARIANT retval
; /* pointer for storing byref retvals in */
5455 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
5456 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
5457 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
5460 for (i
= 0; i
< func_desc
->cParams
; i
++)
5462 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
5463 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
5468 TRACE("changing args\n");
5469 for (i
= 0; i
< func_desc
->cParams
; i
++)
5471 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5473 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5475 /* note: this check is placed so that if the caller passes
5476 * in a VARIANTARG for the retval we just ignore it, like
5478 if (i
== func_desc
->cParams
- 1)
5481 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5482 memset(arg
, 0, sizeof(*arg
));
5483 V_VT(arg
) = rgvt
[i
];
5484 memset(&retval
, 0, sizeof(retval
));
5485 V_BYREF(arg
) = &retval
;
5489 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
5490 hres
= E_UNEXPECTED
;
5494 else if (i
< pDispParams
->cArgs
)
5496 VARIANTARG
*src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
];
5497 dump_Variant(src_arg
);
5499 if (rgvt
[i
] == VT_VARIANT
)
5500 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
5501 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
5503 if (rgvt
[i
] == V_VT(src_arg
))
5504 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
5507 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5508 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
5509 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
5511 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5513 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
5515 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5516 V_VT(&missing_arg
[i
]) = V_VT(src_arg
);
5517 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
5518 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
5519 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5521 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
5523 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
5524 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5528 /* FIXME: this doesn't work for VT_BYREF arguments if
5529 * they are not the same type as in the paramdesc */
5530 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
5531 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
5532 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5537 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
5538 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
5539 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
5542 prgpvarg
[i
] = &rgvarg
[i
];
5544 else if (wParamFlags
& PARAMFLAG_FOPT
)
5547 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5548 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5550 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
5556 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5557 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
5558 V_VARIANTREF(arg
) = &missing_arg
[i
];
5559 V_VT(V_VARIANTREF(arg
)) = VT_ERROR
;
5560 V_ERROR(V_VARIANTREF(arg
)) = DISP_E_PARAMNOTFOUND
;
5565 hres
= DISP_E_BADPARAMCOUNT
;
5569 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5570 if (func_desc
->cParamsOpt
< 0)
5572 FIXME("Does not support safearray optional parameters\n");
5573 hres
= DISP_E_BADPARAMCOUNT
;
5574 goto func_fail
; /* FIXME: we don't free changed types here */
5577 /* VT_VOID is a special case for return types, so it is not
5578 * handled in the general function */
5579 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
5580 V_VT(&varresult
) = VT_EMPTY
;
5583 V_VT(&varresult
) = 0;
5584 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
5585 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5588 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
5589 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
5590 prgpvarg
, &varresult
);
5592 for (i
= 0; i
< func_desc
->cParams
; i
++)
5594 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5595 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5599 TRACE("[retval] value: ");
5600 dump_Variant(prgpvarg
[i
]);
5605 VariantInit(pVarResult
);
5606 /* deref return value */
5607 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
5610 /* free data stored in varresult. Note that
5611 * VariantClear doesn't do what we want because we are
5612 * working with byref types. */
5613 /* FIXME: clear safearrays, bstrs, records and
5614 * variants here too */
5615 if ((V_VT(prgpvarg
[i
]) == (VT_UNKNOWN
| VT_BYREF
)) ||
5616 (V_VT(prgpvarg
[i
]) == (VT_DISPATCH
| VT_BYREF
)))
5618 if(*V_UNKNOWNREF(prgpvarg
[i
]))
5619 IUnknown_Release(*V_UNKNOWNREF(prgpvarg
[i
]));
5623 else if (i
< pDispParams
->cArgs
)
5625 if (wParamFlags
& PARAMFLAG_FOUT
)
5627 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
];
5629 if ((rgvt
[i
] == VT_BYREF
) && (V_VT(arg
) != VT_BYREF
))
5630 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
5634 ERR("failed to convert param %d to vt %d\n", i
,
5635 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
]));
5639 VariantClear(&rgvarg
[i
]);
5641 else if (wParamFlags
& PARAMFLAG_FOPT
)
5643 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5644 VariantClear(&rgvarg
[i
]);
5648 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
5650 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
5651 hres
= DISP_E_EXCEPTION
;
5652 if (pExcepInfo
) pExcepInfo
->scode
= V_ERROR(&varresult
);
5656 HeapFree(GetProcessHeap(), 0, buffer
);
5659 case FUNC_DISPATCH
: {
5662 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
5663 if (SUCCEEDED(hres
)) {
5664 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5665 hres
= IDispatch_Invoke(
5666 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
5667 pVarResult
,pExcepInfo
,pArgErr
5670 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
5671 IDispatch_Release(disp
);
5673 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5677 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
5682 TRACE("-- 0x%08x\n", hres
);
5685 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
5688 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
5689 if(FAILED(hres
)) return hres
;
5691 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5692 dump_VARDESC(var_desc
);
5693 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
5697 /* not found, look for it in inherited interfaces */
5698 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
5699 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
5701 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface
, 0, &ref_type
))) {
5702 /* recursive search */
5704 hres
= ITypeInfo_GetRefTypeInfo(iface
, ref_type
, &pTInfo
);
5705 if(SUCCEEDED(hres
)){
5706 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
5707 ITypeInfo_Release(pTInfo
);
5710 WARN("Could not search inherited interface!\n");
5713 ERR("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
5714 return DISP_E_MEMBERNOTFOUND
;
5717 /* ITypeInfo::GetDocumentation
5719 * Retrieves the documentation string, the complete Help file name and path,
5720 * and the context ID for the Help topic for a specified type description.
5722 * (Can be tested by the Visual Basic Editor in Word for instance.)
5724 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
5725 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
5726 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
5728 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5729 const TLBFuncDesc
*pFDesc
;
5730 const TLBVarDesc
*pVDesc
;
5731 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5732 " HelpContext(%p) HelpFile(%p)\n",
5733 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
5734 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5736 *pBstrName
=SysAllocString(This
->Name
);
5738 *pBstrDocString
=SysAllocString(This
->DocString
);
5740 *pdwHelpContext
=This
->dwHelpContext
;
5742 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
5744 }else {/* for a member */
5745 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5746 if(pFDesc
->funcdesc
.memid
==memid
){
5748 *pBstrName
= SysAllocString(pFDesc
->Name
);
5750 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
5752 *pdwHelpContext
=pFDesc
->helpcontext
;
5755 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5756 if(pVDesc
->vardesc
.memid
==memid
){
5758 *pBstrName
= SysAllocString(pVDesc
->Name
);
5760 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
5762 *pdwHelpContext
=pVDesc
->HelpContext
;
5767 if(This
->TypeAttr
.cImplTypes
&&
5768 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5769 /* recursive search */
5772 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
5774 if(SUCCEEDED(result
)) {
5775 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
5776 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
5777 ITypeInfo_Release(pTInfo
);
5780 WARN("Could not search inherited interface!\n");
5783 WARN("member %d not found\n", memid
);
5784 return TYPE_E_ELEMENTNOTFOUND
;
5787 /* ITypeInfo::GetDllEntry
5789 * Retrieves a description or specification of an entry point for a function
5792 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5793 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5796 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5797 const TLBFuncDesc
*pFDesc
;
5799 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5801 if (pBstrDllName
) *pBstrDllName
= NULL
;
5802 if (pBstrName
) *pBstrName
= NULL
;
5803 if (pwOrdinal
) *pwOrdinal
= 0;
5805 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
5806 return TYPE_E_BADMODULEKIND
;
5808 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5809 if(pFDesc
->funcdesc
.memid
==memid
){
5810 dump_TypeInfo(This
);
5812 dump_TLBFuncDescOne(pFDesc
);
5815 *pBstrDllName
= SysAllocString(This
->DllName
);
5817 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5819 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5827 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5830 return TYPE_E_ELEMENTNOTFOUND
;
5833 /* ITypeInfo::GetRefTypeInfo
5835 * If a type description references other type descriptions, it retrieves
5836 * the referenced type descriptions.
5838 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5841 ITypeInfo
**ppTInfo
)
5843 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5844 HRESULT result
= E_FAIL
;
5846 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
5848 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5849 ITypeInfo_AddRef(*ppTInfo
);
5852 else if (hRefType
== -1 &&
5853 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5854 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5856 /* when we meet a DUAL dispinterface, we must create the interface
5859 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5862 /* the interface version contains the same information as the dispinterface
5863 * copy the contents of the structs.
5865 *pTypeInfoImpl
= *This
;
5866 pTypeInfoImpl
->ref
= 0;
5868 /* change the type to interface */
5869 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5871 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5873 /* we use data structures from This, so we need to keep a reference
5874 * to it to stop it being destroyed and signal to the new instance to
5875 * not free its data structures when it is destroyed */
5876 pTypeInfoImpl
->no_free_data
= TRUE
;
5877 pTypeInfoImpl
->next
= This
;
5878 ITypeInfo_AddRef((ITypeInfo
*) This
);
5880 ITypeInfo_AddRef(*ppTInfo
);
5885 TLBRefType
*pRefType
;
5886 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5887 if(pRefType
->reference
== hRefType
)
5891 FIXME("Can't find pRefType for ref %x\n", hRefType
);
5892 if(pRefType
&& hRefType
!= -1) {
5893 ITypeLib
*pTLib
= NULL
;
5895 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5897 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5899 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5900 TRACE("typeinfo in imported typelib that is already loaded\n");
5901 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5902 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5905 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5906 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5907 pRefType
->pImpTLInfo
->wVersionMajor
,
5908 pRefType
->pImpTLInfo
->wVersionMinor
,
5909 pRefType
->pImpTLInfo
->lcid
,
5912 if(!SUCCEEDED(result
)) {
5913 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5914 result
=LoadTypeLib(libnam
, &pTLib
);
5915 SysFreeString(libnam
);
5917 if(SUCCEEDED(result
)) {
5918 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5919 ITypeLib2_AddRef(pTLib
);
5923 if(SUCCEEDED(result
)) {
5924 if(pRefType
->index
== TLB_REF_USE_GUID
)
5925 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5929 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5933 ITypeLib2_Release(pTLib
);
5937 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
5938 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5942 /* ITypeInfo::AddressOfMember
5944 * Retrieves the addresses of static functions or variables, such as those
5947 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5948 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5950 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5956 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
5958 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
5962 module
= LoadLibraryW(dll
);
5965 ERR("couldn't load %s\n", debugstr_w(dll
));
5967 if (entry
) SysFreeString(entry
);
5968 return STG_E_FILENOTFOUND
;
5970 /* FIXME: store library somewhere where we can free it */
5975 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
5976 entryA
= HeapAlloc(GetProcessHeap(), 0, len
);
5977 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
5979 *ppv
= GetProcAddress(module
, entryA
);
5981 ERR("function not found %s\n", debugstr_a(entryA
));
5983 HeapFree(GetProcessHeap(), 0, entryA
);
5987 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
5989 ERR("function not found %d\n", ordinal
);
5993 if (entry
) SysFreeString(entry
);
5996 return TYPE_E_DLLFUNCTIONNOTFOUND
;
6001 /* ITypeInfo::CreateInstance
6003 * Creates a new instance of a type that describes a component object class
6006 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
6007 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
6009 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6013 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
6019 WARN("Not able to aggregate\n");
6020 return CLASS_E_NOAGGREGATION
;
6023 hr
= ITypeInfo_GetTypeAttr(iface
, &pTA
);
6024 if(FAILED(hr
)) return hr
;
6026 if(pTA
->typekind
!= TKIND_COCLASS
)
6028 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
6034 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
6037 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
6038 TRACE("GetActiveObject rets %08x\n", hr
);
6041 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
6042 IUnknown_Release(pUnk
);
6047 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
6048 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
6052 ITypeInfo_ReleaseTypeAttr(iface
, pTA
);
6056 /* ITypeInfo::GetMops
6058 * Retrieves marshalling information.
6060 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
6063 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6064 FIXME("(%p) stub!\n", This
);
6068 /* ITypeInfo::GetContainingTypeLib
6070 * Retrieves the containing type library and the index of the type description
6071 * within that type library.
6073 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
6074 ITypeLib
* *ppTLib
, UINT
*pIndex
)
6076 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6078 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6080 *pIndex
=This
->index
;
6081 TRACE("returning pIndex=%d\n", *pIndex
);
6085 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
6086 ITypeLib2_AddRef(*ppTLib
);
6087 TRACE("returning ppTLib=%p\n", *ppTLib
);
6093 /* ITypeInfo::ReleaseTypeAttr
6095 * Releases a TYPEATTR previously returned by GetTypeAttr.
6098 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
6099 TYPEATTR
* pTypeAttr
)
6101 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6102 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
6103 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
6106 /* ITypeInfo::ReleaseFuncDesc
6108 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6110 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
6112 FUNCDESC
*pFuncDesc
)
6114 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6117 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
6119 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6120 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
6121 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
6123 SysFreeString((BSTR
)pFuncDesc
);
6126 /* ITypeInfo::ReleaseVarDesc
6128 * Releases a VARDESC previously returned by GetVarDesc.
6130 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
6133 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6134 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
6136 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
6137 if (pVarDesc
->varkind
== VAR_CONST
)
6138 VariantClear(pVarDesc
->u
.lpvarValue
);
6139 SysFreeString((BSTR
)pVarDesc
);
6142 /* ITypeInfo2::GetTypeKind
6144 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6147 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
6148 TYPEKIND
*pTypeKind
)
6150 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6151 *pTypeKind
=This
->TypeAttr
.typekind
;
6152 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
6156 /* ITypeInfo2::GetTypeFlags
6158 * Returns the type flags without any allocations. This returns a DWORD type
6159 * flag, which expands the type flags without growing the TYPEATTR (type
6163 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
6165 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6166 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
6167 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
6171 /* ITypeInfo2::GetFuncIndexOfMemId
6172 * Binds to a specific member based on a known DISPID, where the member name
6173 * is not known (for example, when binding to a default member).
6176 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
6177 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
6179 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6180 const TLBFuncDesc
*pFuncInfo
;
6184 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
6185 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
6191 result
= TYPE_E_ELEMENTNOTFOUND
;
6193 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
6194 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6198 /* TypeInfo2::GetVarIndexOfMemId
6200 * Binds to a specific member based on a known DISPID, where the member name
6201 * is not known (for example, when binding to a default member).
6204 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
6205 MEMBERID memid
, UINT
*pVarIndex
)
6207 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6208 TLBVarDesc
*pVarInfo
;
6211 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
6212 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
6218 result
= TYPE_E_ELEMENTNOTFOUND
;
6220 TRACE("(%p) memid 0x%08x -> %s\n", This
,
6221 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
6225 /* ITypeInfo2::GetCustData
6227 * Gets the custom data
6229 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
6234 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6235 TLBCustData
*pCData
;
6237 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
6238 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6240 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6244 VariantInit( pVarVal
);
6245 VariantCopy( pVarVal
, &pCData
->data
);
6248 return E_INVALIDARG
; /* FIXME: correct? */
6251 /* ITypeInfo2::GetFuncCustData
6253 * Gets the custom data
6255 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
6261 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6262 TLBCustData
*pCData
=NULL
;
6263 TLBFuncDesc
* pFDesc
;
6265 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
6266 pFDesc
=pFDesc
->next
);
6269 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6270 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6272 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6275 VariantInit( pVarVal
);
6276 VariantCopy( pVarVal
, &pCData
->data
);
6279 return E_INVALIDARG
; /* FIXME: correct? */
6282 /* ITypeInfo2::GetParamCustData
6284 * Gets the custom data
6286 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
6293 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6294 TLBCustData
*pCData
=NULL
;
6295 TLBFuncDesc
* pFDesc
;
6298 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
6300 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
6301 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
6302 pCData
= pCData
->next
)
6303 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6305 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6309 VariantInit( pVarVal
);
6310 VariantCopy( pVarVal
, &pCData
->data
);
6313 return E_INVALIDARG
; /* FIXME: correct? */
6316 /* ITypeInfo2::GetVarCustData
6318 * Gets the custom data
6320 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
6326 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6327 TLBCustData
*pCData
=NULL
;
6328 TLBVarDesc
* pVDesc
;
6331 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
6335 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6337 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6341 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6345 VariantInit( pVarVal
);
6346 VariantCopy( pVarVal
, &pCData
->data
);
6349 return E_INVALIDARG
; /* FIXME: correct? */
6352 /* ITypeInfo2::GetImplCustData
6354 * Gets the custom data
6356 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
6362 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6363 TLBCustData
*pCData
=NULL
;
6364 TLBImplType
* pRDesc
;
6367 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
6371 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6373 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6377 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6381 VariantInit( pVarVal
);
6382 VariantCopy( pVarVal
, &pCData
->data
);
6385 return E_INVALIDARG
; /* FIXME: correct? */
6388 /* ITypeInfo2::GetDocumentation2
6390 * Retrieves the documentation string, the complete Help file name and path,
6391 * the localization context to use, and the context ID for the library Help
6392 * topic in the Help file.
6395 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
6399 BSTR
*pbstrHelpString
,
6400 DWORD
*pdwHelpStringContext
,
6401 BSTR
*pbstrHelpStringDll
)
6403 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6404 const TLBFuncDesc
*pFDesc
;
6405 const TLBVarDesc
*pVDesc
;
6406 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6407 "HelpStringContext(%p) HelpStringDll(%p)\n",
6408 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
6409 pbstrHelpStringDll
);
6410 /* the help string should be obtained from the helpstringdll,
6411 * using the _DLLGetDocumentation function, based on the supplied
6412 * lcid. Nice to do sometime...
6414 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6416 *pbstrHelpString
=SysAllocString(This
->Name
);
6417 if(pdwHelpStringContext
)
6418 *pdwHelpStringContext
=This
->dwHelpStringContext
;
6419 if(pbstrHelpStringDll
)
6420 *pbstrHelpStringDll
=
6421 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6423 }else {/* for a member */
6424 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6425 if(pFDesc
->funcdesc
.memid
==memid
){
6427 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
6428 if(pdwHelpStringContext
)
6429 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
6430 if(pbstrHelpStringDll
)
6431 *pbstrHelpStringDll
=
6432 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6435 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6436 if(pVDesc
->vardesc
.memid
==memid
){
6438 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
6439 if(pdwHelpStringContext
)
6440 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
6441 if(pbstrHelpStringDll
)
6442 *pbstrHelpStringDll
=
6443 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6447 return TYPE_E_ELEMENTNOTFOUND
;
6450 /* ITypeInfo2::GetAllCustData
6452 * Gets all custom data items for the Type info.
6455 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
6457 CUSTDATA
*pCustData
)
6459 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6460 TLBCustData
*pCData
;
6463 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
6465 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
6466 if(pCustData
->prgCustData
){
6467 pCustData
->cCustData
=This
->ctCustData
;
6468 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
6469 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6470 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
6473 ERR(" OUT OF MEMORY!\n");
6474 return E_OUTOFMEMORY
;
6479 /* ITypeInfo2::GetAllFuncCustData
6481 * Gets all custom data items for the specified Function
6484 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
6487 CUSTDATA
*pCustData
)
6489 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6490 TLBCustData
*pCData
;
6491 TLBFuncDesc
* pFDesc
;
6493 TRACE("(%p) index %d\n", This
, index
);
6494 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
6495 pFDesc
=pFDesc
->next
)
6498 pCustData
->prgCustData
=
6499 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6500 if(pCustData
->prgCustData
){
6501 pCustData
->cCustData
=pFDesc
->ctCustData
;
6502 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
6503 pCData
= pCData
->next
){
6504 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6505 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6509 ERR(" OUT OF MEMORY!\n");
6510 return E_OUTOFMEMORY
;
6514 return TYPE_E_ELEMENTNOTFOUND
;
6517 /* ITypeInfo2::GetAllParamCustData
6519 * Gets all custom data items for the Functions
6522 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
6523 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
6525 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6526 TLBCustData
*pCData
=NULL
;
6527 TLBFuncDesc
* pFDesc
;
6529 TRACE("(%p) index %d\n", This
, indexFunc
);
6530 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
6531 pFDesc
=pFDesc
->next
)
6533 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
6534 pCustData
->prgCustData
=
6535 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
6536 sizeof(CUSTDATAITEM
));
6537 if(pCustData
->prgCustData
){
6538 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
6539 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
6540 pCData
; i
++, pCData
= pCData
->next
){
6541 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6542 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6546 ERR(" OUT OF MEMORY!\n");
6547 return E_OUTOFMEMORY
;
6551 return TYPE_E_ELEMENTNOTFOUND
;
6554 /* ITypeInfo2::GetAllVarCustData
6556 * Gets all custom data items for the specified Variable
6559 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
6560 UINT index
, CUSTDATA
*pCustData
)
6562 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6563 TLBCustData
*pCData
;
6564 TLBVarDesc
* pVDesc
;
6566 TRACE("(%p) index %d\n", This
, index
);
6567 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
6568 pVDesc
=pVDesc
->next
)
6571 pCustData
->prgCustData
=
6572 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6573 if(pCustData
->prgCustData
){
6574 pCustData
->cCustData
=pVDesc
->ctCustData
;
6575 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
6576 pCData
= pCData
->next
){
6577 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6578 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6582 ERR(" OUT OF MEMORY!\n");
6583 return E_OUTOFMEMORY
;
6587 return TYPE_E_ELEMENTNOTFOUND
;
6590 /* ITypeInfo2::GetAllImplCustData
6592 * Gets all custom data items for the specified implementation type
6595 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
6598 CUSTDATA
*pCustData
)
6600 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6601 TLBCustData
*pCData
;
6602 TLBImplType
* pRDesc
;
6604 TRACE("(%p) index %d\n", This
, index
);
6605 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
6606 pRDesc
=pRDesc
->next
)
6609 pCustData
->prgCustData
=
6610 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6611 if(pCustData
->prgCustData
){
6612 pCustData
->cCustData
=pRDesc
->ctCustData
;
6613 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
6614 pCData
= pCData
->next
){
6615 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6616 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6620 ERR(" OUT OF MEMORY!\n");
6621 return E_OUTOFMEMORY
;
6625 return TYPE_E_ELEMENTNOTFOUND
;
6628 static const ITypeInfo2Vtbl tinfvt
=
6631 ITypeInfo_fnQueryInterface
,
6633 ITypeInfo_fnRelease
,
6635 ITypeInfo_fnGetTypeAttr
,
6636 ITypeInfo_fnGetTypeComp
,
6637 ITypeInfo_fnGetFuncDesc
,
6638 ITypeInfo_fnGetVarDesc
,
6639 ITypeInfo_fnGetNames
,
6640 ITypeInfo_fnGetRefTypeOfImplType
,
6641 ITypeInfo_fnGetImplTypeFlags
,
6642 ITypeInfo_fnGetIDsOfNames
,
6644 ITypeInfo_fnGetDocumentation
,
6645 ITypeInfo_fnGetDllEntry
,
6646 ITypeInfo_fnGetRefTypeInfo
,
6647 ITypeInfo_fnAddressOfMember
,
6648 ITypeInfo_fnCreateInstance
,
6649 ITypeInfo_fnGetMops
,
6650 ITypeInfo_fnGetContainingTypeLib
,
6651 ITypeInfo_fnReleaseTypeAttr
,
6652 ITypeInfo_fnReleaseFuncDesc
,
6653 ITypeInfo_fnReleaseVarDesc
,
6655 ITypeInfo2_fnGetTypeKind
,
6656 ITypeInfo2_fnGetTypeFlags
,
6657 ITypeInfo2_fnGetFuncIndexOfMemId
,
6658 ITypeInfo2_fnGetVarIndexOfMemId
,
6659 ITypeInfo2_fnGetCustData
,
6660 ITypeInfo2_fnGetFuncCustData
,
6661 ITypeInfo2_fnGetParamCustData
,
6662 ITypeInfo2_fnGetVarCustData
,
6663 ITypeInfo2_fnGetImplTypeCustData
,
6664 ITypeInfo2_fnGetDocumentation2
,
6665 ITypeInfo2_fnGetAllCustData
,
6666 ITypeInfo2_fnGetAllFuncCustData
,
6667 ITypeInfo2_fnGetAllParamCustData
,
6668 ITypeInfo2_fnGetAllVarCustData
,
6669 ITypeInfo2_fnGetAllImplTypeCustData
,
6672 /******************************************************************************
6673 * CreateDispTypeInfo [OLEAUT32.31]
6675 * Build type information for an object so it can be called through an
6676 * IDispatch interface.
6679 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6680 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6683 * This call allows an objects methods to be accessed through IDispatch, by
6684 * building an ITypeInfo object that IDispatch can use to call through.
6686 HRESULT WINAPI
CreateDispTypeInfo(
6687 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
6688 LCID lcid
, /* [I] Locale Id */
6689 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
6691 ITypeInfoImpl
*pTIClass
, *pTIIface
;
6692 ITypeLibImpl
*pTypeLibImpl
;
6694 TLBFuncDesc
**ppFuncDesc
;
6697 pTypeLibImpl
= TypeLibImpl_Constructor();
6698 if (!pTypeLibImpl
) return E_FAIL
;
6700 pTIIface
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
6701 pTIIface
->pTypeLib
= pTypeLibImpl
;
6702 pTIIface
->index
= 0;
6703 pTIIface
->Name
= NULL
;
6704 pTIIface
->dwHelpContext
= -1;
6705 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
6706 pTIIface
->TypeAttr
.lcid
= lcid
;
6707 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6708 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
6709 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
6710 pTIIface
->TypeAttr
.cbAlignment
= 2;
6711 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
6712 pTIIface
->TypeAttr
.cbSizeVft
= -1;
6713 pTIIface
->TypeAttr
.cFuncs
= 0;
6714 pTIIface
->TypeAttr
.cImplTypes
= 0;
6715 pTIIface
->TypeAttr
.cVars
= 0;
6716 pTIIface
->TypeAttr
.wTypeFlags
= 0;
6718 ppFuncDesc
= &pTIIface
->funclist
;
6719 for(func
= 0; func
< pidata
->cMembers
; func
++) {
6720 METHODDATA
*md
= pidata
->pmethdata
+ func
;
6721 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
6722 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
6723 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
6724 (*ppFuncDesc
)->funcdesc
.lprgscode
= NULL
;
6725 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_VIRTUAL
;
6726 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
6727 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
6728 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
6729 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
6730 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
<< 2;
6731 (*ppFuncDesc
)->funcdesc
.cScodes
= 0;
6732 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0;
6733 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
6734 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
6735 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
6736 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6737 md
->cArgs
* sizeof(ELEMDESC
));
6738 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6739 md
->cArgs
* sizeof(TLBParDesc
));
6740 for(param
= 0; param
< md
->cArgs
; param
++) {
6741 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
6742 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
6744 (*ppFuncDesc
)->helpcontext
= 0;
6745 (*ppFuncDesc
)->HelpStringContext
= 0;
6746 (*ppFuncDesc
)->HelpString
= NULL
;
6747 (*ppFuncDesc
)->Entry
= NULL
;
6748 (*ppFuncDesc
)->ctCustData
= 0;
6749 (*ppFuncDesc
)->pCustData
= NULL
;
6750 (*ppFuncDesc
)->next
= NULL
;
6751 ppFuncDesc
= &(*ppFuncDesc
)->next
;
6754 dump_TypeInfo(pTIIface
);
6756 pTypeLibImpl
->pTypeInfo
= pTIIface
;
6757 pTypeLibImpl
->TypeInfoCount
++;
6759 pTIClass
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
6760 pTIClass
->pTypeLib
= pTypeLibImpl
;
6761 pTIClass
->index
= 1;
6762 pTIClass
->Name
= NULL
;
6763 pTIClass
->dwHelpContext
= -1;
6764 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
6765 pTIClass
->TypeAttr
.lcid
= lcid
;
6766 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
6767 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
6768 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
6769 pTIClass
->TypeAttr
.cbAlignment
= 2;
6770 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
6771 pTIClass
->TypeAttr
.cbSizeVft
= -1;
6772 pTIClass
->TypeAttr
.cFuncs
= 0;
6773 pTIClass
->TypeAttr
.cImplTypes
= 1;
6774 pTIClass
->TypeAttr
.cVars
= 0;
6775 pTIClass
->TypeAttr
.wTypeFlags
= 0;
6777 pTIClass
->impltypelist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->impltypelist
));
6778 pTIClass
->impltypelist
->hRef
= 1;
6780 pTIClass
->reflist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->reflist
));
6781 pTIClass
->reflist
->index
= 0;
6782 pTIClass
->reflist
->reference
= 1;
6783 pTIClass
->reflist
->pImpTLInfo
= TLB_REF_INTERNAL
;
6785 dump_TypeInfo(pTIClass
);
6787 pTIIface
->next
= pTIClass
;
6788 pTypeLibImpl
->TypeInfoCount
++;
6790 *pptinfo
= (ITypeInfo
*)pTIClass
;
6795 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
6797 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6799 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
6802 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
6804 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6806 return ITypeInfo_AddRef((ITypeInfo
*)This
);
6809 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
6811 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6813 return ITypeInfo_Release((ITypeInfo
*)This
);
6816 static HRESULT WINAPI
ITypeComp_fnBind(
6821 ITypeInfo
** ppTInfo
,
6822 DESCKIND
* pDescKind
,
6825 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6826 const TLBFuncDesc
*pFDesc
;
6827 const TLBVarDesc
*pVDesc
;
6828 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
6830 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6832 *pDescKind
= DESCKIND_NONE
;
6833 pBindPtr
->lpfuncdesc
= NULL
;
6836 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
6837 if (!strcmpiW(pFDesc
->Name
, szName
)) {
6838 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
6841 /* name found, but wrong flags */
6842 hr
= TYPE_E_TYPEMISMATCH
;
6847 HRESULT hr
= TLB_AllocAndInitFuncDesc(
6849 &pBindPtr
->lpfuncdesc
,
6850 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
6853 *pDescKind
= DESCKIND_FUNCDESC
;
6854 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6855 ITypeInfo_AddRef(*ppTInfo
);
6858 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
6859 if (!strcmpiW(pVDesc
->Name
, szName
)) {
6860 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
6863 *pDescKind
= DESCKIND_VARDESC
;
6864 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6865 ITypeInfo_AddRef(*ppTInfo
);
6870 /* FIXME: search each inherited interface, not just the first */
6871 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->TypeAttr
.cImplTypes
) {
6872 /* recursive search */
6876 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
6879 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
6880 ITypeInfo_Release(pTInfo
);
6884 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6885 ITypeComp_Release(pTComp
);
6888 WARN("Could not search inherited interface!\n");
6890 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
6894 static HRESULT WINAPI
ITypeComp_fnBindType(
6898 ITypeInfo
** ppTInfo
,
6899 ITypeComp
** ppTComp
)
6901 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
6903 /* strange behaviour (does nothing) but like the
6906 if (!ppTInfo
|| !ppTComp
)
6915 static const ITypeCompVtbl tcompvt
=
6918 ITypeComp_fnQueryInterface
,
6920 ITypeComp_fnRelease
,
6923 ITypeComp_fnBindType