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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
86 const GUID CLSID_PSOAInterface
= { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
88 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, TYPEDESC
*tdesc
, VARTYPE
*vt
);
89 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
91 /****************************************************************************
94 * Takes p_iVal (which is in little endian) and returns it
95 * in the host machine's byte order.
97 #ifdef WORDS_BIGENDIAN
98 static WORD
FromLEWord(WORD p_iVal
)
100 return (((p_iVal
& 0x00FF) << 8) |
101 ((p_iVal
& 0xFF00) >> 8));
105 static DWORD
FromLEDWord(DWORD p_iVal
)
107 return (((p_iVal
& 0x000000FF) << 24) |
108 ((p_iVal
& 0x0000FF00) << 8) |
109 ((p_iVal
& 0x00FF0000) >> 8) |
110 ((p_iVal
& 0xFF000000) >> 24));
113 #define FromLEWord(X) (X)
114 #define FromLEDWord(X) (X)
118 /****************************************************************************
121 * Fix byte order in any structure if necessary
123 #ifdef WORDS_BIGENDIAN
124 static void FromLEWords(void *p_Val
, int p_iSize
)
128 p_iSize
/= sizeof(WORD
);
131 *Val
= FromLEWord(*Val
);
138 static void FromLEDWords(void *p_Val
, int p_iSize
)
142 p_iSize
/= sizeof(DWORD
);
145 *Val
= FromLEDWord(*Val
);
151 #define FromLEWords(X,Y) /*nothing*/
152 #define FromLEDWords(X,Y) /*nothing*/
155 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
156 /* buffer must be at least 60 characters long */
157 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
159 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
160 static const WCHAR VersionFormatW
[] = {'\\','%','u','.','%','u',0};
162 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
163 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
164 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
168 /* get the path of an interface key, in the form "Interface\\<guid>" */
169 /* buffer must be at least 50 characters long */
170 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
172 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
174 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
175 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
179 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
180 /* buffer must be at least 16 characters long */
181 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
183 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
184 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
185 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
187 sprintfW( buffer
, LcidFormatW
, lcid
);
190 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
191 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
193 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
199 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
202 /****************************************************************************
203 * QueryPathOfRegTypeLib [OLEAUT32.164]
205 * Gets the path to a registered type library.
208 * guid [I] referenced guid
209 * wMaj [I] major version
210 * wMin [I] minor version
212 * path [O] path of typelib
216 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
217 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
220 HRESULT WINAPI
QueryPathOfRegTypeLib(
227 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
231 WCHAR Path
[MAX_PATH
];
234 TRACE_(typelib
)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
236 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
238 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
239 if (res
== ERROR_FILE_NOT_FOUND
)
241 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
242 return TYPE_E_LIBNOTREGISTERED
;
244 else if (res
!= ERROR_SUCCESS
)
246 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
247 return TYPE_E_REGISTRYACCESS
;
252 LONG dwPathLen
= sizeof(Path
);
254 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
256 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
260 else if (myLCID
== lcid
)
262 /* try with sub-langid */
263 myLCID
= SUBLANGID(lcid
);
265 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
267 /* try with system langid */
277 *path
= SysAllocString( Path
);
282 TRACE_(typelib
)("-- 0x%08lx\n", hr
);
286 /******************************************************************************
287 * CreateTypeLib [OLEAUT32.160] creates a typelib
293 HRESULT WINAPI
CreateTypeLib(
294 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
296 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
300 /******************************************************************************
301 * LoadTypeLib [OLEAUT32.161]
303 * Loads a type library
306 * szFile [I] Name of file to load from.
307 * pptLib [O] Pointer that receives ITypeLib object on success.
314 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
316 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
318 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
319 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
322 /******************************************************************************
323 * LoadTypeLibEx [OLEAUT32.183]
325 * Loads and optionally registers a type library
331 HRESULT WINAPI
LoadTypeLibEx(
332 LPCOLESTR szFile
, /* [in] Name of file to load from */
333 REGKIND regkind
, /* [in] Specify kind of registration */
334 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
336 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
341 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
343 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
344 memcpy(szPath
, szFile
, (strlenW(szFile
)+1)*sizeof(WCHAR
));
347 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
350 /* Look for a trailing '\\' followed by an index */
351 pIndexStr
= strrchrW(szFile
, '\\');
352 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
353 index
= atoiW(pIndexStr
);
354 memcpy(szFileCopy
, szFile
,
355 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
356 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
357 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
359 return TYPE_E_CANTLOADLIBRARY
;
360 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
361 return TYPE_E_CANTLOADLIBRARY
;
365 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
367 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
372 case REGKIND_DEFAULT
:
373 /* don't register typelibs supplied with full path. Experimentation confirms the following */
375 ((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
376 (szFile
[0] && (szFile
[1] == ':'))) break;
377 /* else fall-through */
379 case REGKIND_REGISTER
:
380 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
382 IUnknown_Release(*pptLib
);
390 TRACE(" returns %08lx\n",res
);
394 /******************************************************************************
395 * LoadRegTypeLib [OLEAUT32.162]
397 * Loads a registered type library.
400 * rguid [I] GUID of the registered type library.
401 * wVerMajor [I] major version.
402 * wVerMinor [I] minor version.
403 * lcid [I] locale ID.
404 * ppTLib [O] pointer that receives an ITypeLib object on success.
408 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
411 HRESULT WINAPI
LoadRegTypeLib(
419 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
423 res
= LoadTypeLib(bstr
, ppTLib
);
427 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
433 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
434 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
435 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
436 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
437 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
438 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
440 /******************************************************************************
441 * RegisterTypeLib [OLEAUT32.163]
442 * Adds information about a type library to the System Registry
444 * Docs: ITypeLib FAR * ptlib
445 * Docs: OLECHAR FAR* szFullPath
446 * Docs: OLECHAR FAR* szHelpDir
452 HRESULT WINAPI
RegisterTypeLib(
453 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
454 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
455 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
458 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
459 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
460 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
470 if (ptlib
== NULL
|| szFullPath
== NULL
)
473 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
476 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
479 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
480 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
484 /* Set the human-readable name of the typelib */
485 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
487 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
488 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
496 /* Make up the name of the typelib path subkey */
497 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
499 /* Create the typelib path subkey */
500 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
501 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
503 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
504 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
512 /* Create the flags subkey */
513 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
514 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
516 /* FIXME: is %u correct? */
517 static const WCHAR formatW
[] = {'%','u',0};
519 sprintfW(buf
, formatW
, attr
->wLibFlags
);
520 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
521 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
529 /* create the helpdir subkey */
530 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
531 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
533 BOOL freeHelpDir
= FALSE
;
536 /* if we created a new key, and helpDir was null, set the helpdir
537 to the directory which contains the typelib. However,
538 if we just opened an existing key, we leave the helpdir alone */
539 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
540 szHelpDir
= SysAllocString(szFullPath
);
541 pIndexStr
= strrchrW(szHelpDir
, '\\');
548 /* if we have an szHelpDir, set it! */
549 if (szHelpDir
!= NULL
) {
550 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
551 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
557 if (freeHelpDir
) SysFreeString(szHelpDir
);
569 /* register OLE Automation-compatible interfaces for this typelib */
570 types
= ITypeLib_GetTypeInfoCount(ptlib
);
571 for (tidx
=0; tidx
<types
; tidx
++) {
572 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
573 LPOLESTR name
= NULL
;
574 ITypeInfo
*tinfo
= NULL
;
576 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
579 case TKIND_INTERFACE
:
580 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
581 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
585 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
586 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
590 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
595 TYPEATTR
*tattr
= NULL
;
596 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
599 TRACE_(typelib
)("guid=%s, flags=%04x (",
600 debugstr_guid(&tattr
->guid
),
603 if (TRACE_ON(typelib
)) {
604 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
624 if (tattr
->wTypeFlags
& (TYPEFLAG_FOLEAUTOMATION
|TYPEFLAG_FDUAL
))
626 /* register interface<->typelib coupling */
627 get_interface_key( &tattr
->guid
, keyName
);
628 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
629 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
632 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
633 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
635 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
636 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
637 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
638 (BYTE
*)PSOA
, sizeof PSOA
);
642 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
643 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
644 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
645 (BYTE
*)PSOA
, sizeof PSOA
);
649 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
650 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
653 static const WCHAR fmtver
[] = {'%','u','.','%','u',0 };
654 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
656 StringFromGUID2(&attr
->guid
, buffer
, 40);
657 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
658 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
659 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
660 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
661 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
669 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
672 ITypeInfo_Release(tinfo
);
679 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
685 /******************************************************************************
686 * UnRegisterTypeLib [OLEAUT32.186]
687 * Removes information about a type library from the System Registry
694 HRESULT WINAPI
UnRegisterTypeLib(
695 REFGUID libid
, /* [in] Guid of the library */
696 WORD wVerMajor
, /* [in] major version */
697 WORD wVerMinor
, /* [in] minor version */
698 LCID lcid
, /* [in] locale id */
701 BSTR tlibPath
= NULL
;
704 WCHAR subKeyName
[50];
707 BOOL deleteOtherStuff
;
710 TYPEATTR
* typeAttr
= NULL
;
712 ITypeInfo
* typeInfo
= NULL
;
713 ITypeLib
* typeLib
= NULL
;
716 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
718 /* Create the path to the key */
719 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
721 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
723 TRACE("Unsupported syskind %i\n", syskind
);
724 result
= E_INVALIDARG
;
728 /* get the path to the typelib on disk */
729 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
730 result
= E_INVALIDARG
;
734 /* Try and open the key to the type library. */
735 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != S_OK
) {
736 result
= E_INVALIDARG
;
740 /* Try and load the type library */
741 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
742 result
= TYPE_E_INVALIDSTATE
;
746 /* remove any types registered with this typelib */
747 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
748 for (i
=0; i
<numTypes
; i
++) {
749 /* get the kind of type */
750 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
754 /* skip non-interfaces, and get type info for the type */
755 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
758 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
761 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
765 /* the path to the type */
766 get_interface_key( &typeAttr
->guid
, subKeyName
);
768 /* Delete its bits */
769 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != S_OK
) {
772 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
773 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
774 RegDeleteKeyW(subKey
, TypeLibW
);
777 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
780 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
782 if (typeInfo
) ITypeInfo_Release(typeInfo
);
786 /* Now, delete the type library path subkey */
787 get_lcid_subkey( lcid
, syskind
, subKeyName
);
788 RegDeleteKeyW(key
, subKeyName
);
789 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
790 RegDeleteKeyW(key
, subKeyName
);
792 /* check if there is anything besides the FLAGS/HELPDIR keys.
793 If there is, we don't delete them */
794 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
795 deleteOtherStuff
= TRUE
;
797 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == S_OK
) {
798 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
800 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
801 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
802 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
803 deleteOtherStuff
= FALSE
;
807 /* only delete the other parts of the key if we're absolutely sure */
808 if (deleteOtherStuff
) {
809 RegDeleteKeyW(key
, FLAGSW
);
810 RegDeleteKeyW(key
, HELPDIRW
);
814 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
815 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
816 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
820 if (tlibPath
) SysFreeString(tlibPath
);
821 if (typeLib
) ITypeLib_Release(typeLib
);
822 if (subKey
) RegCloseKey(subKey
);
823 if (key
) RegCloseKey(key
);
827 /*======================= ITypeLib implementation =======================*/
829 typedef struct tagTLBCustData
833 struct tagTLBCustData
* next
;
836 /* data structure for import typelibs */
837 typedef struct tagTLBImpLib
839 int offset
; /* offset in the file (MSFT)
840 offset in nametable (SLTG)
841 just used to identify library while reading
843 GUID guid
; /* libid */
844 BSTR name
; /* name */
846 LCID lcid
; /* lcid of imported typelib */
848 WORD wVersionMajor
; /* major version number */
849 WORD wVersionMinor
; /* minor version number */
851 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
852 NULL if not yet loaded */
853 struct tagTLBImpLib
* next
;
856 /* internal ITypeLib data */
857 typedef struct tagITypeLibImpl
859 const ITypeLib2Vtbl
*lpVtbl
;
860 const ITypeCompVtbl
*lpVtblTypeComp
;
862 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
864 /* strings can be stored in tlb as multibyte strings BUT they are *always*
865 * exported to the application as a UNICODE string.
871 unsigned long dwHelpContext
;
872 int TypeInfoCount
; /* nr of typeinfo's in librarry */
873 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
874 int ctCustData
; /* number of items in cust data list */
875 TLBCustData
* pCustData
; /* linked list to cust data */
876 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
877 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
878 libary. Only used while read MSFT
881 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
882 struct tagITypeLibImpl
*next
, *prev
;
887 static const ITypeLib2Vtbl tlbvt
;
888 static const ITypeCompVtbl tlbtcvt
;
890 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
892 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
895 /* ITypeLib methods */
896 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
897 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
899 /*======================= ITypeInfo implementation =======================*/
901 /* data for referenced types */
902 typedef struct tagTLBRefType
904 INT index
; /* Type index for internal ref or for external ref
905 it the format is SLTG. -2 indicates to
908 GUID guid
; /* guid of the referenced type */
909 /* if index == TLB_REF_USE_GUID */
911 HREFTYPE reference
; /* The href of this ref */
912 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
913 TLB_REF_INTERNAL for internal refs
914 TLB_REF_NOT_FOUND for broken refs */
916 struct tagTLBRefType
* next
;
919 #define TLB_REF_USE_GUID -2
921 #define TLB_REF_INTERNAL (void*)-2
922 #define TLB_REF_NOT_FOUND (void*)-1
924 /* internal Parameter data */
925 typedef struct tagTLBParDesc
929 TLBCustData
* pCustData
; /* linked list to cust data */
932 /* internal Function data */
933 typedef struct tagTLBFuncDesc
935 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
936 BSTR Name
; /* the name of this function */
937 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
939 int HelpStringContext
;
941 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
943 TLBCustData
* pCustData
; /* linked list to cust data; */
944 struct tagTLBFuncDesc
* next
;
947 /* internal Variable data */
948 typedef struct tagTLBVarDesc
950 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
951 BSTR Name
; /* the name of this variable */
953 int HelpStringContext
; /* FIXME: where? */
956 TLBCustData
* pCustData
;/* linked list to cust data; */
957 struct tagTLBVarDesc
* next
;
960 /* internal implemented interface data */
961 typedef struct tagTLBImplType
963 HREFTYPE hRef
; /* hRef of interface */
964 int implflags
; /* IMPLFLAG_*s */
966 TLBCustData
* pCustData
;/* linked list to custom data; */
967 struct tagTLBImplType
*next
;
970 /* internal TypeInfo data */
971 typedef struct tagITypeInfoImpl
973 const ITypeInfo2Vtbl
*lpVtbl
;
974 const ITypeCompVtbl
*lpVtblTypeComp
;
976 TYPEATTR TypeAttr
; /* _lots_ of type information. */
977 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
978 int index
; /* index in this typelib; */
979 /* type libs seem to store the doc strings in ascii
980 * so why should we do it in unicode?
985 unsigned long dwHelpContext
;
986 unsigned long dwHelpStringContext
;
989 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
992 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
994 /* Implemented Interfaces */
995 TLBImplType
* impltypelist
;
997 TLBRefType
* reflist
;
999 TLBCustData
* pCustData
; /* linked list to cust data; */
1000 struct tagITypeInfoImpl
* next
;
1003 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1005 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1008 static const ITypeInfo2Vtbl tinfvt
;
1009 static const ITypeCompVtbl tcompvt
;
1011 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
1013 typedef struct tagTLBContext
1015 unsigned int oStart
; /* start of TLB in file */
1016 unsigned int pos
; /* current pos */
1017 unsigned int length
; /* total length */
1018 void *mapping
; /* memory mapping */
1019 MSFT_SegDir
* pTblDir
;
1020 ITypeLibImpl
* pLibInfo
;
1024 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
1029 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
1030 if (pTD
->vt
& VT_RESERVED
)
1031 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1032 if (pTD
->vt
& VT_BYREF
)
1033 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1034 if (pTD
->vt
& VT_ARRAY
)
1035 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1036 if (pTD
->vt
& VT_VECTOR
)
1037 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1038 switch(pTD
->vt
& VT_TYPEMASK
) {
1039 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1040 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1041 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1042 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1043 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1044 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1045 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1046 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1047 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1048 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1049 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1050 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1051 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1052 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1053 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1054 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1055 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1056 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1057 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1058 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1059 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
1060 pTD
->u
.hreftype
); break;
1061 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1062 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1064 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1065 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1067 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1068 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1069 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1072 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1076 static void dump_ELEMDESC(ELEMDESC
*edesc
) {
1078 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1079 dump_TypeDesc(&edesc
->tdesc
,buf
);
1080 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1081 MESSAGE("\t\tu.paramdesc.wParamFlags");
1082 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1083 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1084 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1085 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1086 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1087 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1088 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1089 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1090 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1092 static void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
1094 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
1095 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1096 MESSAGE("Param %d:\n",i
);
1097 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1099 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1100 switch (funcdesc
->funckind
) {
1101 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1102 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1103 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1104 case FUNC_STATIC
: MESSAGE("static");break;
1105 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1106 default: MESSAGE("unknown");break;
1108 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1109 switch (funcdesc
->invkind
) {
1110 case INVOKE_FUNC
: MESSAGE("func");break;
1111 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1112 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1113 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1115 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1116 switch (funcdesc
->callconv
) {
1117 case CC_CDECL
: MESSAGE("cdecl");break;
1118 case CC_PASCAL
: MESSAGE("pascal");break;
1119 case CC_STDCALL
: MESSAGE("stdcall");break;
1120 case CC_SYSCALL
: MESSAGE("syscall");break;
1123 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1124 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1125 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1127 MESSAGE("\telemdescFunc (return value type):\n");
1128 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1131 static const char * typekind_desc
[] =
1144 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
1147 if (!TRACE_ON(typelib
))
1149 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1150 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1151 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1154 dump_FUNCDESC(&(pfd
->funcdesc
));
1156 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1157 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1159 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
1163 dump_TLBFuncDescOne(pfd
);
1167 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
1171 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1176 static void dump_TLBImpLib(TLBImpLib
*import
)
1178 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1179 debugstr_w(import
->name
));
1180 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1181 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1184 static void dump_TLBRefType(TLBRefType
* prt
)
1188 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1189 if(prt
->index
== -1)
1190 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1192 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1194 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1195 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1196 TRACE_(typelib
)("in lib\n");
1197 dump_TLBImpLib(prt
->pImpTLInfo
);
1203 static void dump_TLBImplType(TLBImplType
* impl
)
1207 "implementing/inheriting interface hRef = %lx implflags %x\n",
1208 impl
->hRef
, impl
->implflags
);
1213 void dump_Variant(VARIANT
* pvar
)
1217 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1221 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1222 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1224 TRACE(",%p", V_BYREF(pvar
));
1226 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1230 else switch (V_TYPE(pvar
))
1232 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1233 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1234 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1235 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1237 case VT_I4
: TRACE(",%ld", V_I4(pvar
)); break;
1239 case VT_UI4
: TRACE(",%ld", V_UI4(pvar
)); break;
1240 case VT_I8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_I8(pvar
) >> 32),
1241 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1242 case VT_UI8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_UI8(pvar
) >> 32),
1243 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1244 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1245 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1246 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1247 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1248 case VT_CY
: TRACE(",0x%08lx,0x%08lx", V_CY(pvar
).s
.Hi
,
1249 V_CY(pvar
).s
.Lo
); break;
1251 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1252 TRACE(",<invalid>");
1254 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1255 st
.wHour
, st
.wMinute
, st
.wSecond
);
1259 case VT_USERDEFINED
:
1261 case VT_NULL
: break;
1262 default: TRACE(",?"); break;
1268 static void dump_DispParms(DISPPARAMS
* pdp
)
1272 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1274 while (index
< pdp
->cArgs
)
1276 dump_Variant( &pdp
->rgvarg
[index
] );
1281 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1283 TRACE("%p ref=%lu\n", pty
, pty
->ref
);
1284 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1285 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1286 TRACE("fct:%u var:%u impl:%u\n",
1287 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1288 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1289 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1290 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1291 dump_TLBFuncDesc(pty
->funclist
);
1292 dump_TLBVarDesc(pty
->varlist
);
1293 dump_TLBImplType(pty
->impltypelist
);
1296 static void dump_VARDESC(VARDESC
*v
)
1298 MESSAGE("memid %ld\n",v
->memid
);
1299 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1300 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1301 dump_ELEMDESC(&(v
->elemdescVar
));
1302 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1303 MESSAGE("varkind %d\n",v
->varkind
);
1306 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1308 /* VT_LPWSTR is largest type that */
1309 /* may appear in type description*/
1310 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1311 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1312 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1313 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1314 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1315 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1319 static void TLB_abort(void)
1323 static void * TLB_Alloc(unsigned size
)
1326 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1328 ERR("cannot allocate memory\n");
1333 static void TLB_Free(void * ptr
)
1335 HeapFree(GetProcessHeap(), 0, ptr
);
1338 /* returns the size required for a deep copy of a typedesc into a
1340 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1344 if (alloc_initial_space
)
1345 size
+= sizeof(TYPEDESC
);
1351 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1354 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1355 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1361 /* deep copy a typedesc into a flat buffer */
1362 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1367 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1376 dest
->u
.lptdesc
= buffer
;
1377 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1380 dest
->u
.lpadesc
= buffer
;
1381 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1382 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1383 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1389 /**********************************************************************
1391 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1394 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1396 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1397 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1399 if (where
!= DO_NOT_SEEK
)
1401 where
+= pcx
->oStart
;
1402 if (where
> pcx
->length
)
1405 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1410 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1411 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1416 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1421 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1422 FromLEDWords(buffer
, ret
);
1427 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1432 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1433 FromLEWords(buffer
, ret
);
1438 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1440 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1441 memset(pGuid
,0, sizeof(GUID
));
1444 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1445 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1446 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1447 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1448 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1451 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1454 MSFT_NameIntro niName
;
1456 WCHAR
* pwstring
= NULL
;
1457 BSTR bstrName
= NULL
;
1461 ERR_(typelib
)("bad offset %d\n", offset
);
1464 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1465 pcx
->pTblDir
->pNametab
.offset
+offset
);
1466 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1467 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1468 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1469 name
[niName
.namelen
& 0xff]='\0';
1471 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1474 /* no invalid characters in string */
1477 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1479 /* don't check for invalid character since this has been done previously */
1480 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1482 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1483 lengthInChars
= SysStringLen(bstrName
);
1484 HeapFree(GetProcessHeap(), 0, pwstring
);
1487 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1491 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1498 if(offset
<0) return NULL
;
1499 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1500 if(length
<= 0) return 0;
1501 string
=TLB_Alloc(length
+1);
1502 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1503 string
[length
]='\0';
1505 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1506 string
, -1, NULL
, 0);
1508 /* no invalid characters in string */
1511 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1513 /* don't check for invalid character since this has been done previously */
1514 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1516 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1517 lengthInChars
= SysStringLen(bstr
);
1518 HeapFree(GetProcessHeap(), 0, pwstring
);
1521 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1525 * read a value and fill a VARIANT structure
1527 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1531 TRACE_(typelib
)("\n");
1533 if(offset
<0) { /* data are packed in here */
1534 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1535 V_I2(pVar
) = offset
& 0x3ffffff;
1538 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1539 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1540 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1541 switch (V_VT(pVar
)){
1542 case VT_EMPTY
: /* FIXME: is this right? */
1543 case VT_NULL
: /* FIXME: is this right? */
1544 case VT_I2
: /* this should not happen */
1555 case VT_VOID
: /* FIXME: is this right? */
1563 case VT_DECIMAL
: /* FIXME: is this right? */
1566 /* pointer types with known behaviour */
1569 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1571 FIXME("BSTR length = %d?\n", size
);
1573 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1574 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1575 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1576 /* FIXME: do we need a AtoW conversion here? */
1577 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1578 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1583 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1590 case VT_USERDEFINED
:
1596 case VT_STREAMED_OBJECT
:
1597 case VT_STORED_OBJECT
:
1598 case VT_BLOB_OBJECT
:
1603 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1607 if(size
>0) /* (big|small) endian correct? */
1608 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1612 * create a linked list with custom data
1614 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1620 TRACE_(typelib
)("\n");
1624 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1625 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1626 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1627 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1628 /* add new custom data at head of the list */
1629 pNew
->next
=*ppCustData
;
1631 offset
= entry
.next
;
1636 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1640 pTd
->vt
=type
& VT_TYPEMASK
;
1642 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1644 if(pTd
->vt
== VT_USERDEFINED
)
1645 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1647 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1651 MSFT_DoFuncs(TLBContext
* pcx
,
1656 TLBFuncDesc
** pptfd
)
1659 * member information is stored in a data structure at offset
1660 * indicated by the memoffset field of the typeinfo structure
1661 * There are several distinctive parts.
1662 * The first part starts with a field that holds the total length
1663 * of this (first) part excluding this field. Then follow the records,
1664 * for each member there is one record.
1666 * The first entry is always the length of the record (including this
1668 * The rest of the record depends on the type of the member. If there is
1669 * a field indicating the member type (function, variable, interface, etc)
1670 * I have not found it yet. At this time we depend on the information
1671 * in the type info and the usual order how things are stored.
1673 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1676 * Third is an equal sized array with file offsets to the name entry
1679 * The fourth and last (?) part is an array with offsets to the records
1680 * in the first part of this file segment.
1683 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1684 int recoffset
= offset
+ sizeof(INT
);
1687 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1689 TRACE_(typelib
)("\n");
1691 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1693 for ( i
= 0; i
< cFuncs
; i
++ )
1695 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1697 /* name, eventually add to a hash table */
1698 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1699 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1701 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1703 /* read the function information record */
1704 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1708 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1710 /* do the attributes */
1711 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1714 if ( nrattributes
> 0 )
1716 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1718 if ( nrattributes
> 1 )
1720 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1721 pFuncRec
->OptAttr
[1]) ;
1723 if ( nrattributes
> 2 )
1725 if ( pFuncRec
->FKCCIC
& 0x2000 )
1727 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1731 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1732 pFuncRec
->OptAttr
[2]);
1734 if( nrattributes
> 5 )
1736 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1738 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1741 pFuncRec
->OptAttr
[6],
1742 &(*pptfd
)->pCustData
);
1749 /* fill the FuncDesc Structure */
1750 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1751 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1753 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1754 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1755 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1756 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1757 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1758 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1759 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1763 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1766 /* do the parameters/arguments */
1767 if(pFuncRec
->nrargs
)
1770 MSFT_ParameterInfo paraminfo
;
1772 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1773 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1775 (*pptfd
)->pParamDesc
=
1776 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1778 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1779 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1781 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1783 TYPEDESC
* lpArgTypeDesc
= 0;
1787 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1790 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1793 if (paraminfo
.oName
== -1)
1794 /* this occurs for [propput] or [propget] methods, so
1795 * we should just set the name of the parameter to the
1796 * name of the method. */
1797 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1799 (*pptfd
)->pParamDesc
[j
].Name
=
1800 MSFT_ReadName( pcx
, paraminfo
.oName
);
1801 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1803 /* SEEK value = jump to offset,
1804 * from there jump to the end of record,
1805 * go back by (j-1) arguments
1807 MSFT_ReadLEDWords( ¶minfo
,
1808 sizeof(MSFT_ParameterInfo
), pcx
,
1809 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1810 * sizeof(MSFT_ParameterInfo
)));
1812 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1814 while ( lpArgTypeDesc
!= NULL
)
1816 switch ( lpArgTypeDesc
->vt
)
1819 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1823 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1826 case VT_USERDEFINED
:
1827 MSFT_DoRefType(pcx
, pTI
,
1828 lpArgTypeDesc
->u
.hreftype
);
1830 lpArgTypeDesc
= NULL
;
1834 lpArgTypeDesc
= NULL
;
1840 /* parameter is the return value! */
1841 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1843 TYPEDESC
* lpArgTypeDesc
;
1845 (*pptfd
)->funcdesc
.elemdescFunc
=
1846 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1848 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1850 while ( lpArgTypeDesc
!= NULL
)
1852 switch ( lpArgTypeDesc
->vt
)
1855 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1859 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1863 case VT_USERDEFINED
:
1866 lpArgTypeDesc
->u
.hreftype
);
1868 lpArgTypeDesc
= NULL
;
1872 lpArgTypeDesc
= NULL
;
1877 /* second time around */
1878 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1881 if ( (PARAMFLAG_FHASDEFAULT
&
1882 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1883 ((pFuncRec
->FKCCIC
) & 0x1000) )
1885 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1887 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1889 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1891 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1892 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1894 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1898 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1901 pFuncRec
->OptAttr
[7+j
],
1902 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1907 /* scode is not used: archaic win16 stuff FIXME: right? */
1908 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1909 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1911 pptfd
= & ((*pptfd
)->next
);
1912 recoffset
+= reclength
;
1916 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1917 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1919 int infolen
, nameoffset
, reclength
;
1921 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1925 TRACE_(typelib
)("\n");
1927 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1928 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1929 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1930 recoffset
+= offset
+sizeof(INT
);
1931 for(i
=0;i
<cVars
;i
++){
1932 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1933 /* name, eventually add to a hash table */
1934 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1935 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1936 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1937 /* read the variable information record */
1938 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1940 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1942 if(reclength
>(6*sizeof(INT
)) )
1943 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1944 if(reclength
>(7*sizeof(INT
)) )
1945 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1946 if(reclength
>(8*sizeof(INT
)) )
1947 if(reclength
>(9*sizeof(INT
)) )
1948 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1949 /* fill the VarDesc Structure */
1950 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1951 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1952 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1953 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1954 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1955 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1956 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1957 if(pVarRec
->VarKind
== VAR_CONST
){
1958 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1959 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1960 pVarRec
->OffsValue
, pcx
);
1962 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1963 pptvd
=&((*pptvd
)->next
);
1964 recoffset
+= reclength
;
1967 /* fill in data for a hreftype (offset). When the referenced type is contained
1968 * in the typelib, it's just an (file) offset in the type info base dir.
1969 * If comes from import, it's an offset+1 in the ImpInfo table
1971 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1975 TLBRefType
**ppRefType
= &pTI
->reflist
;
1977 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1980 if((*ppRefType
)->reference
== offset
)
1982 ppRefType
= &(*ppRefType
)->next
;
1985 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1986 sizeof(**ppRefType
));
1988 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1989 /* external typelib */
1990 MSFT_ImpInfo impinfo
;
1991 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1993 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1995 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1996 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1997 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1998 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1999 pImpLib
=pImpLib
->next
;
2002 (*ppRefType
)->reference
=offset
;
2003 (*ppRefType
)->pImpTLInfo
= pImpLib
;
2004 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2005 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
2006 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
2008 (*ppRefType
)->index
= impinfo
.oGuid
;
2010 ERR("Cannot find a reference\n");
2011 (*ppRefType
)->reference
=-1;
2012 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
2015 /* in this typelib */
2016 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
2017 (*ppRefType
)->reference
=offset
;
2018 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
2022 /* process Implemented Interfaces of a com class */
2023 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2027 MSFT_RefRecord refrec
;
2028 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2030 TRACE_(typelib
)("\n");
2032 for(i
=0;i
<count
;i
++){
2033 if(offset
<0) break; /* paranoia */
2034 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2035 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2036 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
2037 (*ppImpl
)->hRef
= refrec
.reftype
;
2038 (*ppImpl
)->implflags
=refrec
.flags
;
2039 (*ppImpl
)->ctCustData
=
2040 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2041 offset
=refrec
.onext
;
2042 ppImpl
=&((*ppImpl
)->next
);
2046 * process a typeinfo record
2048 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2051 ITypeLibImpl
* pLibInfo
)
2053 MSFT_TypeInfoBase tiBase
;
2054 ITypeInfoImpl
*ptiRet
;
2056 TRACE_(typelib
)("count=%u\n", count
);
2058 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2059 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2060 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2062 /* this is where we are coming from */
2063 ptiRet
->pTypeLib
= pLibInfo
;
2064 ptiRet
->index
=count
;
2065 /* fill in the typeattr fields */
2066 WARN("Assign constructor/destructor memid\n");
2068 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2069 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2070 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
2071 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
2072 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2073 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2074 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2075 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2076 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2077 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2078 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2079 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2080 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2081 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2082 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2083 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2084 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2085 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2088 /* IDLDESC idldescType; *//* never saw this one != zero */
2090 /* name, eventually add to a hash table */
2091 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2092 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2094 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2095 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2096 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2098 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2099 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2101 /* note: InfoType's Help file and HelpStringDll come from the containing
2102 * library. Further HelpString and Docstring appear to be the same thing :(
2105 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2106 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2107 ptiRet
->TypeAttr
.cVars
,
2108 tiBase
.memoffset
, & ptiRet
->funclist
);
2110 if(ptiRet
->TypeAttr
.cVars
>0 )
2111 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2112 ptiRet
->TypeAttr
.cVars
,
2113 tiBase
.memoffset
, & ptiRet
->varlist
);
2114 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2115 switch(ptiRet
->TypeAttr
.typekind
)
2118 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2121 case TKIND_DISPATCH
:
2122 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2124 if (tiBase
.datatype1
!= -1)
2126 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2127 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2130 { /* FIXME: This is a really bad hack to add IDispatch */
2131 const char* szStdOle
= "stdole2.tlb\0";
2132 int nStdOleLen
= strlen(szStdOle
);
2133 TLBRefType
**ppRef
= &ptiRet
->reflist
;
2136 if((*ppRef
)->reference
== -1)
2138 ppRef
= &(*ppRef
)->next
;
2141 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
2142 (*ppRef
)->guid
= IID_IDispatch
;
2143 (*ppRef
)->reference
= -1;
2144 (*ppRef
)->index
= TLB_REF_USE_GUID
;
2145 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
2146 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
2147 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
2150 MultiByteToWideChar(CP_ACP
,
2154 (*ppRef
)->pImpTLInfo
->name
,
2155 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
2157 (*ppRef
)->pImpTLInfo
->lcid
= 0;
2158 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
2159 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
2164 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2165 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2166 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2171 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2173 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2174 debugstr_w(ptiRet
->Name
),
2175 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2176 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2181 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2182 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2183 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2186 static ITypeLibImpl
*tlb_cache_first
;
2187 static CRITICAL_SECTION cache_section
;
2188 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2190 0, 0, &cache_section
,
2191 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2192 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2194 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2197 /****************************************************************************
2200 * find the type of the typelib file and map the typelib resource into
2203 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2204 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2205 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2207 ITypeLibImpl
*entry
;
2208 int ret
= TYPE_E_CANTLOADLIBRARY
;
2209 DWORD dwSignature
= 0;
2212 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2216 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2217 EnterCriticalSection(&cache_section
);
2218 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2220 if (!strcmpiW(entry
->path
, pszFileName
) && entry
->index
== index
)
2222 TRACE("cache hit\n");
2223 *ppTypeLib
= (ITypeLib2
*)entry
;
2224 ITypeLib_AddRef(*ppTypeLib
);
2225 LeaveCriticalSection(&cache_section
);
2229 LeaveCriticalSection(&cache_section
);
2231 /* check the signature of the file */
2232 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2233 if (INVALID_HANDLE_VALUE
!= hFile
)
2235 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2238 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2241 /* retrieve file size */
2242 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2244 /* first try to load as *.tlb */
2245 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2246 if ( dwSignature
== MSFT_SIGNATURE
)
2248 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2250 else if ( dwSignature
== SLTG_SIGNATURE
)
2252 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2254 UnmapViewOfFile(pBase
);
2256 CloseHandle(hMapping
);
2262 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName
));
2265 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2266 if (((WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
) || (dwSignature
== 0))
2268 /* find the typelibrary resource*/
2269 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2270 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2273 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2274 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2277 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2280 LPVOID pBase
= LockResource(hGlobal
);
2281 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2285 /* try to load as incore resource */
2286 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2287 if ( dwSignature
== MSFT_SIGNATURE
)
2289 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2291 else if ( dwSignature
== SLTG_SIGNATURE
)
2293 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2297 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2300 FreeResource( hGlobal
);
2303 FreeLibrary(hinstDLL
);
2308 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2310 TRACE("adding to cache\n");
2311 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2312 lstrcpyW(impl
->path
, pszFileName
);
2313 /* We should really canonicalise the path here. */
2314 impl
->index
= index
;
2316 /* FIXME: check if it has added already in the meantime */
2317 EnterCriticalSection(&cache_section
);
2318 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2320 tlb_cache_first
= impl
;
2321 LeaveCriticalSection(&cache_section
);
2324 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2329 /*================== ITypeLib(2) Methods ===================================*/
2331 /****************************************************************************
2332 * ITypeLib2_Constructor_MSFT
2334 * loading an MSFT typelib from an in-memory image
2336 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2340 MSFT_Header tlbHeader
;
2341 MSFT_SegDir tlbSegDir
;
2342 ITypeLibImpl
* pTypeLibImpl
;
2344 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2346 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2347 if (!pTypeLibImpl
) return NULL
;
2349 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2350 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2351 pTypeLibImpl
->ref
= 1;
2353 /* get pointer to beginning of typelib data */
2357 cx
.pLibInfo
= pTypeLibImpl
;
2358 cx
.length
= dwTLBLength
;
2361 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2363 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2364 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2365 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2368 /* there is a small amount of information here until the next important
2370 * the segment directory . Try to calculate the amount of data */
2371 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2373 /* now read the segment directory */
2374 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2375 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2376 cx
.pTblDir
= &tlbSegDir
;
2378 /* just check two entries */
2379 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2381 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2382 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2386 /* now fill our internal data */
2387 /* TLIBATTR fields */
2388 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2390 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2391 /* Windows seems to have zero here, is this correct? */
2392 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2393 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2395 pTypeLibImpl
->LibAttr
.lcid
= 0;
2397 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2398 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2399 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2400 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2402 /* name, eventually add to a hash table */
2403 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2406 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2407 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2409 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2412 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2413 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2416 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2419 if(tlbHeader
.CustomDataOffset
>= 0)
2421 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2424 /* fill in typedescriptions */
2425 if(tlbSegDir
.pTypdescTab
.length
> 0)
2427 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2429 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2430 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2433 /* FIXME: add several sanity checks here */
2434 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2435 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2437 /* FIXME: check safearray */
2439 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2441 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2443 else if(td
[0] == VT_CARRAY
)
2445 /* array descr table here */
2446 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2448 else if(td
[0] == VT_USERDEFINED
)
2450 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2452 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2455 /* second time around to fill the array subscript info */
2458 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2459 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2461 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2462 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2465 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2467 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2469 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2471 for(j
= 0; j
<td
[2]; j
++)
2473 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2474 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2475 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2476 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2481 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2482 ERR("didn't find array description data\n");
2487 /* imported type libs */
2488 if(tlbSegDir
.pImpFiles
.offset
>0)
2490 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2491 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2494 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2499 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2500 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2501 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2503 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2504 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2505 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2506 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2509 name
= TLB_Alloc(size
+1);
2510 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2511 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2512 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2513 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2516 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2517 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2519 ppImpLib
= &(*ppImpLib
)->next
;
2524 if(tlbHeader
.nrtypeinfos
>= 0 )
2526 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2527 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2530 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2532 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2534 ppTI
= &((*ppTI
)->next
);
2535 (pTypeLibImpl
->TypeInfoCount
)++;
2539 TRACE("(%p)\n", pTypeLibImpl
);
2540 return (ITypeLib2
*) pTypeLibImpl
;
2544 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2550 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2551 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2552 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2553 ret
= SysAllocString(nameW
);
2554 HeapFree(GetProcessHeap(), 0, nameW
);
2558 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2564 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2565 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2569 guid
->Data4
[0] = s
>> 8;
2570 guid
->Data4
[1] = s
& 0xff;
2573 for(i
= 0; i
< 6; i
++) {
2574 memcpy(b
, str
+ 24 + 2 * i
, 2);
2575 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2580 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2587 bytelen
= *(WORD
*)ptr
;
2588 if(bytelen
== 0xffff) return 2;
2589 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2590 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2591 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2592 *pBstr
= SysAllocStringLen(nameW
, len
);
2593 HeapFree(GetProcessHeap(), 0, nameW
);
2597 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2602 bytelen
= *(WORD
*)ptr
;
2603 if(bytelen
== 0xffff) return 2;
2604 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2605 memcpy(*str
, ptr
+ 2, bytelen
);
2606 (*str
)[bytelen
] = '\0';
2610 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2612 char *ptr
= pLibBlk
;
2615 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2616 FIXME("libblk magic = %04x\n", w
);
2621 if((w
= *(WORD
*)ptr
) != 0xffff) {
2622 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2627 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2629 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2631 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2634 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2637 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2638 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2640 pTypeLibImpl
->LibAttr
.lcid
= 0;
2643 ptr
+= 4; /* skip res12 */
2645 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2648 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2651 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2654 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2655 ptr
+= sizeof(GUID
);
2657 return ptr
- (char*)pLibBlk
;
2660 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2663 TYPEDESC
*pTD
= &pElem
->tdesc
;
2665 /* Handle [in/out] first */
2666 if((*pType
& 0xc000) == 0xc000)
2667 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2668 else if(*pType
& 0x8000)
2669 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2670 else if(*pType
& 0x4000)
2671 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2673 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2676 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2679 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2682 if((*pType
& 0xe00) == 0xe00) {
2684 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2686 pTD
= pTD
->u
.lptdesc
;
2688 switch(*pType
& 0x7f) {
2691 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2693 pTD
= pTD
->u
.lptdesc
;
2696 case VT_USERDEFINED
:
2697 pTD
->vt
= VT_USERDEFINED
;
2698 pTD
->u
.hreftype
= *(++pType
) / 4;
2704 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2707 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2709 pTD
->vt
= VT_CARRAY
;
2710 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2712 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2713 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2714 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2715 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2717 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2723 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2727 pTD
->vt
= VT_SAFEARRAY
;
2728 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2730 pTD
= pTD
->u
.lptdesc
;
2734 pTD
->vt
= *pType
& 0x7f;
2744 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2749 TLBRefType
**ppRefType
;
2751 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2752 FIXME("Ref magic = %x\n", pRef
->magic
);
2755 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2757 ppRefType
= &pTI
->reflist
;
2758 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2760 unsigned int lib_offs
, type_num
;
2762 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2763 sizeof(**ppRefType
));
2765 name
+= SLTG_ReadStringA(name
, &refname
);
2766 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2767 FIXME("Can't sscanf ref\n");
2768 if(lib_offs
!= 0xffff) {
2769 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2772 if((*import
)->offset
== lib_offs
)
2774 import
= &(*import
)->next
;
2777 char fname
[MAX_PATH
+1];
2780 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2782 (*import
)->offset
= lib_offs
;
2783 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2785 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2786 &(*import
)->wVersionMajor
,
2787 &(*import
)->wVersionMinor
,
2788 &(*import
)->lcid
, fname
) != 4) {
2789 FIXME("can't sscanf ref %s\n",
2790 pNameTable
+ lib_offs
+ 40);
2792 len
= strlen(fname
);
2793 if(fname
[len
-1] != '#')
2794 FIXME("fname = %s\n", fname
);
2795 fname
[len
-1] = '\0';
2796 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2798 (*ppRefType
)->pImpTLInfo
= *import
;
2799 } else { /* internal ref */
2800 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2802 (*ppRefType
)->reference
= ref
;
2803 (*ppRefType
)->index
= type_num
;
2805 HeapFree(GetProcessHeap(), 0, refname
);
2806 ppRefType
= &(*ppRefType
)->next
;
2808 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2809 FIXME("End of ref block magic = %x\n", *name
);
2810 dump_TLBRefType(pTI
->reflist
);
2813 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2816 SLTG_ImplInfo
*info
;
2817 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2818 /* I don't really get this structure, usually it's 0x16 bytes
2819 long, but iuser.tlb contains some that are 0x18 bytes long.
2820 That's ok because we can use the next ptr to jump to the next
2821 one. But how do we know the length of the last one? The WORD
2822 at offs 0x8 might be the clue. For now I'm just assuming that
2823 the last one is the regular 0x16 bytes. */
2825 info
= (SLTG_ImplInfo
*)pBlk
;
2827 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2828 sizeof(**ppImplType
));
2829 (*ppImplType
)->hRef
= info
->ref
;
2830 (*ppImplType
)->implflags
= info
->impltypeflags
;
2831 pTI
->TypeAttr
.cImplTypes
++;
2832 ppImplType
= &(*ppImplType
)->next
;
2834 if(info
->next
== 0xffff)
2837 FIXME("Interface inheriting more than one interface\n");
2838 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2840 info
++; /* see comment at top of function */
2844 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2847 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2848 SLTG_MemberHeader
*pMemHeader
;
2849 char *pFirstItem
, *pNextItem
;
2851 if(pTIHeader
->href_table
!= 0xffffffff) {
2852 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2857 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2859 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2861 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2862 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2865 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2869 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2872 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2873 SLTG_MemberHeader
*pMemHeader
;
2874 SLTG_Function
*pFunc
;
2875 char *pFirstItem
, *pNextItem
;
2876 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2879 if(pTIHeader
->href_table
!= 0xffffffff) {
2880 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2884 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2886 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2888 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2889 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2892 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2893 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2898 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2899 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2900 FIXME("func magic = %02x\n", pFunc
->magic
);
2903 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2904 sizeof(**ppFuncDesc
));
2905 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2907 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2908 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2909 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2910 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2911 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2912 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2914 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2915 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2917 if(pFunc
->retnextopt
& 0x80)
2918 pType
= &pFunc
->rettype
;
2920 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2923 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2925 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2926 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2927 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2928 (*ppFuncDesc
)->pParamDesc
=
2929 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2930 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2932 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2934 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2935 char *paramName
= pNameTable
+ *pArg
;
2937 /* If arg type follows then paramName points to the 2nd
2938 letter of the name, else the next WORD is an offset to
2939 the arg type and paramName points to the first letter.
2940 So let's take one char off paramName and see if we're
2941 pointing at an alpha-numeric char. However if *pArg is
2942 0xffff or 0xfffe then the param has no name, the former
2943 meaning that the next WORD is the type, the latter
2944 meaning the the next WORD is an offset to the type. */
2949 else if(*pArg
== 0xfffe) {
2953 else if(paramName
[-1] && !isalnum(paramName
[-1]))
2958 if(HaveOffs
) { /* the next word is an offset to type */
2959 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2960 SLTG_DoType(pType
, pFirstItem
,
2961 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2966 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2967 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2970 /* Are we an optional param ? */
2971 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2972 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2973 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2976 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2977 TLB_MultiByteToBSTR(paramName
);
2981 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2982 if(pFunc
->next
== 0xffff) break;
2984 pTI
->TypeAttr
.cFuncs
= num
;
2985 dump_TLBFuncDesc(pTI
->funclist
);
2986 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2989 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2992 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2993 SLTG_MemberHeader
*pMemHeader
;
2994 SLTG_RecordItem
*pItem
;
2996 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3001 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3003 pFirstItem
= (char*)(pMemHeader
+ 1);
3004 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
3005 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
3006 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
3007 FIXME("record magic = %02x\n", pItem
->magic
);
3010 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3011 sizeof(**ppVarDesc
));
3012 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3013 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3014 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
3015 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
3017 if(pItem
->typepos
== 0x02)
3018 pType
= &pItem
->type
;
3019 else if(pItem
->typepos
== 0x00)
3020 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
3022 FIXME("typepos = %02x\n", pItem
->typepos
);
3026 SLTG_DoType(pType
, pFirstItem
,
3027 &(*ppVarDesc
)->vardesc
.elemdescVar
);
3029 /* FIXME("helpcontext, helpstring\n"); */
3031 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
3033 ppVarDesc
= &((*ppVarDesc
)->next
);
3034 if(pItem
->next
== 0xffff) break;
3036 pTI
->TypeAttr
.cVars
= num
;
3037 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3040 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3043 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3044 SLTG_MemberHeader
*pMemHeader
;
3045 SLTG_AliasItem
*pItem
;
3048 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3049 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3052 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3053 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
3054 if (pItem
->vt
== 0xffff) {
3055 if (i
<(pMemHeader
->cbExtra
/4-1))
3056 FIXME("Endmarker too early in process alias data!\n");
3060 FIXME("Chain extends over last entry?\n");
3063 if (pItem
->vt
== VT_USERDEFINED
) {
3064 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
3065 /* guessing here ... */
3066 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
3067 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
3070 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
3071 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
3075 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3078 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3081 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3082 SLTG_MemberHeader
*pMemHeader
;
3083 SLTG_AliasItem
*pItem
;
3085 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3086 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3087 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
3088 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
3089 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3092 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3095 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3096 SLTG_MemberHeader
*pMemHeader
;
3097 SLTG_EnumItem
*pItem
;
3099 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3102 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3104 pFirstItem
= (char*)(pMemHeader
+ 1);
3105 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
3106 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
3107 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
3108 FIXME("enumitem magic = %04x\n", pItem
->magic
);
3111 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3112 sizeof(**ppVarDesc
));
3113 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3114 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3115 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3117 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3118 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
3119 *(INT
*)(pItem
->value
+ pFirstItem
);
3120 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
3121 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3122 /* FIXME("helpcontext, helpstring\n"); */
3124 ppVarDesc
= &((*ppVarDesc
)->next
);
3125 if(pItem
->next
== 0xffff) break;
3127 pTI
->TypeAttr
.cVars
= num
;
3128 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3131 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3132 managable copy of it into this */
3145 } SLTG_InternalOtherTypeInfo
;
3147 /****************************************************************************
3148 * ITypeLib2_Constructor_SLTG
3150 * loading a SLTG typelib from an in-memory image
3152 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3154 ITypeLibImpl
*pTypeLibImpl
;
3155 SLTG_Header
*pHeader
;
3156 SLTG_BlkEntry
*pBlkEntry
;
3160 LPVOID pBlk
, pFirstBlk
;
3161 SLTG_LibBlk
*pLibBlk
;
3162 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3163 char *pAfterOTIBlks
= NULL
;
3164 char *pNameTable
, *ptr
;
3167 ITypeInfoImpl
**ppTypeInfoImpl
;
3169 TRACE_(typelib
)("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3171 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
3172 if (!pTypeLibImpl
) return NULL
;
3174 pTypeLibImpl
->lpVtbl
= &tlbvt
;
3175 pTypeLibImpl
->ref
= 1;
3179 TRACE_(typelib
)("header:\n");
3180 TRACE_(typelib
)("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
3181 pHeader
->nrOfFileBlks
);
3182 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3183 FIXME("Header type magic 0x%08lx not supported.\n",
3184 pHeader
->SLTG_magic
);
3188 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3189 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3191 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3192 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3194 /* Next we have a magic block */
3195 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3197 /* Let's see if we're still in sync */
3198 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3199 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3200 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3203 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3204 sizeof(SLTG_DIR_MAGIC
))) {
3205 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3209 pIndex
= (SLTG_Index
*)(pMagic
+1);
3211 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3213 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3215 /* We'll set up a ptr to the main library block, which is the last one. */
3217 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3218 pBlkEntry
[order
].next
!= 0;
3219 order
= pBlkEntry
[order
].next
- 1, i
++) {
3220 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3224 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3226 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3231 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3233 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3234 sizeof(*pOtherTypeInfoBlks
) *
3235 pTypeLibImpl
->TypeInfoCount
);
3238 ptr
= (char*)pLibBlk
+ len
;
3240 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3244 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3246 w
= *(WORD
*)(ptr
+ 2);
3249 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3251 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3252 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3254 w
= *(WORD
*)(ptr
+ 4 + len
);
3256 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3258 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3260 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3261 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3263 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3264 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3265 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3267 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3269 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3272 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3273 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3274 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3275 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3276 len
+= sizeof(SLTG_OtherTypeInfo
);
3280 pAfterOTIBlks
= ptr
;
3282 /* Skip this WORD and get the next DWORD */
3283 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3285 /* Now add this to pLibBLk look at what we're pointing at and
3286 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3287 dust and we should be pointing at the beginning of the name
3290 pNameTable
= (char*)pLibBlk
+ len
;
3292 switch(*(WORD
*)pNameTable
) {
3299 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3303 pNameTable
+= 0x216;
3307 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3309 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3312 /* Hopefully we now have enough ptrs set up to actually read in
3313 some TypeInfos. It's not clear which order to do them in, so
3314 I'll just follow the links along the BlkEntry chain and read
3315 them in in the order in which they're in the file */
3317 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3319 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3320 pBlkEntry
[order
].next
!= 0;
3321 order
= pBlkEntry
[order
].next
- 1, i
++) {
3323 SLTG_TypeInfoHeader
*pTIHeader
;
3324 SLTG_TypeInfoTail
*pTITail
;
3326 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3327 pOtherTypeInfoBlks
[i
].index_name
)) {
3328 FIXME("Index strings don't match\n");
3333 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3334 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3337 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3338 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3339 (*ppTypeInfoImpl
)->index
= i
;
3340 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3341 pOtherTypeInfoBlks
[i
].name_offs
+
3343 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3344 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3346 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3347 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3348 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3349 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3350 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3352 if((pTIHeader
->typeflags1
& 7) != 2)
3353 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3354 if(pTIHeader
->typeflags3
!= 2)
3355 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3357 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3358 debugstr_w((*ppTypeInfoImpl
)->Name
),
3359 typekind_desc
[pTIHeader
->typekind
],
3360 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3361 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3363 switch(pTIHeader
->typekind
) {
3365 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3369 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3372 case TKIND_INTERFACE
:
3373 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3377 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3381 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3382 if (pTITail
->tdescalias_vt
)
3383 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3386 case TKIND_DISPATCH
:
3387 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3391 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3397 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3398 but we've already set those */
3399 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3400 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3401 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3403 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3425 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3426 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3429 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3430 FIXME("Somehow processed %d TypeInfos\n", i
);
3434 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3435 return (ITypeLib2
*)pTypeLibImpl
;
3438 /* ITypeLib::QueryInterface
3440 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3445 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3447 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3450 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3451 IsEqualIID(riid
,&IID_ITypeLib
)||
3452 IsEqualIID(riid
,&IID_ITypeLib2
))
3459 ITypeLib2_AddRef(iface
);
3460 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3463 TRACE("-- Interface: E_NOINTERFACE\n");
3464 return E_NOINTERFACE
;
3469 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3471 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3472 ULONG ref
= InterlockedIncrement(&This
->ref
);
3474 TRACE("(%p)->ref was %lu\n",This
, ref
- 1);
3479 /* ITypeLib::Release
3481 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3483 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3484 ULONG ref
= InterlockedDecrement(&This
->ref
);
3486 TRACE("(%p)->(%lu)\n",This
, ref
);
3490 /* remove cache entry */
3491 TRACE("removing from cache list\n");
3492 EnterCriticalSection(&cache_section
);
3493 if (This
->next
) This
->next
->prev
= This
->prev
;
3494 if (This
->prev
) This
->prev
->next
= This
->next
;
3495 else tlb_cache_first
= This
->next
;
3496 LeaveCriticalSection(&cache_section
);
3498 /* FIXME destroy child objects */
3499 TRACE(" destroying ITypeLib(%p)\n",This
);
3503 SysFreeString(This
->Name
);
3507 if (This
->DocString
)
3509 SysFreeString(This
->DocString
);
3510 This
->DocString
= NULL
;
3515 SysFreeString(This
->HelpFile
);
3516 This
->HelpFile
= NULL
;
3519 if (This
->HelpStringDll
)
3521 SysFreeString(This
->HelpStringDll
);
3522 This
->HelpStringDll
= NULL
;
3525 if (This
->pTypeInfo
) /* can be NULL */
3526 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3527 HeapFree(GetProcessHeap(),0,This
);
3534 /* ITypeLib::GetTypeInfoCount
3536 * Returns the number of type descriptions in the type library
3538 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3540 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3541 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3542 return This
->TypeInfoCount
;
3545 /* ITypeLib::GetTypeInfo
3547 * retrieves the specified type description in the library.
3549 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3552 ITypeInfo
**ppTInfo
)
3556 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3557 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3559 TRACE("(%p)->(index=%d)\n", This
, index
);
3561 if (!ppTInfo
) return E_INVALIDARG
;
3563 /* search element n in list */
3564 for(i
=0; i
< index
; i
++)
3566 pTypeInfo
= pTypeInfo
->next
;
3569 TRACE("-- element not found\n");
3570 return TYPE_E_ELEMENTNOTFOUND
;
3574 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3576 ITypeInfo_AddRef(*ppTInfo
);
3577 TRACE("-- found (%p)\n",*ppTInfo
);
3582 /* ITypeLibs::GetTypeInfoType
3584 * Retrieves the type of a type description.
3586 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3591 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3593 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3595 TRACE("(%p) index %d\n", This
, index
);
3597 if(!pTKind
) return E_INVALIDARG
;
3599 /* search element n in list */
3600 for(i
=0; i
< index
; i
++)
3604 TRACE("-- element not found\n");
3605 return TYPE_E_ELEMENTNOTFOUND
;
3607 pTInfo
= pTInfo
->next
;
3610 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3611 TRACE("-- found Type (%d)\n", *pTKind
);
3615 /* ITypeLib::GetTypeInfoOfGuid
3617 * Retrieves the type description that corresponds to the specified GUID.
3620 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3623 ITypeInfo
**ppTInfo
)
3625 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3626 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3628 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3630 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3632 /* search linked list for guid */
3633 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3635 pTypeInfo
= pTypeInfo
->next
;
3639 /* end of list reached */
3640 TRACE("-- element not found\n");
3641 return TYPE_E_ELEMENTNOTFOUND
;
3645 TRACE("-- found (%p, %s)\n",
3647 debugstr_w(pTypeInfo
->Name
));
3649 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3650 ITypeInfo_AddRef(*ppTInfo
);
3654 /* ITypeLib::GetLibAttr
3656 * Retrieves the structure that contains the library's attributes.
3659 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3661 LPTLIBATTR
*ppTLibAttr
)
3663 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3664 TRACE("(%p)\n",This
);
3665 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3666 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3670 /* ITypeLib::GetTypeComp
3672 * Enables a client compiler to bind to a library's types, variables,
3673 * constants, and global functions.
3676 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3678 ITypeComp
**ppTComp
)
3680 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3682 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3683 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3684 ITypeComp_AddRef(*ppTComp
);
3689 /* ITypeLib::GetDocumentation
3691 * Retrieves the library's documentation string, the complete Help file name
3692 * and path, and the context identifier for the library Help topic in the Help
3695 * On a successful return all non-null BSTR pointers will have been set,
3698 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3702 BSTR
*pBstrDocString
,
3703 DWORD
*pdwHelpContext
,
3704 BSTR
*pBstrHelpFile
)
3706 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3708 HRESULT result
= E_INVALIDARG
;
3713 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3715 pBstrName
, pBstrDocString
,
3716 pdwHelpContext
, pBstrHelpFile
);
3720 /* documentation for the typelib */
3725 if(!(*pBstrName
= SysAllocString(This
->Name
)))
3733 if (This
->DocString
)
3735 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
3738 else if (This
->Name
)
3740 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
3744 *pBstrDocString
= NULL
;
3748 *pdwHelpContext
= This
->dwHelpContext
;
3754 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
3758 *pBstrHelpFile
= NULL
;
3765 /* for a typeinfo */
3766 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3768 if(SUCCEEDED(result
))
3770 result
= ITypeInfo_GetDocumentation(pTInfo
,
3774 pdwHelpContext
, pBstrHelpFile
);
3776 ITypeInfo_Release(pTInfo
);
3781 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3783 if (pBstrName
) SysFreeString (*pBstrName
);
3785 return STG_E_INSUFFICIENTMEMORY
;
3790 * Indicates whether a passed-in string contains the name of a type or member
3791 * described in the library.
3794 static HRESULT WINAPI
ITypeLib2_fnIsName(
3800 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3801 ITypeInfoImpl
*pTInfo
;
3802 TLBFuncDesc
*pFInfo
;
3805 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3807 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3811 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3812 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3813 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3814 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3815 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3816 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3817 goto ITypeLib2_fnIsName_exit
;
3819 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3820 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3825 ITypeLib2_fnIsName_exit
:
3826 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3827 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3832 /* ITypeLib::FindName
3834 * Finds occurrences of a type description in a type library. This may be used
3835 * to quickly verify that a name exists in a type library.
3838 static HRESULT WINAPI
ITypeLib2_fnFindName(
3842 ITypeInfo
**ppTInfo
,
3846 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3847 ITypeInfoImpl
*pTInfo
;
3848 TLBFuncDesc
*pFInfo
;
3851 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3853 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3854 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3855 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3856 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3857 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
3858 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3859 goto ITypeLib2_fnFindName_exit
;
3862 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3863 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3865 ITypeLib2_fnFindName_exit
:
3866 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3867 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3870 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3871 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3878 /* ITypeLib::ReleaseTLibAttr
3880 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3883 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3885 TLIBATTR
*pTLibAttr
)
3887 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3888 TRACE("freeing (%p)\n",This
);
3889 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3893 /* ITypeLib2::GetCustData
3895 * gets the custom data
3897 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3902 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3903 TLBCustData
*pCData
;
3905 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3907 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3910 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3914 VariantInit( pVarVal
);
3915 VariantCopy( pVarVal
, &pCData
->data
);
3918 return E_INVALIDARG
; /* FIXME: correct? */
3921 /* ITypeLib2::GetLibStatistics
3923 * Returns statistics about a type library that are required for efficient
3924 * sizing of hash tables.
3927 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3929 ULONG
*pcUniqueNames
,
3930 ULONG
*pcchUniqueNames
)
3932 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3934 FIXME("(%p): stub!\n", This
);
3936 if(pcUniqueNames
) *pcUniqueNames
=1;
3937 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3941 /* ITypeLib2::GetDocumentation2
3943 * Retrieves the library's documentation string, the complete Help file name
3944 * and path, the localization context to use, and the context ID for the
3945 * library Help topic in the Help file.
3948 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3952 BSTR
*pbstrHelpString
,
3953 DWORD
*pdwHelpStringContext
,
3954 BSTR
*pbstrHelpStringDll
)
3956 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3960 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3962 /* the help string should be obtained from the helpstringdll,
3963 * using the _DLLGetDocumentation function, based on the supplied
3964 * lcid. Nice to do sometime...
3968 /* documentation for the typelib */
3970 *pbstrHelpString
=SysAllocString(This
->DocString
);
3971 if(pdwHelpStringContext
)
3972 *pdwHelpStringContext
=This
->dwHelpContext
;
3973 if(pbstrHelpStringDll
)
3974 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3980 /* for a typeinfo */
3981 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3983 if(SUCCEEDED(result
))
3985 ITypeInfo2
* pTInfo2
;
3986 result
= ITypeInfo_QueryInterface(pTInfo
,
3988 (LPVOID
*) &pTInfo2
);
3990 if(SUCCEEDED(result
))
3992 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3996 pdwHelpStringContext
,
3997 pbstrHelpStringDll
);
3999 ITypeInfo2_Release(pTInfo2
);
4002 ITypeInfo_Release(pTInfo
);
4008 /* ITypeLib2::GetAllCustData
4010 * Gets all custom data items for the library.
4013 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4015 CUSTDATA
*pCustData
)
4017 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4018 TLBCustData
*pCData
;
4020 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4021 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4022 if(pCustData
->prgCustData
){
4023 pCustData
->cCustData
=This
->ctCustData
;
4024 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4025 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4026 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4029 ERR(" OUT OF MEMORY!\n");
4030 return E_OUTOFMEMORY
;
4035 static const ITypeLib2Vtbl tlbvt
= {
4036 ITypeLib2_fnQueryInterface
,
4038 ITypeLib2_fnRelease
,
4039 ITypeLib2_fnGetTypeInfoCount
,
4040 ITypeLib2_fnGetTypeInfo
,
4041 ITypeLib2_fnGetTypeInfoType
,
4042 ITypeLib2_fnGetTypeInfoOfGuid
,
4043 ITypeLib2_fnGetLibAttr
,
4044 ITypeLib2_fnGetTypeComp
,
4045 ITypeLib2_fnGetDocumentation
,
4047 ITypeLib2_fnFindName
,
4048 ITypeLib2_fnReleaseTLibAttr
,
4050 ITypeLib2_fnGetCustData
,
4051 ITypeLib2_fnGetLibStatistics
,
4052 ITypeLib2_fnGetDocumentation2
,
4053 ITypeLib2_fnGetAllCustData
4057 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4059 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4061 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4064 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4066 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4068 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4071 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4073 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4075 return ITypeLib2_Release((ITypeLib2
*)This
);
4078 static HRESULT WINAPI
ITypeLibComp_fnBind(
4083 ITypeInfo
** ppTInfo
,
4084 DESCKIND
* pDescKind
,
4087 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4091 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4095 ITypeInfo
** ppTInfo
,
4096 ITypeComp
** ppTComp
)
4098 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4102 static const ITypeCompVtbl tlbtcvt
=
4105 ITypeLibComp_fnQueryInterface
,
4106 ITypeLibComp_fnAddRef
,
4107 ITypeLibComp_fnRelease
,
4109 ITypeLibComp_fnBind
,
4110 ITypeLibComp_fnBindType
4113 /*================== ITypeInfo(2) Methods ===================================*/
4114 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4116 ITypeInfoImpl
* pTypeInfoImpl
;
4118 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4121 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4122 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4123 pTypeInfoImpl
->ref
=1;
4125 TRACE("(%p)\n", pTypeInfoImpl
);
4126 return (ITypeInfo2
*) pTypeInfoImpl
;
4129 /* ITypeInfo::QueryInterface
4131 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4136 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4138 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4141 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4142 IsEqualIID(riid
,&IID_ITypeInfo
)||
4143 IsEqualIID(riid
,&IID_ITypeInfo2
))
4147 ITypeInfo_AddRef(iface
);
4148 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4151 TRACE("-- Interface: E_NOINTERFACE\n");
4152 return E_NOINTERFACE
;
4155 /* ITypeInfo::AddRef
4157 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4159 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4160 ULONG ref
= InterlockedIncrement(&This
->ref
);
4162 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4164 TRACE("(%p)->ref is %lu\n",This
, ref
);
4168 /* ITypeInfo::Release
4170 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4172 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4173 ULONG ref
= InterlockedDecrement(&This
->ref
);
4175 TRACE("(%p)->(%lu)\n",This
, ref
);
4178 /* We don't release ITypeLib when ref=0 because
4179 it means that function is called by ITypeLib2_Release */
4180 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4182 FIXME("destroy child objects\n");
4184 TRACE("destroying ITypeInfo(%p)\n",This
);
4187 SysFreeString(This
->Name
);
4191 if (This
->DocString
)
4193 SysFreeString(This
->DocString
);
4194 This
->DocString
= 0;
4199 SysFreeString(This
->DllName
);
4205 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4208 HeapFree(GetProcessHeap(),0,This
);
4214 /* ITypeInfo::GetTypeAttr
4216 * Retrieves a TYPEATTR structure that contains the attributes of the type
4220 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4221 LPTYPEATTR
*ppTypeAttr
)
4223 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4226 TRACE("(%p)\n",This
);
4228 size
= sizeof(**ppTypeAttr
);
4229 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4230 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
4232 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
4234 return E_OUTOFMEMORY
;
4236 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4238 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4239 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
4240 &This
->TypeAttr
.tdescAlias
, (void *)(*ppTypeAttr
+ 1));
4242 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
4243 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4245 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4246 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4251 /* ITypeInfo::GetTypeComp
4253 * Retrieves the ITypeComp interface for the type description, which enables a
4254 * client compiler to bind to the type description's members.
4257 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4258 ITypeComp
* *ppTComp
)
4260 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4262 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4264 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4265 ITypeComp_AddRef(*ppTComp
);
4269 /* ITypeInfo::GetFuncDesc
4271 * Retrieves the FUNCDESC structure that contains information about a
4272 * specified function.
4275 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4276 LPFUNCDESC
*ppFuncDesc
)
4278 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4280 TLBFuncDesc
* pFDesc
;
4281 TRACE("(%p) index %d\n", This
, index
);
4282 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4285 /* FIXME: must do a copy here */
4286 *ppFuncDesc
=&pFDesc
->funcdesc
;
4289 return E_INVALIDARG
;
4292 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
4296 SIZE_T size
= sizeof(*src
);
4298 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
4299 if (src
->varkind
== VAR_CONST
)
4300 size
+= sizeof(VARIANT
);
4301 size
+= TLB_SizeTypeDesc(&src
->elemdescVar
.tdesc
, FALSE
);
4302 if (src
->elemdescVar
.u
.paramdesc
.pparamdescex
)
4303 size
+= sizeof(*src
->elemdescVar
.u
.paramdesc
.pparamdescex
);
4305 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
4306 if (!dest
) return E_OUTOFMEMORY
;
4309 buffer
= (char *)(dest
+ 1);
4310 if (src
->lpstrSchema
)
4313 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
4314 len
= strlenW(src
->lpstrSchema
);
4315 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
4316 buffer
+= (len
+ 1) * sizeof(WCHAR
);
4319 if (src
->varkind
== VAR_CONST
)
4323 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
4324 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
4325 buffer
+= sizeof(VARIANT
);
4326 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
4329 SysFreeString((BSTR
)dest_ptr
);
4333 buffer
= TLB_CopyTypeDesc(&dest
->elemdescVar
.tdesc
, &src
->elemdescVar
.tdesc
, buffer
);
4334 if (src
->elemdescVar
.u
.paramdesc
.pparamdescex
)
4336 PARAMDESCEX
*pparamdescex_src
= src
->elemdescVar
.u
.paramdesc
.pparamdescex
;
4337 PARAMDESCEX
*pparamdescex_dest
= dest
->elemdescVar
.u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)buffer
;
4339 buffer
+= sizeof(PARAMDESCEX
);
4340 *pparamdescex_dest
= *pparamdescex_src
;
4341 hr
= VariantCopy(&pparamdescex_dest
->varDefaultValue
, &pparamdescex_src
->varDefaultValue
);
4344 if (src
->varkind
== VAR_CONST
)
4345 VariantClear(dest
->u
.lpvarValue
);
4346 SysFreeString((BSTR
)dest
);
4354 /* ITypeInfo::GetVarDesc
4356 * Retrieves a VARDESC structure that describes the specified variable.
4359 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4360 LPVARDESC
*ppVarDesc
)
4362 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4364 TLBVarDesc
* pVDesc
;
4365 TRACE("(%p) index %d\n", This
, index
);
4366 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4370 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
4372 return E_INVALIDARG
;
4375 /* ITypeInfo_GetNames
4377 * Retrieves the variable with the specified member ID (or the name of the
4378 * property or method and its parameters) that correspond to the specified
4381 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4382 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4384 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4385 TLBFuncDesc
* pFDesc
;
4386 TLBVarDesc
* pVDesc
;
4388 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4389 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4392 /* function found, now return function and parameter names */
4393 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4396 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4398 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4404 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4407 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4412 if(This
->TypeAttr
.cImplTypes
&&
4413 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4414 /* recursive search */
4417 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4419 if(SUCCEEDED(result
))
4421 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4422 ITypeInfo_Release(pTInfo
);
4425 WARN("Could not search inherited interface!\n");
4429 WARN("no names found\n");
4432 return TYPE_E_ELEMENTNOTFOUND
;
4439 /* ITypeInfo::GetRefTypeOfImplType
4441 * If a type description describes a COM class, it retrieves the type
4442 * description of the implemented interface types. For an interface,
4443 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4447 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4452 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4455 TLBImplType
*pImpl
= This
->impltypelist
;
4457 TRACE("(%p) index %d\n", This
, index
);
4458 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4462 /* only valid on dual interfaces;
4463 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4465 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4467 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4468 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4474 hr
= TYPE_E_ELEMENTNOTFOUND
;
4479 /* get element n from linked list */
4480 for(i
=0; pImpl
&& i
<index
; i
++)
4482 pImpl
= pImpl
->next
;
4486 *pRefType
= pImpl
->hRef
;
4488 hr
= TYPE_E_ELEMENTNOTFOUND
;
4494 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType
);
4496 TRACE("FAILURE -- hresult = 0x%08lx\n", hr
);
4502 /* ITypeInfo::GetImplTypeFlags
4504 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4505 * or base interface in a type description.
4507 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4508 UINT index
, INT
*pImplTypeFlags
)
4510 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4514 TRACE("(%p) index %d\n", This
, index
);
4515 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4516 i
++, pImpl
=pImpl
->next
)
4518 if(i
==index
&& pImpl
){
4519 *pImplTypeFlags
=pImpl
->implflags
;
4523 return TYPE_E_ELEMENTNOTFOUND
;
4527 * Maps between member names and member IDs, and parameter names and
4530 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4531 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4533 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4534 TLBFuncDesc
* pFDesc
;
4535 TLBVarDesc
* pVDesc
;
4538 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4540 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4542 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4543 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4544 for(i
=1; i
< cNames
; i
++){
4545 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4546 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4548 if( j
<pFDesc
->funcdesc
.cParams
)
4551 ret
=DISP_E_UNKNOWNNAME
;
4556 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4557 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4558 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4562 /* not found, see if this is and interface with an inheritance */
4563 if(This
->TypeAttr
.cImplTypes
&&
4564 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4565 /* recursive search */
4567 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4568 This
->impltypelist
->hRef
, &pTInfo
);
4570 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4571 ITypeInfo_Release(pTInfo
);
4574 WARN("Could not search inherited interface!\n");
4576 WARN("no names found\n");
4577 return DISP_E_UNKNOWNNAME
;
4580 /* ITypeInfo::Invoke
4582 * Invokes a method, or accesses a property of an object, that implements the
4583 * interface described by the type description.
4586 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4589 if (TRACE_ON(ole
)) {
4591 TRACE("Calling %p(",func
);
4592 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4604 res
= func(args
[0]);
4607 res
= func(args
[0],args
[1]);
4610 res
= func(args
[0],args
[1],args
[2]);
4613 res
= func(args
[0],args
[1],args
[2],args
[3]);
4616 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4619 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4622 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4625 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4628 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4631 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
4634 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
4637 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]);
4640 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]);
4643 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]);
4646 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4652 FIXME("unsupported calling convention %d\n",callconv
);
4656 TRACE("returns %08lx\n",res
);
4660 extern int _argsize(DWORD vt
);
4662 /****************************************************************************
4663 * Helper functions for Dispcall / Invoke, which copies one variant
4664 * with target type onto the argument stack.
4667 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4668 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4670 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4673 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4674 memcpy(argpos
,&arg
,sizeof(void*));
4678 if (V_VT(arg
) == vt
) {
4679 memcpy(argpos
, &V_I4(arg
), arglen
);
4683 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4684 memcpy(argpos
, &V_ARRAY(arg
), sizeof(SAFEARRAY
*));
4688 if (vt
== VT_VARIANT
) {
4689 memcpy(argpos
, arg
, arglen
);
4692 /* Deref BYREF vars if there is need */
4693 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4694 memcpy(argpos
,(void*)V_I4(arg
), arglen
);
4697 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4698 /* in this context, if the type lib specifies IUnknown*, giving an
4699 IDispatch* is correct; so, don't invoke VariantChangeType */
4700 memcpy(argpos
,&V_I4(arg
), arglen
);
4703 if ((vt
== VT_PTR
) && tdesc
)
4704 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4706 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4707 ITypeInfo
*tinfo2
= NULL
;
4708 TYPEATTR
*tattr
= NULL
;
4711 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4713 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4714 "while coercing from vt 0x%x. Copying 4 byte.\n",
4715 tdesc
->u
.hreftype
,V_VT(arg
));
4716 memcpy(argpos
, &V_I4(arg
), 4);
4719 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4722 ERR("GetTypeAttr failed\n");
4723 ITypeInfo_Release(tinfo2
);
4726 switch (tattr
->typekind
) {
4728 switch ( V_VT( arg
) ) {
4730 *argpos
= V_I2(arg
);
4734 memcpy(argpos
, &V_I4(arg
), 4);
4737 case VT_BYREF
|VT_I4
:
4738 memcpy(argpos
, V_I4REF(arg
), 4);
4742 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4749 tdesc
= &(tattr
->tdescAlias
);
4750 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4753 case TKIND_INTERFACE
:
4754 if (V_VT(arg
) == VT_DISPATCH
) {
4756 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4757 memcpy(argpos
, &V_DISPATCH(arg
), 4);
4761 hres
=IUnknown_QueryInterface(V_DISPATCH(arg
),
4762 &IID_IDispatch
,(LPVOID
*)&disp
);
4763 if (SUCCEEDED(hres
)) {
4764 memcpy(argpos
,&disp
,4);
4765 IUnknown_Release(V_DISPATCH(arg
));
4769 FIXME("Failed to query IDispatch interface from %s while "
4770 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4774 if (V_VT(arg
) == VT_UNKNOWN
) {
4775 memcpy(argpos
, &V_UNKNOWN(arg
), 4);
4779 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4780 V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4784 case TKIND_DISPATCH
:
4785 if (V_VT(arg
) == VT_DISPATCH
) {
4786 memcpy(argpos
, &V_DISPATCH(arg
), 4);
4791 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4795 FIXME("TKIND_RECORD unhandled.\n");
4799 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4803 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4804 ITypeInfo_Release(tinfo2
);
4809 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4810 memcpy(argpos
,&V_I4(&va
), arglen
);
4811 FIXME("Should not use VariantChangeType here."
4812 " (conversion from 0x%x -> 0x%x) %08lx\n",
4813 V_VT(arg
), vt
, *argpos
4817 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4821 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, TYPEDESC
*tdesc
, VARTYPE
*vt
)
4824 ITypeInfo
*tinfo2
= NULL
;
4825 TYPEATTR
*tattr
= NULL
;
4827 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
4830 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4832 tdesc
->u
.hreftype
, hr
);
4835 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
4838 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr
);
4839 ITypeInfo_Release(tinfo2
);
4843 switch (tattr
->typekind
)
4850 tdesc
= &tattr
->tdescAlias
;
4851 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
4854 case TKIND_INTERFACE
:
4855 if (IsEqualIID(&IID_IDispatch
, &tattr
->guid
))
4861 case TKIND_DISPATCH
:
4866 FIXME("TKIND_RECORD unhandled.\n");
4871 FIXME("TKIND_RECORD unhandled.\n");
4876 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4880 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4881 ITypeInfo_Release(tinfo2
);
4885 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, TYPEDESC
*tdesc
, VARTYPE
*vt
)
4889 /* enforce only one level of pointer indirection */
4890 if (!(*vt
& VT_BYREF
) && (tdesc
->vt
== VT_PTR
))
4892 tdesc
= tdesc
->u
.lptdesc
;
4894 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4895 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4896 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4897 if ((tdesc
->vt
== VT_USERDEFINED
) ||
4898 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
4900 VARTYPE vt_userdefined
= 0;
4901 TYPEDESC
*tdesc_userdefined
= tdesc
;
4902 if (tdesc
->vt
== VT_PTR
)
4904 vt_userdefined
= VT_BYREF
;
4905 tdesc_userdefined
= tdesc
->u
.lptdesc
;
4907 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
4909 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
4910 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
4912 *vt
|= vt_userdefined
;
4924 case VT_USERDEFINED
:
4925 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
4928 ERR("cannot convert VT_PTR into variant VT\n");
4938 /***********************************************************************
4939 * DispCallFunc (OLEAUT32.@)
4943 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4944 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
4946 int i
, argsize
, argspos
;
4950 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4951 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
4952 pvargResult
, V_VT(pvargResult
));
4954 /* DispCallFunc is only used to invoke methods belonging to an
4955 * IDispatch-derived COM interface. So we need to add a first parameter
4956 * to the list of arguments, to supply the interface pointer */
4958 for (i
=0;i
<cActuals
;i
++)
4960 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4961 dump_Variant(prgpvarg
[i
]);
4962 argsize
+= _argsize(prgvt
[i
]);
4964 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4965 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4967 for (i
=0;i
<cActuals
;i
++)
4969 VARIANT
*arg
= prgpvarg
[i
];
4970 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4971 memcpy(&args
[argspos
], &V_NONE(arg
), _argsize(prgvt
[i
]) * sizeof(DWORD
));
4972 argspos
+= _argsize(prgvt
[i
]);
4975 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/sizeof(void *)],cc
,argsize
,args
);
4976 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
4978 TRACE("Method returned 0x%08lx\n",hres
);
4979 V_VT(pvargResult
) = vtReturn
;
4980 V_UI4(pvargResult
) = hres
;
4983 HeapFree(GetProcessHeap(),0,args
);
4987 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4992 DISPPARAMS
*pDispParams
,
4993 VARIANT
*pVarResult
,
4994 EXCEPINFO
*pExcepInfo
,
4997 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4999 unsigned int func_index
, var_index
;
5003 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
5004 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
5006 dump_DispParms(pDispParams
);
5008 hres
= ITypeInfo2_GetFuncIndexOfMemId(iface
, memid
, dwFlags
, &func_index
);
5009 if (SUCCEEDED(hres
)) {
5010 FUNCDESC
*func_desc
;
5012 hres
= ITypeInfo2_GetFuncDesc(iface
, func_index
, &func_desc
);
5013 if(FAILED(hres
)) return hres
;
5016 TRACE("invoking:\n");
5017 dump_FUNCDESC(func_desc
);
5020 switch (func_desc
->funckind
) {
5021 case FUNC_PUREVIRTUAL
:
5022 case FUNC_VIRTUAL
: {
5024 int numargs
, numargs2
, argspos
, args2pos
;
5025 DWORD
*args
, *args2
;
5026 VARIANT
*rgvarg
= HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT
) * func_desc
->cParams
);
5027 memcpy(rgvarg
,pDispParams
->rgvarg
,sizeof(VARIANT
)*pDispParams
->cArgs
);
5030 numargs
= 1; /* sizeof(thisptr) */
5032 for (i
= 0; i
< func_desc
->cParams
; i
++) {
5033 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
5035 numargs
+= _argsize(tdesc
->vt
);
5036 if (i
>=pDispParams
->cArgs
) { /* arguments to return */
5037 if (tdesc
->vt
== VT_PTR
) {
5038 numargs2
+= _argsize(tdesc
->u
.lptdesc
->vt
);
5040 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc
->vt
);
5041 numargs2
+= _argsize(tdesc
->vt
);
5046 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
5047 args2
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DWORD
)*numargs2
);
5049 args
[0] = (DWORD
)pIUnk
;
5050 argspos
= 1; args2pos
= 0;
5051 for (i
= 0; i
< func_desc
->cParams
; i
++) {
5052 ELEMDESC
*elemdesc
= &(func_desc
->lprgelemdescParam
[i
]);
5053 TYPEDESC
*tdesc
= &(elemdesc
->tdesc
);
5054 USHORT paramFlags
= elemdesc
->u
.paramdesc
.wParamFlags
;
5055 int arglen
= _argsize(tdesc
->vt
);
5057 if (i
<pDispParams
->cArgs
) {
5058 VARIANT
*arg
= &rgvarg
[pDispParams
->cArgs
-i
-1];
5060 if (paramFlags
& PARAMFLAG_FOPT
) {
5061 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
5062 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5063 if(V_VT(arg
) == VT_EMPTY
5064 || ((V_ISBYREF(arg
)) && !V_BYREF(arg
))) {
5065 /* FIXME: Documentation says that we do this when parameter is left unspecified.
5066 How to determine it? */
5068 if(paramFlags
& PARAMFLAG_FHASDEFAULT
)
5069 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5070 V_VT(arg
) = VT_ERROR
;
5071 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
5072 arglen
= _argsize(VT_ERROR
);
5075 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
5076 if (FAILED(hres
)) goto func_fail
;
5078 } else if (paramFlags
& PARAMFLAG_FOPT
) {
5079 VARIANT
*arg
= &rgvarg
[i
];
5081 if (i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
5082 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5083 if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
5084 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5086 V_VT(arg
) = VT_ERROR
;
5087 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
5088 arglen
= _argsize(VT_ERROR
);
5089 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
5090 if (FAILED(hres
)) goto func_fail
;
5093 if (tdesc
->vt
== VT_PTR
)
5094 arglen
= _argsize(tdesc
->u
.lptdesc
->vt
);
5096 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
5098 /* Supply pointers for the rest, so propertyget works*/
5099 args
[argspos
] = (DWORD
)&args2
[args2pos
];
5101 /* If pointer to variant, pass reference it. */
5102 if ((tdesc
->vt
== VT_PTR
) &&
5103 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
5106 args
[argspos
]= (DWORD
)pVarResult
;
5111 if (func_desc
->cParamsOpt
< 0)
5112 FIXME("Does not support optional parameters (%d)\n", func_desc
->cParamsOpt
);
5114 res
= _invoke((*(FARPROC
**)pIUnk
)[func_desc
->oVft
/4],
5115 func_desc
->callconv
,
5121 for (i
= 0; i
< func_desc
->cParams
; i
++) {
5122 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5123 if (wParamFlags
& PARAMFLAG_FRETVAL
) {
5124 ELEMDESC
*elemdesc
= &func_desc
->lprgelemdescParam
[i
];
5125 TYPEDESC
*tdesc
= &elemdesc
->tdesc
;
5126 VARIANTARG varresult
;
5127 V_VT(&varresult
) = 0;
5128 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &V_VT(&varresult
));
5131 /* FIXME: this is really messy - we should keep the
5132 * args in VARIANTARGs rather than a DWORD array */
5133 memcpy(&V_UI4(&varresult
), &args
[i
+1], sizeof(DWORD
));
5136 TRACE("varresult: ");
5137 dump_Variant(&varresult
);
5139 hres
= VariantCopyInd(pVarResult
, &varresult
);
5140 /* free data stored in varresult. Note that
5141 * VariantClear doesn't do what we want because we are
5142 * working with byref types. */
5143 /* FIXME: clear safearrays, bstrs, records and
5144 * variants here too */
5145 if ((V_VT(&varresult
) == (VT_UNKNOWN
| VT_BYREF
)) ||
5146 (V_VT(&varresult
) == (VT_DISPATCH
| VT_BYREF
)))
5148 if(*V_UNKNOWNREF(&varresult
))
5149 IUnknown_Release(*V_UNKNOWNREF(&varresult
));
5156 if ((func_desc
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
) && FAILED(res
)) {
5157 WARN("invoked function failed with error 0x%08lx\n", res
);
5158 hres
= DISP_E_EXCEPTION
;
5159 if (pExcepInfo
) pExcepInfo
->scode
= res
;
5162 HeapFree(GetProcessHeap(), 0, rgvarg
);
5163 HeapFree(GetProcessHeap(),0,args2
);
5164 HeapFree(GetProcessHeap(),0,args
);
5167 case FUNC_DISPATCH
: {
5170 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
5171 if (SUCCEEDED(hres
)) {
5172 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5173 hres
= IDispatch_Invoke(
5174 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
5175 pVarResult
,pExcepInfo
,pArgErr
5178 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres
);
5179 IDispatch_Release(disp
);
5181 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5185 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
5190 ITypeInfo2_ReleaseFuncDesc(iface
, func_desc
);
5191 TRACE("-- 0x%08lx\n", hres
);
5194 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
5197 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
5198 if(FAILED(hres
)) return hres
;
5200 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5201 dump_VARDESC(var_desc
);
5202 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
5206 /* not found, look for it in inherited interfaces */
5207 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
5208 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
5210 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface
, 0, &ref_type
))) {
5211 /* recursive search */
5213 hres
= ITypeInfo_GetRefTypeInfo(iface
, ref_type
, &pTInfo
);
5214 if(SUCCEEDED(hres
)){
5215 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
5216 ITypeInfo_Release(pTInfo
);
5219 WARN("Could not search inherited interface!\n");
5222 ERR("did not find member id %08lx, flags %d!\n", memid
, dwFlags
);
5223 return DISP_E_MEMBERNOTFOUND
;
5226 /* ITypeInfo::GetDocumentation
5228 * Retrieves the documentation string, the complete Help file name and path,
5229 * and the context ID for the Help topic for a specified type description.
5231 * (Can be tested by the Visual Basic Editor in Word for instance.)
5233 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
5234 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
5235 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
5237 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5238 TLBFuncDesc
* pFDesc
;
5239 TLBVarDesc
* pVDesc
;
5240 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5241 " HelpContext(%p) HelpFile(%p)\n",
5242 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
5243 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5245 *pBstrName
=SysAllocString(This
->Name
);
5247 *pBstrDocString
=SysAllocString(This
->DocString
);
5249 *pdwHelpContext
=This
->dwHelpContext
;
5251 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
5253 }else {/* for a member */
5254 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5255 if(pFDesc
->funcdesc
.memid
==memid
){
5257 *pBstrName
= SysAllocString(pFDesc
->Name
);
5259 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
5261 *pdwHelpContext
=pFDesc
->helpcontext
;
5264 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5265 if(pVDesc
->vardesc
.memid
==memid
){
5267 *pBstrName
= SysAllocString(pVDesc
->Name
);
5269 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
5271 *pdwHelpContext
=pVDesc
->HelpContext
;
5275 WARN("member %ld not found\n", memid
);
5276 return TYPE_E_ELEMENTNOTFOUND
;
5279 /* ITypeInfo::GetDllEntry
5281 * Retrieves a description or specification of an entry point for a function
5284 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5285 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5288 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5289 TLBFuncDesc
*pFDesc
;
5291 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5293 if (pBstrDllName
) *pBstrDllName
= NULL
;
5294 if (pBstrName
) *pBstrName
= NULL
;
5295 if (pwOrdinal
) *pwOrdinal
= 0;
5297 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
5298 return TYPE_E_BADMODULEKIND
;
5300 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5301 if(pFDesc
->funcdesc
.memid
==memid
){
5302 dump_TypeInfo(This
);
5303 dump_TLBFuncDescOne(pFDesc
);
5306 *pBstrDllName
= SysAllocString(This
->DllName
);
5308 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5310 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5318 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5321 return TYPE_E_ELEMENTNOTFOUND
;
5324 /* ITypeInfo::GetRefTypeInfo
5326 * If a type description references other type descriptions, it retrieves
5327 * the referenced type descriptions.
5329 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5332 ITypeInfo
**ppTInfo
)
5334 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5335 HRESULT result
= E_FAIL
;
5337 if (hRefType
== -1 &&
5338 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5339 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5341 /* when we meet a DUAL dispinterface, we must create the interface
5344 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5347 /* the interface version contains the same information as the dispinterface
5348 * copy the contents of the structs.
5350 *pTypeInfoImpl
= *This
;
5351 pTypeInfoImpl
->ref
= 1;
5353 /* change the type to interface */
5354 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5356 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5358 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
5363 TLBRefType
*pRefType
;
5364 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5365 if(pRefType
->reference
== hRefType
)
5369 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
5370 if(pRefType
&& hRefType
!= -1) {
5371 ITypeLib
*pTLib
= NULL
;
5373 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5375 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5377 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5378 TRACE("typeinfo in imported typelib that is already loaded\n");
5379 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5380 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5383 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5384 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5385 pRefType
->pImpTLInfo
->wVersionMajor
,
5386 pRefType
->pImpTLInfo
->wVersionMinor
,
5387 pRefType
->pImpTLInfo
->lcid
,
5390 if(!SUCCEEDED(result
)) {
5391 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5392 result
=LoadTypeLib(libnam
, &pTLib
);
5393 SysFreeString(libnam
);
5395 if(SUCCEEDED(result
)) {
5396 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5397 ITypeLib2_AddRef(pTLib
);
5401 if(SUCCEEDED(result
)) {
5402 if(pRefType
->index
== TLB_REF_USE_GUID
)
5403 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5407 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5411 ITypeLib2_Release(pTLib
);
5415 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
5416 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5420 /* ITypeInfo::AddressOfMember
5422 * Retrieves the addresses of static functions or variables, such as those
5425 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5426 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5428 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5429 FIXME("(%p) stub!\n", This
);
5433 /* ITypeInfo::CreateInstance
5435 * Creates a new instance of a type that describes a component object class
5438 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
5439 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
5441 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5442 FIXME("(%p) stub!\n", This
);
5446 /* ITypeInfo::GetMops
5448 * Retrieves marshalling information.
5450 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
5453 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5454 FIXME("(%p) stub!\n", This
);
5458 /* ITypeInfo::GetContainingTypeLib
5460 * Retrieves the containing type library and the index of the type description
5461 * within that type library.
5463 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
5464 ITypeLib
* *ppTLib
, UINT
*pIndex
)
5466 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5468 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5470 *pIndex
=This
->index
;
5471 TRACE("returning pIndex=%d\n", *pIndex
);
5475 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
5476 ITypeLib2_AddRef(*ppTLib
);
5477 TRACE("returning ppTLib=%p\n", *ppTLib
);
5483 /* ITypeInfo::ReleaseTypeAttr
5485 * Releases a TYPEATTR previously returned by GetTypeAttr.
5488 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
5489 TYPEATTR
* pTypeAttr
)
5491 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5492 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
5493 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
5496 /* ITypeInfo::ReleaseFuncDesc
5498 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5500 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
5502 FUNCDESC
*pFuncDesc
)
5504 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5505 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
5508 /* ITypeInfo::ReleaseVarDesc
5510 * Releases a VARDESC previously returned by GetVarDesc.
5512 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5515 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5516 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5518 if (pVarDesc
->elemdescVar
.u
.paramdesc
.pparamdescex
)
5519 VariantClear(&pVarDesc
->elemdescVar
.u
.paramdesc
.pparamdescex
->varDefaultValue
);
5520 if (pVarDesc
->varkind
== VAR_CONST
)
5521 VariantClear(pVarDesc
->u
.lpvarValue
);
5522 SysFreeString((BSTR
)pVarDesc
);
5525 /* ITypeInfo2::GetTypeKind
5527 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5530 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5531 TYPEKIND
*pTypeKind
)
5533 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5534 *pTypeKind
=This
->TypeAttr
.typekind
;
5535 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5539 /* ITypeInfo2::GetTypeFlags
5541 * Returns the type flags without any allocations. This returns a DWORD type
5542 * flag, which expands the type flags without growing the TYPEATTR (type
5546 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5548 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5549 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5550 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5554 /* ITypeInfo2::GetFuncIndexOfMemId
5555 * Binds to a specific member based on a known DISPID, where the member name
5556 * is not known (for example, when binding to a default member).
5559 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5560 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5562 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5563 TLBFuncDesc
*pFuncInfo
;
5567 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
5568 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
5574 result
= TYPE_E_ELEMENTNOTFOUND
;
5576 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5577 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5581 /* TypeInfo2::GetVarIndexOfMemId
5583 * Binds to a specific member based on a known DISPID, where the member name
5584 * is not known (for example, when binding to a default member).
5587 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5588 MEMBERID memid
, UINT
*pVarIndex
)
5590 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5591 TLBVarDesc
*pVarInfo
;
5594 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5595 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5601 result
= TYPE_E_ELEMENTNOTFOUND
;
5603 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5604 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5608 /* ITypeInfo2::GetCustData
5610 * Gets the custom data
5612 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5617 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5618 TLBCustData
*pCData
;
5620 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5621 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5623 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5627 VariantInit( pVarVal
);
5628 VariantCopy( pVarVal
, &pCData
->data
);
5631 return E_INVALIDARG
; /* FIXME: correct? */
5634 /* ITypeInfo2::GetFuncCustData
5636 * Gets the custom data
5638 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5644 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5645 TLBCustData
*pCData
=NULL
;
5646 TLBFuncDesc
* pFDesc
;
5648 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5649 pFDesc
=pFDesc
->next
);
5652 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5653 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5655 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5658 VariantInit( pVarVal
);
5659 VariantCopy( pVarVal
, &pCData
->data
);
5662 return E_INVALIDARG
; /* FIXME: correct? */
5665 /* ITypeInfo2::GetParamCustData
5667 * Gets the custom data
5669 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5676 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5677 TLBCustData
*pCData
=NULL
;
5678 TLBFuncDesc
* pFDesc
;
5681 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5683 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5684 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5685 pCData
= pCData
->next
)
5686 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5688 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5692 VariantInit( pVarVal
);
5693 VariantCopy( pVarVal
, &pCData
->data
);
5696 return E_INVALIDARG
; /* FIXME: correct? */
5699 /* ITypeInfo2::GetVarCustData
5701 * Gets the custom data
5703 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5709 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5710 TLBCustData
*pCData
=NULL
;
5711 TLBVarDesc
* pVDesc
;
5714 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5718 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5720 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5724 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5728 VariantInit( pVarVal
);
5729 VariantCopy( pVarVal
, &pCData
->data
);
5732 return E_INVALIDARG
; /* FIXME: correct? */
5735 /* ITypeInfo2::GetImplCustData
5737 * Gets the custom data
5739 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5745 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5746 TLBCustData
*pCData
=NULL
;
5747 TLBImplType
* pRDesc
;
5750 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5754 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5756 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5760 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5764 VariantInit( pVarVal
);
5765 VariantCopy( pVarVal
, &pCData
->data
);
5768 return E_INVALIDARG
; /* FIXME: correct? */
5771 /* ITypeInfo2::GetDocumentation2
5773 * Retrieves the documentation string, the complete Help file name and path,
5774 * the localization context to use, and the context ID for the library Help
5775 * topic in the Help file.
5778 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5782 BSTR
*pbstrHelpString
,
5783 DWORD
*pdwHelpStringContext
,
5784 BSTR
*pbstrHelpStringDll
)
5786 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5787 TLBFuncDesc
* pFDesc
;
5788 TLBVarDesc
* pVDesc
;
5789 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5790 "HelpStringContext(%p) HelpStringDll(%p)\n",
5791 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5792 pbstrHelpStringDll
);
5793 /* the help string should be obtained from the helpstringdll,
5794 * using the _DLLGetDocumentation function, based on the supplied
5795 * lcid. Nice to do sometime...
5797 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5799 *pbstrHelpString
=SysAllocString(This
->Name
);
5800 if(pdwHelpStringContext
)
5801 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5802 if(pbstrHelpStringDll
)
5803 *pbstrHelpStringDll
=
5804 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5806 }else {/* for a member */
5807 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5808 if(pFDesc
->funcdesc
.memid
==memid
){
5810 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5811 if(pdwHelpStringContext
)
5812 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5813 if(pbstrHelpStringDll
)
5814 *pbstrHelpStringDll
=
5815 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5818 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5819 if(pVDesc
->vardesc
.memid
==memid
){
5821 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5822 if(pdwHelpStringContext
)
5823 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5824 if(pbstrHelpStringDll
)
5825 *pbstrHelpStringDll
=
5826 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5830 return TYPE_E_ELEMENTNOTFOUND
;
5833 /* ITypeInfo2::GetAllCustData
5835 * Gets all custom data items for the Type info.
5838 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5840 CUSTDATA
*pCustData
)
5842 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5843 TLBCustData
*pCData
;
5846 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5848 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5849 if(pCustData
->prgCustData
){
5850 pCustData
->cCustData
=This
->ctCustData
;
5851 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5852 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5853 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5856 ERR(" OUT OF MEMORY!\n");
5857 return E_OUTOFMEMORY
;
5862 /* ITypeInfo2::GetAllFuncCustData
5864 * Gets all custom data items for the specified Function
5867 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5870 CUSTDATA
*pCustData
)
5872 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5873 TLBCustData
*pCData
;
5874 TLBFuncDesc
* pFDesc
;
5876 TRACE("(%p) index %d\n", This
, index
);
5877 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5878 pFDesc
=pFDesc
->next
)
5881 pCustData
->prgCustData
=
5882 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5883 if(pCustData
->prgCustData
){
5884 pCustData
->cCustData
=pFDesc
->ctCustData
;
5885 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5886 pCData
= pCData
->next
){
5887 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5888 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5892 ERR(" OUT OF MEMORY!\n");
5893 return E_OUTOFMEMORY
;
5897 return TYPE_E_ELEMENTNOTFOUND
;
5900 /* ITypeInfo2::GetAllParamCustData
5902 * Gets all custom data items for the Functions
5905 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5906 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5908 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5909 TLBCustData
*pCData
=NULL
;
5910 TLBFuncDesc
* pFDesc
;
5912 TRACE("(%p) index %d\n", This
, indexFunc
);
5913 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5914 pFDesc
=pFDesc
->next
)
5916 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5917 pCustData
->prgCustData
=
5918 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5919 sizeof(CUSTDATAITEM
));
5920 if(pCustData
->prgCustData
){
5921 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5922 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5923 pCData
; i
++, pCData
= pCData
->next
){
5924 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5925 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5929 ERR(" OUT OF MEMORY!\n");
5930 return E_OUTOFMEMORY
;
5934 return TYPE_E_ELEMENTNOTFOUND
;
5937 /* ITypeInfo2::GetAllVarCustData
5939 * Gets all custom data items for the specified Variable
5942 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5943 UINT index
, CUSTDATA
*pCustData
)
5945 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5946 TLBCustData
*pCData
;
5947 TLBVarDesc
* pVDesc
;
5949 TRACE("(%p) index %d\n", This
, index
);
5950 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5951 pVDesc
=pVDesc
->next
)
5954 pCustData
->prgCustData
=
5955 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5956 if(pCustData
->prgCustData
){
5957 pCustData
->cCustData
=pVDesc
->ctCustData
;
5958 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5959 pCData
= pCData
->next
){
5960 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5961 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5965 ERR(" OUT OF MEMORY!\n");
5966 return E_OUTOFMEMORY
;
5970 return TYPE_E_ELEMENTNOTFOUND
;
5973 /* ITypeInfo2::GetAllImplCustData
5975 * Gets all custom data items for the specified implementation type
5978 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5981 CUSTDATA
*pCustData
)
5983 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5984 TLBCustData
*pCData
;
5985 TLBImplType
* pRDesc
;
5987 TRACE("(%p) index %d\n", This
, index
);
5988 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5989 pRDesc
=pRDesc
->next
)
5992 pCustData
->prgCustData
=
5993 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5994 if(pCustData
->prgCustData
){
5995 pCustData
->cCustData
=pRDesc
->ctCustData
;
5996 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5997 pCData
= pCData
->next
){
5998 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5999 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6003 ERR(" OUT OF MEMORY!\n");
6004 return E_OUTOFMEMORY
;
6008 return TYPE_E_ELEMENTNOTFOUND
;
6011 static const ITypeInfo2Vtbl tinfvt
=
6014 ITypeInfo_fnQueryInterface
,
6016 ITypeInfo_fnRelease
,
6018 ITypeInfo_fnGetTypeAttr
,
6019 ITypeInfo_fnGetTypeComp
,
6020 ITypeInfo_fnGetFuncDesc
,
6021 ITypeInfo_fnGetVarDesc
,
6022 ITypeInfo_fnGetNames
,
6023 ITypeInfo_fnGetRefTypeOfImplType
,
6024 ITypeInfo_fnGetImplTypeFlags
,
6025 ITypeInfo_fnGetIDsOfNames
,
6027 ITypeInfo_fnGetDocumentation
,
6028 ITypeInfo_fnGetDllEntry
,
6029 ITypeInfo_fnGetRefTypeInfo
,
6030 ITypeInfo_fnAddressOfMember
,
6031 ITypeInfo_fnCreateInstance
,
6032 ITypeInfo_fnGetMops
,
6033 ITypeInfo_fnGetContainingTypeLib
,
6034 ITypeInfo_fnReleaseTypeAttr
,
6035 ITypeInfo_fnReleaseFuncDesc
,
6036 ITypeInfo_fnReleaseVarDesc
,
6038 ITypeInfo2_fnGetTypeKind
,
6039 ITypeInfo2_fnGetTypeFlags
,
6040 ITypeInfo2_fnGetFuncIndexOfMemId
,
6041 ITypeInfo2_fnGetVarIndexOfMemId
,
6042 ITypeInfo2_fnGetCustData
,
6043 ITypeInfo2_fnGetFuncCustData
,
6044 ITypeInfo2_fnGetParamCustData
,
6045 ITypeInfo2_fnGetVarCustData
,
6046 ITypeInfo2_fnGetImplTypeCustData
,
6047 ITypeInfo2_fnGetDocumentation2
,
6048 ITypeInfo2_fnGetAllCustData
,
6049 ITypeInfo2_fnGetAllFuncCustData
,
6050 ITypeInfo2_fnGetAllParamCustData
,
6051 ITypeInfo2_fnGetAllVarCustData
,
6052 ITypeInfo2_fnGetAllImplTypeCustData
,
6055 /******************************************************************************
6056 * CreateDispTypeInfo [OLEAUT32.31]
6058 * Build type information for an object so it can be called through an
6059 * IDispatch interface.
6062 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6063 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6066 * This call allows an objects methods to be accessed through IDispatch, by
6067 * building an ITypeInfo object that IDispatch can use to call through.
6069 HRESULT WINAPI
CreateDispTypeInfo(
6070 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
6071 LCID lcid
, /* [I] Locale Id */
6072 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
6074 ITypeInfoImpl
*pTIImpl
;
6076 TLBFuncDesc
**ppFuncDesc
;
6078 pTIImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
6079 pTIImpl
->pTypeLib
= NULL
;
6081 pTIImpl
->Name
= NULL
;
6082 pTIImpl
->dwHelpContext
= -1;
6083 memset(&pTIImpl
->TypeAttr
.guid
, 0, sizeof(GUID
));
6084 pTIImpl
->TypeAttr
.lcid
= lcid
;
6085 pTIImpl
->TypeAttr
.typekind
= TKIND_COCLASS
;
6086 pTIImpl
->TypeAttr
.wMajorVerNum
= 0;
6087 pTIImpl
->TypeAttr
.wMinorVerNum
= 0;
6088 pTIImpl
->TypeAttr
.cbAlignment
= 2;
6089 pTIImpl
->TypeAttr
.cbSizeInstance
= -1;
6090 pTIImpl
->TypeAttr
.cbSizeVft
= -1;
6091 pTIImpl
->TypeAttr
.cFuncs
= 0;
6092 pTIImpl
->TypeAttr
.cImplTypes
= 1;
6093 pTIImpl
->TypeAttr
.cVars
= 0;
6094 pTIImpl
->TypeAttr
.wTypeFlags
= 0;
6096 ppFuncDesc
= &pTIImpl
->funclist
;
6097 for(func
= 0; func
< pidata
->cMembers
; func
++) {
6098 METHODDATA
*md
= pidata
->pmethdata
+ func
;
6099 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
6100 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
6101 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
6102 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
6103 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
6104 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
6105 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
6106 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
;
6107 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0; /*??*/
6108 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
6109 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6110 md
->cArgs
* sizeof(ELEMDESC
));
6111 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6112 md
->cArgs
* sizeof(TLBParDesc
));
6113 for(param
= 0; param
< md
->cArgs
; param
++) {
6114 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
6115 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
6117 ppFuncDesc
= &(*ppFuncDesc
)->next
;
6119 *pptinfo
= (ITypeInfo
*)pTIImpl
;
6124 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
6126 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6128 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
6131 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
6133 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6135 return ITypeInfo_AddRef((ITypeInfo
*)This
);
6138 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
6140 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6142 return ITypeInfo_Release((ITypeInfo
*)This
);
6145 static HRESULT WINAPI
ITypeComp_fnBind(
6150 ITypeInfo
** ppTInfo
,
6151 DESCKIND
* pDescKind
,
6154 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6155 TLBFuncDesc
* pFDesc
;
6156 TLBVarDesc
* pVDesc
;
6158 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6160 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
6161 if (pFDesc
->funcdesc
.invkind
& wFlags
)
6162 if (!strcmpW(pFDesc
->Name
, szName
)) {
6168 *pDescKind
= DESCKIND_FUNCDESC
;
6169 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
6170 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6173 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
6175 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
6176 if (!strcmpW(pVDesc
->Name
, szName
)) {
6177 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
6180 *pDescKind
= DESCKIND_VARDESC
;
6181 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6187 /* not found, look for it in inherited interfaces */
6188 if (This
->TypeAttr
.cImplTypes
&&
6189 (This
->TypeAttr
.typekind
== TKIND_INTERFACE
|| This
->TypeAttr
.typekind
== TKIND_DISPATCH
)) {
6190 /* recursive search */
6194 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
6197 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
6198 ITypeInfo_Release(pTInfo
);
6202 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6203 ITypeComp_Release(pTComp
);
6206 WARN("Could not search inherited interface!\n");
6208 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
6209 *pDescKind
= DESCKIND_NONE
;
6210 pBindPtr
->lpfuncdesc
= NULL
;
6212 return DISP_E_MEMBERNOTFOUND
;
6215 static HRESULT WINAPI
ITypeComp_fnBindType(
6219 ITypeInfo
** ppTInfo
,
6220 ITypeComp
** ppTComp
)
6222 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
6224 /* strange behaviour (does nothing) but like the
6227 if (!ppTInfo
|| !ppTComp
)
6236 static const ITypeCompVtbl tcompvt
=
6239 ITypeComp_fnQueryInterface
,
6241 ITypeComp_fnRelease
,
6244 ITypeComp_fnBindType