4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
57 #include "wine/port.h"
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
76 #include "wine/unicode.h"
79 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
85 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
86 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
88 /****************************************************************************
91 * Takes p_iVal (which is in little endian) and returns it
92 * in the host machine's byte order.
94 #ifdef WORDS_BIGENDIAN
95 static WORD
FromLEWord(WORD p_iVal
)
97 return (((p_iVal
& 0x00FF) << 8) |
98 ((p_iVal
& 0xFF00) >> 8));
102 static DWORD
FromLEDWord(DWORD p_iVal
)
104 return (((p_iVal
& 0x000000FF) << 24) |
105 ((p_iVal
& 0x0000FF00) << 8) |
106 ((p_iVal
& 0x00FF0000) >> 8) |
107 ((p_iVal
& 0xFF000000) >> 24));
110 #define FromLEWord(X) (X)
111 #define FromLEDWord(X) (X)
115 /****************************************************************************
118 * Fix byte order in any structure if necessary
120 #ifdef WORDS_BIGENDIAN
121 static void FromLEWords(void *p_Val
, int p_iSize
)
125 p_iSize
/= sizeof(WORD
);
128 *Val
= FromLEWord(*Val
);
135 static void FromLEDWords(void *p_Val
, int p_iSize
)
139 p_iSize
/= sizeof(DWORD
);
142 *Val
= FromLEDWord(*Val
);
148 #define FromLEWords(X,Y) /*nothing*/
149 #define FromLEDWords(X,Y) /*nothing*/
152 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
153 /* buffer must be at least 60 characters long */
154 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
156 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
157 static const WCHAR VersionFormatW
[] = {'\\','%','u','.','%','u',0};
159 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
160 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
161 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
165 /* get the path of an interface key, in the form "Interface\\<guid>" */
166 /* buffer must be at least 50 characters long */
167 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
169 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
171 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
172 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
176 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
177 /* buffer must be at least 16 characters long */
178 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
180 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
181 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
182 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
184 sprintfW( buffer
, LcidFormatW
, lcid
);
187 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
188 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
190 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
196 static int TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
199 /****************************************************************************
200 * QueryPathOfRegTypeLib [OLEAUT32.164]
202 * Gets the path to a registered type library.
205 * guid [I] referenced guid
206 * wMaj [I] major version
207 * wMin [I] minor version
209 * path [O] path of typelib
213 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
214 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
217 HRESULT WINAPI
QueryPathOfRegTypeLib(
224 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
228 WCHAR Path
[MAX_PATH
];
231 TRACE_(typelib
)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
233 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
235 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
236 if (res
== ERROR_FILE_NOT_FOUND
)
238 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
239 return TYPE_E_LIBNOTREGISTERED
;
241 else if (res
!= ERROR_SUCCESS
)
243 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
244 return TYPE_E_REGISTRYACCESS
;
249 LONG dwPathLen
= sizeof(Path
);
251 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
253 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
257 else if (myLCID
== lcid
)
259 /* try with sub-langid */
260 myLCID
= SUBLANGID(lcid
);
262 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
264 /* try with system langid */
274 *path
= SysAllocString( Path
);
279 TRACE_(typelib
)("-- 0x%08lx\n", hr
);
283 /******************************************************************************
284 * CreateTypeLib [OLEAUT32.160] creates a typelib
290 HRESULT WINAPI
CreateTypeLib(
291 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
293 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
297 /******************************************************************************
298 * LoadTypeLib [OLEAUT32.161]
300 * Loads a type library
303 * szFile [I] Name of file to load from.
304 * pptLib [O] Pointer that receives ITypeLib object on success.
311 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
313 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
315 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
316 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
319 /******************************************************************************
320 * LoadTypeLibEx [OLEAUT32.183]
322 * Loads and optionally registers a type library
328 HRESULT WINAPI
LoadTypeLibEx(
329 LPCOLESTR szFile
, /* [in] Name of file to load from */
330 REGKIND regkind
, /* [in] Specify kind of registration */
331 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
333 WCHAR szPath
[MAX_PATH
+1];
336 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
340 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
345 case REGKIND_DEFAULT
:
346 /* don't register typelibs supplied with full path. Experimentation confirms the following */
347 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
348 (szFile
[0] && (szFile
[1] == ':'))) break;
349 /* else fall-through */
351 case REGKIND_REGISTER
:
352 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
354 IUnknown_Release(*pptLib
);
362 TRACE(" returns %08lx\n",res
);
366 /******************************************************************************
367 * LoadRegTypeLib [OLEAUT32.162]
369 * Loads a registered type library.
372 * rguid [I] GUID of the registered type library.
373 * wVerMajor [I] major version.
374 * wVerMinor [I] minor version.
375 * lcid [I] locale ID.
376 * ppTLib [O] pointer that receives an ITypeLib object on success.
380 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
383 HRESULT WINAPI
LoadRegTypeLib(
395 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
399 res
= LoadTypeLib(bstr
, ppTLib
);
403 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
409 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
410 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
411 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
412 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
413 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
414 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
416 /******************************************************************************
417 * RegisterTypeLib [OLEAUT32.163]
418 * Adds information about a type library to the System Registry
420 * Docs: ITypeLib FAR * ptlib
421 * Docs: OLECHAR FAR* szFullPath
422 * Docs: OLECHAR FAR* szHelpDir
428 HRESULT WINAPI
RegisterTypeLib(
429 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
430 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
431 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
434 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
435 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
436 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
446 if (ptlib
== NULL
|| szFullPath
== NULL
)
449 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
452 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
455 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
456 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
460 /* Set the human-readable name of the typelib */
461 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
463 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
464 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
472 /* Make up the name of the typelib path subkey */
473 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
475 /* Create the typelib path subkey */
476 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
477 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
479 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
480 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
488 /* Create the flags subkey */
489 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
490 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
492 /* FIXME: is %u correct? */
493 static const WCHAR formatW
[] = {'%','u',0};
495 sprintfW(buf
, formatW
, attr
->wLibFlags
);
496 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
497 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
505 /* create the helpdir subkey */
506 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
507 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
509 BOOL freeHelpDir
= FALSE
;
512 /* if we created a new key, and helpDir was null, set the helpdir
513 to the directory which contains the typelib. However,
514 if we just opened an existing key, we leave the helpdir alone */
515 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
516 szHelpDir
= SysAllocString(szFullPath
);
517 pIndexStr
= strrchrW(szHelpDir
, '\\');
524 /* if we have an szHelpDir, set it! */
525 if (szHelpDir
!= NULL
) {
526 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
527 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
533 if (freeHelpDir
) SysFreeString(szHelpDir
);
545 /* register OLE Automation-compatible interfaces for this typelib */
546 types
= ITypeLib_GetTypeInfoCount(ptlib
);
547 for (tidx
=0; tidx
<types
; tidx
++) {
548 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
549 LPOLESTR name
= NULL
;
550 ITypeInfo
*tinfo
= NULL
;
552 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
555 case TKIND_INTERFACE
:
556 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
557 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
561 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
562 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
566 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
571 TYPEATTR
*tattr
= NULL
;
572 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
575 TRACE_(typelib
)("guid=%s, flags=%04x (",
576 debugstr_guid(&tattr
->guid
),
579 if (TRACE_ON(typelib
)) {
580 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
600 if (tattr
->wTypeFlags
& (TYPEFLAG_FOLEAUTOMATION
|TYPEFLAG_FDISPATCHABLE
))
602 /* register interface<->typelib coupling */
603 get_interface_key( &tattr
->guid
, keyName
);
604 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
605 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
608 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
609 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
611 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
612 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
613 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
614 (BYTE
*)PSOA
, sizeof PSOA
);
618 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
619 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
620 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
621 (BYTE
*)PSOA
, sizeof PSOA
);
625 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
626 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
629 static const WCHAR fmtver
[] = {'%','u','.','%','u',0 };
630 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
632 StringFromGUID2(&attr
->guid
, buffer
, 40);
633 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
634 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
635 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
636 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
637 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
645 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
648 ITypeInfo_Release(tinfo
);
655 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
661 /******************************************************************************
662 * UnRegisterTypeLib [OLEAUT32.186]
663 * Removes information about a type library from the System Registry
670 HRESULT WINAPI
UnRegisterTypeLib(
671 REFGUID libid
, /* [in] Guid of the library */
672 WORD wVerMajor
, /* [in] major version */
673 WORD wVerMinor
, /* [in] minor version */
674 LCID lcid
, /* [in] locale id */
677 BSTR tlibPath
= NULL
;
680 WCHAR subKeyName
[50];
683 BOOL deleteOtherStuff
;
686 TYPEATTR
* typeAttr
= NULL
;
688 ITypeInfo
* typeInfo
= NULL
;
689 ITypeLib
* typeLib
= NULL
;
692 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
694 /* Create the path to the key */
695 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
697 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
699 TRACE("Unsupported syskind %i\n", syskind
);
700 result
= E_INVALIDARG
;
704 /* get the path to the typelib on disk */
705 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
706 result
= E_INVALIDARG
;
710 /* Try and open the key to the type library. */
711 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != S_OK
) {
712 result
= E_INVALIDARG
;
716 /* Try and load the type library */
717 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
718 result
= TYPE_E_INVALIDSTATE
;
722 /* remove any types registered with this typelib */
723 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
724 for (i
=0; i
<numTypes
; i
++) {
725 /* get the kind of type */
726 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
730 /* skip non-interfaces, and get type info for the type */
731 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
734 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
737 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
741 /* the path to the type */
742 get_interface_key( &typeAttr
->guid
, subKeyName
);
744 /* Delete its bits */
745 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != S_OK
) {
748 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
749 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
750 RegDeleteKeyW(subKey
, TypeLibW
);
753 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
756 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
758 if (typeInfo
) ITypeInfo_Release(typeInfo
);
762 /* Now, delete the type library path subkey */
763 get_lcid_subkey( lcid
, syskind
, subKeyName
);
764 RegDeleteKeyW(key
, subKeyName
);
765 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
766 RegDeleteKeyW(key
, subKeyName
);
768 /* check if there is anything besides the FLAGS/HELPDIR keys.
769 If there is, we don't delete them */
770 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
771 deleteOtherStuff
= TRUE
;
773 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == S_OK
) {
774 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
776 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
777 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
778 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
779 deleteOtherStuff
= FALSE
;
783 /* only delete the other parts of the key if we're absolutely sure */
784 if (deleteOtherStuff
) {
785 RegDeleteKeyW(key
, FLAGSW
);
786 RegDeleteKeyW(key
, HELPDIRW
);
790 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
791 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
792 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
796 if (tlibPath
) SysFreeString(tlibPath
);
797 if (typeLib
) ITypeLib_Release(typeLib
);
798 if (subKey
) RegCloseKey(subKey
);
799 if (key
) RegCloseKey(key
);
803 /*======================= ITypeLib implementation =======================*/
805 typedef struct tagTLBCustData
809 struct tagTLBCustData
* next
;
812 /* data structure for import typelibs */
813 typedef struct tagTLBImpLib
815 int offset
; /* offset in the file (MSFT)
816 offset in nametable (SLTG)
817 just used to identify library while reading
819 GUID guid
; /* libid */
820 BSTR name
; /* name */
822 LCID lcid
; /* lcid of imported typelib */
824 WORD wVersionMajor
; /* major version number */
825 WORD wVersionMinor
; /* minor version number */
827 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
828 NULL if not yet loaded */
829 struct tagTLBImpLib
* next
;
832 /* internal ITypeLib data */
833 typedef struct tagITypeLibImpl
835 const ITypeLib2Vtbl
*lpVtbl
;
836 const ITypeCompVtbl
*lpVtblTypeComp
;
838 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
840 /* strings can be stored in tlb as multibyte strings BUT they are *always*
841 * exported to the application as a UNICODE string.
847 unsigned long dwHelpContext
;
848 int TypeInfoCount
; /* nr of typeinfo's in librarry */
849 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
850 int ctCustData
; /* number of items in cust data list */
851 TLBCustData
* pCustData
; /* linked list to cust data */
852 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
853 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
854 libary. Only used while read MSFT
857 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
858 struct tagITypeLibImpl
*next
, *prev
;
863 static const ITypeLib2Vtbl tlbvt
;
864 static const ITypeCompVtbl tlbtcvt
;
866 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
868 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
871 /* ITypeLib methods */
872 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
873 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
875 /*======================= ITypeInfo implementation =======================*/
877 /* data for referenced types */
878 typedef struct tagTLBRefType
880 INT index
; /* Type index for internal ref or for external ref
881 it the format is SLTG. -2 indicates to
884 GUID guid
; /* guid of the referenced type */
885 /* if index == TLB_REF_USE_GUID */
887 HREFTYPE reference
; /* The href of this ref */
888 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
889 TLB_REF_INTERNAL for internal refs
890 TLB_REF_NOT_FOUND for broken refs */
892 struct tagTLBRefType
* next
;
895 #define TLB_REF_USE_GUID -2
897 #define TLB_REF_INTERNAL (void*)-2
898 #define TLB_REF_NOT_FOUND (void*)-1
900 /* internal Parameter data */
901 typedef struct tagTLBParDesc
905 TLBCustData
* pCustData
; /* linked list to cust data */
908 /* internal Function data */
909 typedef struct tagTLBFuncDesc
911 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
912 BSTR Name
; /* the name of this function */
913 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
915 int HelpStringContext
;
917 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
919 TLBCustData
* pCustData
; /* linked list to cust data; */
920 struct tagTLBFuncDesc
* next
;
923 /* internal Variable data */
924 typedef struct tagTLBVarDesc
926 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
927 BSTR Name
; /* the name of this variable */
929 int HelpStringContext
; /* FIXME: where? */
932 TLBCustData
* pCustData
;/* linked list to cust data; */
933 struct tagTLBVarDesc
* next
;
936 /* internal implemented interface data */
937 typedef struct tagTLBImplType
939 HREFTYPE hRef
; /* hRef of interface */
940 int implflags
; /* IMPLFLAG_*s */
942 TLBCustData
* pCustData
;/* linked list to custom data; */
943 struct tagTLBImplType
*next
;
946 /* internal TypeInfo data */
947 typedef struct tagITypeInfoImpl
949 const ITypeInfo2Vtbl
*lpVtbl
;
950 const ITypeCompVtbl
*lpVtblTypeComp
;
952 TYPEATTR TypeAttr
; /* _lots_ of type information. */
953 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
954 int index
; /* index in this typelib; */
955 HREFTYPE hreftype
; /* hreftype for app object binding */
956 /* type libs seem to store the doc strings in ascii
957 * so why should we do it in unicode?
962 unsigned long dwHelpContext
;
963 unsigned long dwHelpStringContext
;
966 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
969 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
971 /* Implemented Interfaces */
972 TLBImplType
* impltypelist
;
974 TLBRefType
* reflist
;
976 TLBCustData
* pCustData
; /* linked list to cust data; */
977 struct tagITypeInfoImpl
* next
;
980 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
982 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
985 static const ITypeInfo2Vtbl tinfvt
;
986 static const ITypeCompVtbl tcompvt
;
988 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
990 typedef struct tagTLBContext
992 unsigned int oStart
; /* start of TLB in file */
993 unsigned int pos
; /* current pos */
994 unsigned int length
; /* total length */
995 void *mapping
; /* memory mapping */
996 MSFT_SegDir
* pTblDir
;
997 ITypeLibImpl
* pLibInfo
;
1001 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
1006 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1007 if (pTD
->vt
& VT_RESERVED
)
1008 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1009 if (pTD
->vt
& VT_BYREF
)
1010 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1011 if (pTD
->vt
& VT_ARRAY
)
1012 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1013 if (pTD
->vt
& VT_VECTOR
)
1014 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1015 switch(pTD
->vt
& VT_TYPEMASK
) {
1016 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1017 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1018 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1019 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1020 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1021 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1022 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1023 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1024 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1025 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1026 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1027 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1028 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1029 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1030 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1031 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1032 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1033 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1034 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1035 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1036 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
1037 pTD
->u
.hreftype
); break;
1038 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1039 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1041 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1042 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1044 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1045 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1046 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1049 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1053 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1055 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1056 dump_TypeDesc(&edesc
->tdesc
,buf
);
1057 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1058 MESSAGE("\t\tu.paramdesc.wParamFlags");
1059 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1060 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1061 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1062 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1063 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1064 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1065 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1066 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1067 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1069 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1071 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
1072 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1073 MESSAGE("Param %d:\n",i
);
1074 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1076 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1077 switch (funcdesc
->funckind
) {
1078 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1079 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1080 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1081 case FUNC_STATIC
: MESSAGE("static");break;
1082 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1083 default: MESSAGE("unknown");break;
1085 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1086 switch (funcdesc
->invkind
) {
1087 case INVOKE_FUNC
: MESSAGE("func");break;
1088 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1089 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1090 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1092 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1093 switch (funcdesc
->callconv
) {
1094 case CC_CDECL
: MESSAGE("cdecl");break;
1095 case CC_PASCAL
: MESSAGE("pascal");break;
1096 case CC_STDCALL
: MESSAGE("stdcall");break;
1097 case CC_SYSCALL
: MESSAGE("syscall");break;
1100 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1101 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1102 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1104 MESSAGE("\telemdescFunc (return value type):\n");
1105 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1108 static const char * typekind_desc
[] =
1121 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1124 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1125 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1126 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1129 dump_FUNCDESC(&(pfd
->funcdesc
));
1131 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1132 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1134 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
)
1138 dump_TLBFuncDescOne(pfd
);
1142 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
)
1146 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1151 static void dump_TLBImpLib(const TLBImpLib
*import
)
1153 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1154 debugstr_w(import
->name
));
1155 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1156 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1159 static void dump_TLBRefType(const TLBRefType
* prt
)
1163 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1164 if(prt
->index
== -1)
1165 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1167 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1169 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1170 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1171 TRACE_(typelib
)("in lib\n");
1172 dump_TLBImpLib(prt
->pImpTLInfo
);
1178 static void dump_TLBImplType(const TLBImplType
* impl
)
1182 "implementing/inheriting interface hRef = %lx implflags %x\n",
1183 impl
->hRef
, impl
->implflags
);
1188 void dump_Variant(const VARIANT
* pvar
)
1192 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1196 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1197 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1199 TRACE(",%p", V_BYREF(pvar
));
1201 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1203 TRACE(",%p", V_ARRAY(pvar
));
1205 else switch (V_TYPE(pvar
))
1207 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1208 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1209 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1210 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1212 case VT_I4
: TRACE(",%ld", V_I4(pvar
)); break;
1214 case VT_UI4
: TRACE(",%ld", V_UI4(pvar
)); break;
1215 case VT_I8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_I8(pvar
) >> 32),
1216 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1217 case VT_UI8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_UI8(pvar
) >> 32),
1218 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1219 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1220 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1221 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1222 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1223 case VT_CY
: TRACE(",0x%08lx,0x%08lx", V_CY(pvar
).s
.Hi
,
1224 V_CY(pvar
).s
.Lo
); break;
1226 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1227 TRACE(",<invalid>");
1229 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1230 st
.wHour
, st
.wMinute
, st
.wSecond
);
1234 case VT_USERDEFINED
:
1236 case VT_NULL
: break;
1237 default: TRACE(",?"); break;
1243 static void dump_DispParms(const DISPPARAMS
* pdp
)
1247 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1249 while (index
< pdp
->cArgs
)
1251 dump_Variant( &pdp
->rgvarg
[index
] );
1256 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1258 TRACE("%p ref=%lu\n", pty
, pty
->ref
);
1259 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1260 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1261 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1262 TRACE("fct:%u var:%u impl:%u\n",
1263 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1264 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1265 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1266 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1268 dump_TLBFuncDesc(pty
->funclist
);
1269 dump_TLBVarDesc(pty
->varlist
);
1270 dump_TLBImplType(pty
->impltypelist
);
1273 static void dump_VARDESC(const VARDESC
*v
)
1275 MESSAGE("memid %ld\n",v
->memid
);
1276 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1277 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1278 dump_ELEMDESC(&(v
->elemdescVar
));
1279 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1280 MESSAGE("varkind %d\n",v
->varkind
);
1283 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1285 /* VT_LPWSTR is largest type that */
1286 /* may appear in type description*/
1287 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1288 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1289 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1290 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1291 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1292 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1296 static void TLB_abort(void)
1300 static void * TLB_Alloc(unsigned size
)
1303 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1305 ERR("cannot allocate memory\n");
1310 static void TLB_Free(void * ptr
)
1312 HeapFree(GetProcessHeap(), 0, ptr
);
1315 /* returns the size required for a deep copy of a typedesc into a
1317 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1321 if (alloc_initial_space
)
1322 size
+= sizeof(TYPEDESC
);
1328 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1331 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1332 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1338 /* deep copy a typedesc into a flat buffer */
1339 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1344 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1353 dest
->u
.lptdesc
= buffer
;
1354 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1357 dest
->u
.lpadesc
= buffer
;
1358 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1359 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1360 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1366 /**********************************************************************
1368 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1370 static inline unsigned int MSFT_Tell(TLBContext
*pcx
)
1375 static inline void MSFT_Seek(TLBContext
*pcx
, long where
)
1377 if (where
!= DO_NOT_SEEK
)
1379 where
+= pcx
->oStart
;
1380 if (where
> pcx
->length
)
1383 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1391 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1393 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1394 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1396 MSFT_Seek(pcx
, where
);
1397 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1398 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1403 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1408 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1409 FromLEDWords(buffer
, ret
);
1414 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1419 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1420 FromLEWords(buffer
, ret
);
1425 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1427 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1428 memset(pGuid
,0, sizeof(GUID
));
1431 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1432 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1433 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1434 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1435 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1438 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1440 MSFT_NameIntro niName
;
1444 ERR_(typelib
)("bad offset %d\n", offset
);
1448 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1449 pcx
->pTblDir
->pNametab
.offset
+offset
);
1451 return niName
.hreftype
;
1454 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1457 MSFT_NameIntro niName
;
1459 WCHAR
* pwstring
= NULL
;
1460 BSTR bstrName
= NULL
;
1464 ERR_(typelib
)("bad offset %d\n", offset
);
1467 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1468 pcx
->pTblDir
->pNametab
.offset
+offset
);
1469 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1470 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1471 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1472 name
[niName
.namelen
& 0xff]='\0';
1474 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1477 /* no invalid characters in string */
1480 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1482 /* don't check for invalid character since this has been done previously */
1483 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1485 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1486 lengthInChars
= SysStringLen(bstrName
);
1487 HeapFree(GetProcessHeap(), 0, pwstring
);
1490 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1494 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1501 if(offset
<0) return NULL
;
1502 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1503 if(length
<= 0) return 0;
1504 string
=TLB_Alloc(length
+1);
1505 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1506 string
[length
]='\0';
1508 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1509 string
, -1, NULL
, 0);
1511 /* no invalid characters in string */
1514 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1516 /* don't check for invalid character since this has been done previously */
1517 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1519 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1520 lengthInChars
= SysStringLen(bstr
);
1521 HeapFree(GetProcessHeap(), 0, pwstring
);
1524 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1528 * read a value and fill a VARIANT structure
1530 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1534 TRACE_(typelib
)("\n");
1536 if(offset
<0) { /* data are packed in here */
1537 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1538 V_I4(pVar
) = offset
& 0x3ffffff;
1541 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1542 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1543 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1544 switch (V_VT(pVar
)){
1545 case VT_EMPTY
: /* FIXME: is this right? */
1546 case VT_NULL
: /* FIXME: is this right? */
1547 case VT_I2
: /* this should not happen */
1558 case VT_VOID
: /* FIXME: is this right? */
1566 case VT_DECIMAL
: /* FIXME: is this right? */
1569 /* pointer types with known behaviour */
1572 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1575 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1578 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1580 nullPos
= MSFT_Tell(pcx
);
1581 size
= nullPos
- origPos
;
1582 MSFT_Seek(pcx
, origPos
);
1584 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1585 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1586 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1587 /* FIXME: do we need a AtoW conversion here? */
1588 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1589 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1593 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1600 case VT_USERDEFINED
:
1606 case VT_STREAMED_OBJECT
:
1607 case VT_STORED_OBJECT
:
1608 case VT_BLOB_OBJECT
:
1613 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1617 if(size
>0) /* (big|small) endian correct? */
1618 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1622 * create a linked list with custom data
1624 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1630 TRACE_(typelib
)("\n");
1634 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1635 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1636 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1637 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1638 /* add new custom data at head of the list */
1639 pNew
->next
=*ppCustData
;
1641 offset
= entry
.next
;
1646 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1650 pTd
->vt
=type
& VT_TYPEMASK
;
1652 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1654 if(pTd
->vt
== VT_USERDEFINED
)
1655 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1657 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1660 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1662 /* resolve referenced type if any */
1665 switch (lpTypeDesc
->vt
)
1668 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1672 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1675 case VT_USERDEFINED
:
1676 MSFT_DoRefType(pcx
, pTI
,
1677 lpTypeDesc
->u
.hreftype
);
1689 MSFT_DoFuncs(TLBContext
* pcx
,
1694 TLBFuncDesc
** pptfd
)
1697 * member information is stored in a data structure at offset
1698 * indicated by the memoffset field of the typeinfo structure
1699 * There are several distinctive parts.
1700 * The first part starts with a field that holds the total length
1701 * of this (first) part excluding this field. Then follow the records,
1702 * for each member there is one record.
1704 * The first entry is always the length of the record (including this
1706 * The rest of the record depends on the type of the member. If there is
1707 * a field indicating the member type (function, variable, interface, etc)
1708 * I have not found it yet. At this time we depend on the information
1709 * in the type info and the usual order how things are stored.
1711 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1714 * Third is an equal sized array with file offsets to the name entry
1717 * The fourth and last (?) part is an array with offsets to the records
1718 * in the first part of this file segment.
1721 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1722 int recoffset
= offset
+ sizeof(INT
);
1725 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1726 TLBFuncDesc
*ptfd_prev
= NULL
;
1728 TRACE_(typelib
)("\n");
1730 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1732 for ( i
= 0; i
< cFuncs
; i
++ )
1734 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1736 /* name, eventually add to a hash table */
1737 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1738 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1740 /* nameoffset is sometimes -1 on the second half of a propget/propput
1741 * pair of functions */
1742 if ((nameoffset
== -1) && (i
> 0))
1743 (*pptfd
)->Name
= SysAllocString(ptfd_prev
->Name
);
1745 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1747 /* read the function information record */
1748 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1752 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1754 /* do the attributes */
1755 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1758 if ( nrattributes
> 0 )
1760 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1762 if ( nrattributes
> 1 )
1764 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1765 pFuncRec
->OptAttr
[1]) ;
1767 if ( nrattributes
> 2 )
1769 if ( pFuncRec
->FKCCIC
& 0x2000 )
1771 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1775 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1776 pFuncRec
->OptAttr
[2]);
1778 if( nrattributes
> 5 )
1780 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1782 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1785 pFuncRec
->OptAttr
[6],
1786 &(*pptfd
)->pCustData
);
1793 /* fill the FuncDesc Structure */
1794 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1795 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1797 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1798 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1799 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1800 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1801 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1802 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1803 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1807 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1809 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
);
1811 /* do the parameters/arguments */
1812 if(pFuncRec
->nrargs
)
1815 MSFT_ParameterInfo paraminfo
;
1817 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1818 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1820 (*pptfd
)->pParamDesc
=
1821 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1823 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1824 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1826 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1828 ELEMDESC
*elemdesc
= &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1835 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1838 if (paraminfo
.oName
== -1)
1839 /* this occurs for [propput] or [propget] methods, so
1840 * we should just set the name of the parameter to the
1841 * name of the method. */
1842 (*pptfd
)->pParamDesc
[j
].Name
= SysAllocString((*pptfd
)->Name
);
1844 (*pptfd
)->pParamDesc
[j
].Name
=
1845 MSFT_ReadName( pcx
, paraminfo
.oName
);
1846 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w((*pptfd
)->pParamDesc
[j
].Name
));
1848 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
1851 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
1852 (pFuncRec
->FKCCIC
& 0x1000) )
1854 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1856 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1858 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
1860 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1861 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1863 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1867 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
1869 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1872 pFuncRec
->OptAttr
[7+j
],
1873 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1876 /* SEEK value = jump to offset,
1877 * from there jump to the end of record,
1878 * go back by (j-1) arguments
1880 MSFT_ReadLEDWords( ¶minfo
,
1881 sizeof(MSFT_ParameterInfo
), pcx
,
1882 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1883 * sizeof(MSFT_ParameterInfo
)));
1887 /* scode is not used: archaic win16 stuff FIXME: right? */
1888 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1889 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1892 pptfd
= & ((*pptfd
)->next
);
1893 recoffset
+= reclength
;
1897 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1898 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1900 int infolen
, nameoffset
, reclength
;
1902 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1906 TRACE_(typelib
)("\n");
1908 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1909 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1910 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1911 recoffset
+= offset
+sizeof(INT
);
1912 for(i
=0;i
<cVars
;i
++){
1913 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1914 /* name, eventually add to a hash table */
1915 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1916 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1917 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1918 /* read the variable information record */
1919 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1921 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1923 if(reclength
>(6*sizeof(INT
)) )
1924 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1925 if(reclength
>(7*sizeof(INT
)) )
1926 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1927 if(reclength
>(8*sizeof(INT
)) )
1928 if(reclength
>(9*sizeof(INT
)) )
1929 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1930 /* fill the VarDesc Structure */
1931 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1932 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
1933 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1934 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1935 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1936 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1937 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1938 if(pVarRec
->VarKind
== VAR_CONST
){
1939 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1940 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1941 pVarRec
->OffsValue
, pcx
);
1943 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1944 MSFT_ResolveReferencedTypes(pcx
, pTI
, &(*pptvd
)->vardesc
.elemdescVar
.tdesc
);
1945 pptvd
=&((*pptvd
)->next
);
1946 recoffset
+= reclength
;
1949 /* fill in data for a hreftype (offset). When the referenced type is contained
1950 * in the typelib, it's just an (file) offset in the type info base dir.
1951 * If comes from import, it's an offset+1 in the ImpInfo table
1953 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1957 TLBRefType
**ppRefType
= &pTI
->reflist
;
1959 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1962 if((*ppRefType
)->reference
== offset
)
1964 ppRefType
= &(*ppRefType
)->next
;
1967 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1968 sizeof(**ppRefType
));
1970 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1971 /* external typelib */
1972 MSFT_ImpInfo impinfo
;
1973 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1975 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1977 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1978 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1979 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1980 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1981 pImpLib
=pImpLib
->next
;
1984 (*ppRefType
)->reference
=offset
;
1985 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1986 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
1987 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1988 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType
)->guid
));
1989 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1991 (*ppRefType
)->index
= impinfo
.oGuid
;
1993 ERR("Cannot find a reference\n");
1994 (*ppRefType
)->reference
=-1;
1995 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1998 /* in this typelib */
1999 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
2000 (*ppRefType
)->reference
=offset
;
2001 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
2005 /* process Implemented Interfaces of a com class */
2006 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2010 MSFT_RefRecord refrec
;
2011 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2013 TRACE_(typelib
)("\n");
2015 for(i
=0;i
<count
;i
++){
2016 if(offset
<0) break; /* paranoia */
2017 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2018 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2019 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
2020 (*ppImpl
)->hRef
= refrec
.reftype
;
2021 (*ppImpl
)->implflags
=refrec
.flags
;
2022 (*ppImpl
)->ctCustData
=
2023 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2024 offset
=refrec
.onext
;
2025 ppImpl
=&((*ppImpl
)->next
);
2029 * process a typeinfo record
2031 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2035 ITypeLibImpl
* pLibInfo
)
2037 MSFT_TypeInfoBase tiBase
;
2038 ITypeInfoImpl
*ptiRet
;
2040 TRACE_(typelib
)("count=%u\n", count
);
2042 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2043 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2044 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2046 /* this is where we are coming from */
2047 ptiRet
->pTypeLib
= pLibInfo
;
2048 ptiRet
->index
=count
;
2049 /* fill in the typeattr fields */
2051 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2052 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2053 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2054 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2055 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2056 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2057 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2058 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2059 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2060 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2061 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2062 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2063 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2064 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2065 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2066 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2069 /* IDLDESC idldescType; *//* never saw this one != zero */
2071 /* name, eventually add to a hash table */
2072 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2073 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2074 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2076 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2077 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2078 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2080 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2081 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2083 /* note: InfoType's Help file and HelpStringDll come from the containing
2084 * library. Further HelpString and Docstring appear to be the same thing :(
2087 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2088 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2089 ptiRet
->TypeAttr
.cVars
,
2090 tiBase
.memoffset
, & ptiRet
->funclist
);
2092 if(ptiRet
->TypeAttr
.cVars
>0 )
2093 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2094 ptiRet
->TypeAttr
.cVars
,
2095 tiBase
.memoffset
, & ptiRet
->varlist
);
2096 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2097 switch(ptiRet
->TypeAttr
.typekind
)
2100 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2103 case TKIND_DISPATCH
:
2104 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2106 if (tiBase
.datatype1
!= -1)
2108 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2109 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2113 MSFT_DoRefType(pcx
, ptiRet
, dispatch_href
);
2114 ptiRet
->impltypelist
->hRef
= dispatch_href
;
2118 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2119 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2120 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2125 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2127 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2128 debugstr_w(ptiRet
->Name
),
2129 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2130 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2135 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2136 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2137 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2140 static ITypeLibImpl
*tlb_cache_first
;
2141 static CRITICAL_SECTION cache_section
;
2142 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2144 0, 0, &cache_section
,
2145 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2146 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2148 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2151 /****************************************************************************
2154 * find the type of the typelib file and map the typelib resource into
2157 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2158 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2159 static int TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2161 ITypeLibImpl
*entry
;
2162 int ret
= TYPE_E_CANTLOADLIBRARY
;
2168 lstrcpynW(pszPath
, pszFileName
, cchPath
);
2170 /* first try loading as a dll and access the typelib as a resource */
2171 hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2172 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2175 /* it may have been specified with resource index appended to the
2176 * path, so remove it and try again */
2177 const WCHAR
*pIndexStr
= strrchrW(pszFileName
, '\\');
2178 if(pIndexStr
&& pIndexStr
!= pszFileName
&& *++pIndexStr
!= '\0')
2180 index
= atoiW(pIndexStr
);
2181 pszPath
[pIndexStr
- pszFileName
- 1] = '\0';
2183 hinstDLL
= LoadLibraryExW(pszPath
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2184 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2188 /* get the path to the specified typelib file */
2191 /* otherwise, try loading as a regular file */
2192 if (!SearchPathW(NULL
, pszFileName
, NULL
, cchPath
, pszPath
, NULL
))
2193 return TYPE_E_CANTLOADLIBRARY
;
2196 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2198 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2199 EnterCriticalSection(&cache_section
);
2200 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2202 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2204 TRACE("cache hit\n");
2205 *ppTypeLib
= (ITypeLib2
*)entry
;
2206 ITypeLib_AddRef(*ppTypeLib
);
2207 LeaveCriticalSection(&cache_section
);
2211 LeaveCriticalSection(&cache_section
);
2213 /* now actually load and parse the typelib */
2216 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2217 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2220 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2223 LPVOID pBase
= LockResource(hGlobal
);
2224 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2228 /* try to load as incore resource */
2229 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2230 if (dwSignature
== MSFT_SIGNATURE
)
2231 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2232 else if (dwSignature
== SLTG_SIGNATURE
)
2233 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2235 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2237 FreeResource( hGlobal
);
2240 FreeLibrary(hinstDLL
);
2244 HANDLE hFile
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2245 if (INVALID_HANDLE_VALUE
!= hFile
)
2247 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2250 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2253 /* retrieve file size */
2254 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2255 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2257 if (dwSignature
== MSFT_SIGNATURE
)
2258 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2259 else if (dwSignature
== SLTG_SIGNATURE
)
2260 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2262 UnmapViewOfFile(pBase
);
2264 CloseHandle(hMapping
);
2271 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2273 TRACE("adding to cache\n");
2274 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath
)+1) * sizeof(WCHAR
));
2275 lstrcpyW(impl
->path
, pszPath
);
2276 /* We should really canonicalise the path here. */
2277 impl
->index
= index
;
2279 /* FIXME: check if it has added already in the meantime */
2280 EnterCriticalSection(&cache_section
);
2281 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2283 tlb_cache_first
= impl
;
2284 LeaveCriticalSection(&cache_section
);
2287 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2292 /*================== ITypeLib(2) Methods ===================================*/
2294 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2296 ITypeLibImpl
* pTypeLibImpl
;
2298 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2299 if (!pTypeLibImpl
) return NULL
;
2301 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2302 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2303 pTypeLibImpl
->ref
= 1;
2305 return pTypeLibImpl
;
2308 /****************************************************************************
2309 * ITypeLib2_Constructor_MSFT
2311 * loading an MSFT typelib from an in-memory image
2313 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2317 MSFT_Header tlbHeader
;
2318 MSFT_SegDir tlbSegDir
;
2319 ITypeLibImpl
* pTypeLibImpl
;
2321 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2323 pTypeLibImpl
= TypeLibImpl_Constructor();
2324 if (!pTypeLibImpl
) return NULL
;
2326 /* get pointer to beginning of typelib data */
2330 cx
.pLibInfo
= pTypeLibImpl
;
2331 cx
.length
= dwTLBLength
;
2334 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2335 TRACE_(typelib
)("header:\n");
2336 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2337 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2338 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2341 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
2343 /* there is a small amount of information here until the next important
2345 * the segment directory . Try to calculate the amount of data */
2346 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2348 /* now read the segment directory */
2349 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2350 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2351 cx
.pTblDir
= &tlbSegDir
;
2353 /* just check two entries */
2354 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2356 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2357 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2361 /* now fill our internal data */
2362 /* TLIBATTR fields */
2363 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2365 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2366 /* Windows seems to have zero here, is this correct? */
2367 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2368 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2370 pTypeLibImpl
->LibAttr
.lcid
= 0;
2372 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2373 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2374 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2375 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2377 /* name, eventually add to a hash table */
2378 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2381 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2382 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2384 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2387 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2388 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2391 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2394 if(tlbHeader
.CustomDataOffset
>= 0)
2396 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2399 /* fill in typedescriptions */
2400 if(tlbSegDir
.pTypdescTab
.length
> 0)
2402 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2404 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2405 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2408 /* FIXME: add several sanity checks here */
2409 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2410 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2412 /* FIXME: check safearray */
2414 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2416 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2418 else if(td
[0] == VT_CARRAY
)
2420 /* array descr table here */
2421 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2423 else if(td
[0] == VT_USERDEFINED
)
2425 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2427 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2430 /* second time around to fill the array subscript info */
2433 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2434 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2436 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2437 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2440 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2442 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2444 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2446 for(j
= 0; j
<td
[2]; j
++)
2448 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2449 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2450 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2451 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2456 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2457 ERR("didn't find array description data\n");
2462 /* imported type libs */
2463 if(tlbSegDir
.pImpFiles
.offset
>0)
2465 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2466 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2469 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2474 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2475 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2476 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2478 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2479 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2480 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2481 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2484 name
= TLB_Alloc(size
+1);
2485 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2486 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2487 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2488 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2491 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2492 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2494 ppImpLib
= &(*ppImpLib
)->next
;
2499 if(tlbHeader
.nrtypeinfos
>= 0 )
2501 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2502 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2505 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2507 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, tlbHeader
.dispatchpos
, pTypeLibImpl
);
2509 ppTI
= &((*ppTI
)->next
);
2510 (pTypeLibImpl
->TypeInfoCount
)++;
2514 TRACE("(%p)\n", pTypeLibImpl
);
2515 return (ITypeLib2
*) pTypeLibImpl
;
2519 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2525 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2526 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2527 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2528 ret
= SysAllocString(nameW
);
2529 HeapFree(GetProcessHeap(), 0, nameW
);
2533 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2539 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2540 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2544 guid
->Data4
[0] = s
>> 8;
2545 guid
->Data4
[1] = s
& 0xff;
2548 for(i
= 0; i
< 6; i
++) {
2549 memcpy(b
, str
+ 24 + 2 * i
, 2);
2550 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2555 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2562 bytelen
= *(WORD
*)ptr
;
2563 if(bytelen
== 0xffff) return 2;
2564 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2565 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2566 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2567 *pBstr
= SysAllocStringLen(nameW
, len
);
2568 HeapFree(GetProcessHeap(), 0, nameW
);
2572 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2577 bytelen
= *(WORD
*)ptr
;
2578 if(bytelen
== 0xffff) return 2;
2579 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2580 memcpy(*str
, ptr
+ 2, bytelen
);
2581 (*str
)[bytelen
] = '\0';
2585 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2587 char *ptr
= pLibBlk
;
2590 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2591 FIXME("libblk magic = %04x\n", w
);
2596 if((w
= *(WORD
*)ptr
) != 0xffff) {
2597 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2602 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2604 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2606 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2609 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2612 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2613 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2615 pTypeLibImpl
->LibAttr
.lcid
= 0;
2618 ptr
+= 4; /* skip res12 */
2620 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2623 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2626 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2629 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2630 ptr
+= sizeof(GUID
);
2632 return ptr
- (char*)pLibBlk
;
2635 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
)
2640 if((*pType
& 0xe00) == 0xe00) {
2642 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2644 pTD
= pTD
->u
.lptdesc
;
2646 switch(*pType
& 0x3f) {
2649 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2651 pTD
= pTD
->u
.lptdesc
;
2654 case VT_USERDEFINED
:
2655 pTD
->vt
= VT_USERDEFINED
;
2656 pTD
->u
.hreftype
= *(++pType
) / 4;
2662 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2665 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2667 pTD
->vt
= VT_CARRAY
;
2668 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2670 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2671 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2672 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2673 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2675 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2681 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2685 pTD
->vt
= VT_SAFEARRAY
;
2686 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2688 pTD
= pTD
->u
.lptdesc
;
2692 pTD
->vt
= *pType
& 0x3f;
2701 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2703 /* Handle [in/out] first */
2704 if((*pType
& 0xc000) == 0xc000)
2705 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2706 else if(*pType
& 0x8000)
2707 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2708 else if(*pType
& 0x4000)
2709 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2711 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2714 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2717 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2719 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
);
2723 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2728 TLBRefType
**ppRefType
;
2730 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2731 FIXME("Ref magic = %x\n", pRef
->magic
);
2734 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2736 ppRefType
= &pTI
->reflist
;
2737 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2739 unsigned int lib_offs
, type_num
;
2741 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2742 sizeof(**ppRefType
));
2744 name
+= SLTG_ReadStringA(name
, &refname
);
2745 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2746 FIXME("Can't sscanf ref\n");
2747 if(lib_offs
!= 0xffff) {
2748 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2751 if((*import
)->offset
== lib_offs
)
2753 import
= &(*import
)->next
;
2756 char fname
[MAX_PATH
+1];
2759 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2761 (*import
)->offset
= lib_offs
;
2762 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2764 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2765 &(*import
)->wVersionMajor
,
2766 &(*import
)->wVersionMinor
,
2767 &(*import
)->lcid
, fname
) != 4) {
2768 FIXME("can't sscanf ref %s\n",
2769 pNameTable
+ lib_offs
+ 40);
2771 len
= strlen(fname
);
2772 if(fname
[len
-1] != '#')
2773 FIXME("fname = %s\n", fname
);
2774 fname
[len
-1] = '\0';
2775 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2777 (*ppRefType
)->pImpTLInfo
= *import
;
2778 } else { /* internal ref */
2779 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2781 (*ppRefType
)->reference
= ref
;
2782 (*ppRefType
)->index
= type_num
;
2784 HeapFree(GetProcessHeap(), 0, refname
);
2785 ppRefType
= &(*ppRefType
)->next
;
2787 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2788 FIXME("End of ref block magic = %x\n", *name
);
2789 dump_TLBRefType(pTI
->reflist
);
2792 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2795 SLTG_ImplInfo
*info
;
2796 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2797 /* I don't really get this structure, usually it's 0x16 bytes
2798 long, but iuser.tlb contains some that are 0x18 bytes long.
2799 That's ok because we can use the next ptr to jump to the next
2800 one. But how do we know the length of the last one? The WORD
2801 at offs 0x8 might be the clue. For now I'm just assuming that
2802 the last one is the regular 0x16 bytes. */
2804 info
= (SLTG_ImplInfo
*)pBlk
;
2806 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2807 sizeof(**ppImplType
));
2808 (*ppImplType
)->hRef
= info
->ref
;
2809 (*ppImplType
)->implflags
= info
->impltypeflags
;
2810 pTI
->TypeAttr
.cImplTypes
++;
2811 ppImplType
= &(*ppImplType
)->next
;
2813 if(info
->next
== 0xffff)
2816 FIXME("Interface inheriting more than one interface\n");
2817 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2819 info
++; /* see comment at top of function */
2823 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
, char *pNameTable
)
2825 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2826 BSTR bstrPrevName
= NULL
;
2827 SLTG_Variable
*pItem
;
2832 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
2833 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++) {
2835 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2836 sizeof(**ppVarDesc
));
2837 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2839 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
2840 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
2841 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
2845 if (pItem
->name
== 0xfffe)
2846 (*ppVarDesc
)->Name
= SysAllocString(bstrPrevName
);
2848 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2850 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
2851 TRACE_(typelib
)("memid = 0x%lx\n", pItem
->memid
);
2853 if (pItem
->flags
& 0x40) {
2854 TRACE_(typelib
)("VAR_DISPATCH\n");
2855 (*ppVarDesc
)->vardesc
.varkind
= VAR_DISPATCH
;
2857 else if (pItem
->flags
& 0x10) {
2858 TRACE_(typelib
)("VAR_CONST\n");
2859 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2860 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2862 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2863 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2864 *(INT
*)(pBlk
+ pItem
->byte_offs
);
2867 TRACE_(typelib
)("VAR_PERINSTANCE\n");
2868 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2869 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2872 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
2873 (*ppVarDesc
)->vardesc
.wVarFlags
= pItem
->varflags
;
2875 if (pItem
->flags
& 0x80)
2876 (*ppVarDesc
)->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
2878 if(pItem
->flags
& 0x02)
2879 pType
= &pItem
->type
;
2881 pType
= (WORD
*)(pBlk
+ pItem
->type
);
2883 if (pItem
->flags
& ~0xd2)
2884 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xd2);
2886 SLTG_DoElem(pType
, pBlk
,
2887 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2889 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2891 bstrPrevName
= (*ppVarDesc
)->Name
;
2892 ppVarDesc
= &((*ppVarDesc
)->next
);
2894 pTI
->TypeAttr
.cVars
= cVars
;
2897 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cFuncs
, char *pNameTable
)
2899 SLTG_Function
*pFunc
;
2901 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2903 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
;
2904 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++) {
2909 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2910 sizeof(**ppFuncDesc
));
2912 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
2913 case SLTG_FUNCTION_MAGIC
:
2914 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
2916 case SLTG_DISPATCH_FUNCTION_MAGIC
:
2917 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_DISPATCH
;
2919 case SLTG_STATIC_FUNCTION_MAGIC
:
2920 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_STATIC
;
2923 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
2924 HeapFree(GetProcessHeap(), 0, *ppFuncDesc
);
2928 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2930 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2931 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2932 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2933 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2934 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2935 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2937 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
2938 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2940 if(pFunc
->retnextopt
& 0x80)
2941 pType
= &pFunc
->rettype
;
2943 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
2945 SLTG_DoElem(pType
, pBlk
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2947 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2948 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2949 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2950 (*ppFuncDesc
)->pParamDesc
=
2951 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2952 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2954 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
2956 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2957 char *paramName
= pNameTable
+ *pArg
;
2959 /* If arg type follows then paramName points to the 2nd
2960 letter of the name, else the next WORD is an offset to
2961 the arg type and paramName points to the first letter.
2962 So let's take one char off paramName and see if we're
2963 pointing at an alpha-numeric char. However if *pArg is
2964 0xffff or 0xfffe then the param has no name, the former
2965 meaning that the next WORD is the type, the latter
2966 meaning the the next WORD is an offset to the type. */
2971 else if(*pArg
== 0xfffe) {
2975 else if(paramName
[-1] && !isalnum(paramName
[-1]))
2980 if(HaveOffs
) { /* the next word is an offset to type */
2981 pType
= (WORD
*)(pBlk
+ *pArg
);
2982 SLTG_DoElem(pType
, pBlk
,
2983 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2988 pArg
= SLTG_DoElem(pArg
, pBlk
,
2989 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2992 /* Are we an optional param ? */
2993 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2994 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2995 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2998 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2999 TLB_MultiByteToBSTR(paramName
);
3003 ppFuncDesc
= &((*ppFuncDesc
)->next
);
3004 if(pFunc
->next
== 0xffff) break;
3006 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3009 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3010 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3011 SLTG_TypeInfoTail
*pTITail
)
3013 char *pFirstItem
, *pNextItem
;
3015 if(pTIHeader
->href_table
!= 0xffffffff) {
3016 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3020 pFirstItem
= pNextItem
= pBlk
;
3022 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3023 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
3028 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3029 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3030 SLTG_TypeInfoTail
*pTITail
)
3032 char *pFirstItem
, *pNextItem
;
3034 if(pTIHeader
->href_table
!= 0xffffffff) {
3035 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3039 pFirstItem
= pNextItem
= pBlk
;
3041 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3042 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
3045 if (pTITail
->funcs_off
!= 0xffff)
3046 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3048 if (TRACE_ON(typelib
))
3049 dump_TLBFuncDesc(pTI
->funclist
);
3052 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3053 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3054 SLTG_TypeInfoTail
*pTITail
)
3056 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3059 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3060 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3061 SLTG_TypeInfoTail
*pTITail
)
3065 if (pTITail
->simple_alias
) {
3066 /* if simple alias, no more processing required */
3067 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3071 if(pTIHeader
->href_table
!= 0xffffffff) {
3072 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3076 /* otherwise it is an offset to a type */
3077 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3079 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
);
3082 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3083 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3084 SLTG_TypeInfoTail
*pTITail
)
3086 if (pTIHeader
->href_table
!= 0xffffffff)
3087 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3090 if (pTITail
->vars_off
!= 0xffff)
3091 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3093 if (pTITail
->funcs_off
!= 0xffff)
3094 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3096 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3097 * of dispinterface functons including the IDispatch ones, so
3098 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3099 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3101 if (TRACE_ON(typelib
))
3102 dump_TLBFuncDesc(pTI
->funclist
);
3105 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3106 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3107 SLTG_TypeInfoTail
*pTITail
)
3109 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3112 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3113 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3114 SLTG_TypeInfoTail
*pTITail
)
3116 if (pTIHeader
->href_table
!= 0xffffffff)
3117 SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
,
3120 if (pTITail
->vars_off
!= 0xffff)
3121 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
);
3123 if (pTITail
->funcs_off
!= 0xffff)
3124 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
);
3127 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3128 managable copy of it into this */
3141 } SLTG_InternalOtherTypeInfo
;
3143 /****************************************************************************
3144 * ITypeLib2_Constructor_SLTG
3146 * loading a SLTG typelib from an in-memory image
3148 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3150 ITypeLibImpl
*pTypeLibImpl
;
3151 SLTG_Header
*pHeader
;
3152 SLTG_BlkEntry
*pBlkEntry
;
3156 LPVOID pBlk
, pFirstBlk
;
3157 SLTG_LibBlk
*pLibBlk
;
3158 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3159 char *pAfterOTIBlks
= NULL
;
3160 char *pNameTable
, *ptr
;
3163 ITypeInfoImpl
**ppTypeInfoImpl
;
3165 TRACE_(typelib
)("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3168 pTypeLibImpl
= TypeLibImpl_Constructor();
3169 if (!pTypeLibImpl
) return NULL
;
3173 TRACE_(typelib
)("header:\n");
3174 TRACE_(typelib
)("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
3175 pHeader
->nrOfFileBlks
);
3176 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3177 FIXME("Header type magic 0x%08lx not supported.\n",
3178 pHeader
->SLTG_magic
);
3182 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3183 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3185 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3186 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3188 /* Next we have a magic block */
3189 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3191 /* Let's see if we're still in sync */
3192 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3193 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3194 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3197 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3198 sizeof(SLTG_DIR_MAGIC
))) {
3199 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3203 pIndex
= (SLTG_Index
*)(pMagic
+1);
3205 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3207 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3209 /* We'll set up a ptr to the main library block, which is the last one. */
3211 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3212 pBlkEntry
[order
].next
!= 0;
3213 order
= pBlkEntry
[order
].next
- 1, i
++) {
3214 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3218 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3220 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3225 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3227 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3228 sizeof(*pOtherTypeInfoBlks
) *
3229 pTypeLibImpl
->TypeInfoCount
);
3232 ptr
= (char*)pLibBlk
+ len
;
3234 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3238 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3240 w
= *(WORD
*)(ptr
+ 2);
3243 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3245 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3246 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3248 w
= *(WORD
*)(ptr
+ 4 + len
);
3250 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3252 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3254 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3255 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3257 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3258 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3259 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3261 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3263 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3266 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3267 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3268 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3269 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3270 len
+= sizeof(SLTG_OtherTypeInfo
);
3274 pAfterOTIBlks
= ptr
;
3276 /* Skip this WORD and get the next DWORD */
3277 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3279 /* Now add this to pLibBLk look at what we're pointing at and
3280 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3281 dust and we should be pointing at the beginning of the name
3284 pNameTable
= (char*)pLibBlk
+ len
;
3286 switch(*(WORD
*)pNameTable
) {
3293 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3297 pNameTable
+= 0x216;
3301 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3303 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3306 /* Hopefully we now have enough ptrs set up to actually read in
3307 some TypeInfos. It's not clear which order to do them in, so
3308 I'll just follow the links along the BlkEntry chain and read
3309 them in in the order in which they're in the file */
3311 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3313 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3314 pBlkEntry
[order
].next
!= 0;
3315 order
= pBlkEntry
[order
].next
- 1, i
++) {
3317 SLTG_TypeInfoHeader
*pTIHeader
;
3318 SLTG_TypeInfoTail
*pTITail
;
3319 SLTG_MemberHeader
*pMemHeader
;
3321 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3322 pOtherTypeInfoBlks
[i
].index_name
)) {
3323 FIXME("Index strings don't match\n");
3328 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3329 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3332 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3333 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
3335 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3336 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3337 (*ppTypeInfoImpl
)->index
= i
;
3338 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3339 pOtherTypeInfoBlks
[i
].name_offs
+
3341 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3342 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3344 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3345 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3346 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3347 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3348 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3350 if((pTIHeader
->typeflags1
& 7) != 2)
3351 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3352 if(pTIHeader
->typeflags3
!= 2)
3353 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3355 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3356 debugstr_w((*ppTypeInfoImpl
)->Name
),
3357 typekind_desc
[pTIHeader
->typekind
],
3358 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3359 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3361 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
3363 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
3365 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3366 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3367 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3369 switch(pTIHeader
->typekind
) {
3371 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3372 pTIHeader
, pTITail
);
3376 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3377 pTIHeader
, pTITail
);
3380 case TKIND_INTERFACE
:
3381 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3382 pTIHeader
, pTITail
);
3386 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3387 pTIHeader
, pTITail
);
3391 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3392 pTIHeader
, pTITail
);
3395 case TKIND_DISPATCH
:
3396 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3397 pTIHeader
, pTITail
);
3401 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
3402 pTIHeader
, pTITail
);
3406 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3411 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3412 but we've already set those */
3413 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3428 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3429 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3432 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3433 FIXME("Somehow processed %d TypeInfos\n", i
);
3437 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3438 return (ITypeLib2
*)pTypeLibImpl
;
3441 /* ITypeLib::QueryInterface
3443 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3448 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3450 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3453 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3454 IsEqualIID(riid
,&IID_ITypeLib
)||
3455 IsEqualIID(riid
,&IID_ITypeLib2
))
3462 ITypeLib2_AddRef(iface
);
3463 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3466 TRACE("-- Interface: E_NOINTERFACE\n");
3467 return E_NOINTERFACE
;
3472 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3474 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3475 ULONG ref
= InterlockedIncrement(&This
->ref
);
3477 TRACE("(%p)->ref was %lu\n",This
, ref
- 1);
3482 /* ITypeLib::Release
3484 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3486 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3487 ULONG ref
= InterlockedDecrement(&This
->ref
);
3489 TRACE("(%p)->(%lu)\n",This
, ref
);
3493 /* remove cache entry */
3496 TRACE("removing from cache list\n");
3497 EnterCriticalSection(&cache_section
);
3498 if (This
->next
) This
->next
->prev
= This
->prev
;
3499 if (This
->prev
) This
->prev
->next
= This
->next
;
3500 else tlb_cache_first
= This
->next
;
3501 LeaveCriticalSection(&cache_section
);
3502 HeapFree(GetProcessHeap(), 0, This
->path
);
3504 /* FIXME destroy child objects */
3505 TRACE(" destroying ITypeLib(%p)\n",This
);
3509 SysFreeString(This
->Name
);
3513 if (This
->DocString
)
3515 SysFreeString(This
->DocString
);
3516 This
->DocString
= NULL
;
3521 SysFreeString(This
->HelpFile
);
3522 This
->HelpFile
= NULL
;
3525 if (This
->HelpStringDll
)
3527 SysFreeString(This
->HelpStringDll
);
3528 This
->HelpStringDll
= NULL
;
3531 if (This
->pTypeInfo
) /* can be NULL */
3532 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3533 HeapFree(GetProcessHeap(),0,This
);
3540 /* ITypeLib::GetTypeInfoCount
3542 * Returns the number of type descriptions in the type library
3544 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3546 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3547 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3548 return This
->TypeInfoCount
;
3551 /* ITypeLib::GetTypeInfo
3553 * retrieves the specified type description in the library.
3555 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3558 ITypeInfo
**ppTInfo
)
3562 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3563 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3565 TRACE("(%p)->(index=%d)\n", This
, index
);
3567 if (!ppTInfo
) return E_INVALIDARG
;
3569 /* search element n in list */
3570 for(i
=0; i
< index
; i
++)
3572 pTypeInfo
= pTypeInfo
->next
;
3575 TRACE("-- element not found\n");
3576 return TYPE_E_ELEMENTNOTFOUND
;
3580 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3582 ITypeInfo_AddRef(*ppTInfo
);
3583 TRACE("-- found (%p)\n",*ppTInfo
);
3588 /* ITypeLibs::GetTypeInfoType
3590 * Retrieves the type of a type description.
3592 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3597 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3599 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3601 TRACE("(%p) index %d\n", This
, index
);
3603 if(!pTKind
) return E_INVALIDARG
;
3605 /* search element n in list */
3606 for(i
=0; i
< index
; i
++)
3610 TRACE("-- element not found\n");
3611 return TYPE_E_ELEMENTNOTFOUND
;
3613 pTInfo
= pTInfo
->next
;
3616 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3617 TRACE("-- found Type (%d)\n", *pTKind
);
3621 /* ITypeLib::GetTypeInfoOfGuid
3623 * Retrieves the type description that corresponds to the specified GUID.
3626 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3629 ITypeInfo
**ppTInfo
)
3631 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3632 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3634 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3638 WARN("-- element not found\n");
3639 return TYPE_E_ELEMENTNOTFOUND
;
3642 /* search linked list for guid */
3643 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3645 pTypeInfo
= pTypeInfo
->next
;
3649 /* end of list reached */
3650 WARN("-- element not found\n");
3651 return TYPE_E_ELEMENTNOTFOUND
;
3655 TRACE("-- found (%p, %s)\n",
3657 debugstr_w(pTypeInfo
->Name
));
3659 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3660 ITypeInfo_AddRef(*ppTInfo
);
3664 /* ITypeLib::GetLibAttr
3666 * Retrieves the structure that contains the library's attributes.
3669 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3671 LPTLIBATTR
*ppTLibAttr
)
3673 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3674 TRACE("(%p)\n",This
);
3675 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3676 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3680 /* ITypeLib::GetTypeComp
3682 * Enables a client compiler to bind to a library's types, variables,
3683 * constants, and global functions.
3686 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3688 ITypeComp
**ppTComp
)
3690 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3692 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3693 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3694 ITypeComp_AddRef(*ppTComp
);
3699 /* ITypeLib::GetDocumentation
3701 * Retrieves the library's documentation string, the complete Help file name
3702 * and path, and the context identifier for the library Help topic in the Help
3705 * On a successful return all non-null BSTR pointers will have been set,
3708 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3712 BSTR
*pBstrDocString
,
3713 DWORD
*pdwHelpContext
,
3714 BSTR
*pBstrHelpFile
)
3716 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3718 HRESULT result
= E_INVALIDARG
;
3723 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3725 pBstrName
, pBstrDocString
,
3726 pdwHelpContext
, pBstrHelpFile
);
3730 /* documentation for the typelib */
3735 if(!(*pBstrName
= SysAllocString(This
->Name
)))
3743 if (This
->DocString
)
3745 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
3748 else if (This
->Name
)
3750 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
3754 *pBstrDocString
= NULL
;
3758 *pdwHelpContext
= This
->dwHelpContext
;
3764 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
3768 *pBstrHelpFile
= NULL
;
3775 /* for a typeinfo */
3776 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3778 if(SUCCEEDED(result
))
3780 result
= ITypeInfo_GetDocumentation(pTInfo
,
3784 pdwHelpContext
, pBstrHelpFile
);
3786 ITypeInfo_Release(pTInfo
);
3791 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3793 if (pBstrName
) SysFreeString (*pBstrName
);
3795 return STG_E_INSUFFICIENTMEMORY
;
3800 * Indicates whether a passed-in string contains the name of a type or member
3801 * described in the library.
3804 static HRESULT WINAPI
ITypeLib2_fnIsName(
3810 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3811 ITypeInfoImpl
*pTInfo
;
3812 TLBFuncDesc
*pFInfo
;
3815 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3817 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3821 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3822 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3823 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3824 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3825 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3826 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3827 goto ITypeLib2_fnIsName_exit
;
3829 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3830 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3835 ITypeLib2_fnIsName_exit
:
3836 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3837 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3842 /* ITypeLib::FindName
3844 * Finds occurrences of a type description in a type library. This may be used
3845 * to quickly verify that a name exists in a type library.
3848 static HRESULT WINAPI
ITypeLib2_fnFindName(
3852 ITypeInfo
**ppTInfo
,
3856 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3857 ITypeInfoImpl
*pTInfo
;
3858 TLBFuncDesc
*pFInfo
;
3861 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3863 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3864 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3865 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3866 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3867 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
3868 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3869 goto ITypeLib2_fnFindName_exit
;
3872 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3873 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3875 ITypeLib2_fnFindName_exit
:
3876 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3877 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3880 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3881 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3888 /* ITypeLib::ReleaseTLibAttr
3890 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3893 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3895 TLIBATTR
*pTLibAttr
)
3897 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3898 TRACE("freeing (%p)\n",This
);
3899 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3903 /* ITypeLib2::GetCustData
3905 * gets the custom data
3907 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3912 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3913 TLBCustData
*pCData
;
3915 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3917 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3920 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3924 VariantInit( pVarVal
);
3925 VariantCopy( pVarVal
, &pCData
->data
);
3928 return E_INVALIDARG
; /* FIXME: correct? */
3931 /* ITypeLib2::GetLibStatistics
3933 * Returns statistics about a type library that are required for efficient
3934 * sizing of hash tables.
3937 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3939 ULONG
*pcUniqueNames
,
3940 ULONG
*pcchUniqueNames
)
3942 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3944 FIXME("(%p): stub!\n", This
);
3946 if(pcUniqueNames
) *pcUniqueNames
=1;
3947 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3951 /* ITypeLib2::GetDocumentation2
3953 * Retrieves the library's documentation string, the complete Help file name
3954 * and path, the localization context to use, and the context ID for the
3955 * library Help topic in the Help file.
3958 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3962 BSTR
*pbstrHelpString
,
3963 DWORD
*pdwHelpStringContext
,
3964 BSTR
*pbstrHelpStringDll
)
3966 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3970 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3972 /* the help string should be obtained from the helpstringdll,
3973 * using the _DLLGetDocumentation function, based on the supplied
3974 * lcid. Nice to do sometime...
3978 /* documentation for the typelib */
3980 *pbstrHelpString
=SysAllocString(This
->DocString
);
3981 if(pdwHelpStringContext
)
3982 *pdwHelpStringContext
=This
->dwHelpContext
;
3983 if(pbstrHelpStringDll
)
3984 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3990 /* for a typeinfo */
3991 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3993 if(SUCCEEDED(result
))
3995 ITypeInfo2
* pTInfo2
;
3996 result
= ITypeInfo_QueryInterface(pTInfo
,
3998 (LPVOID
*) &pTInfo2
);
4000 if(SUCCEEDED(result
))
4002 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4006 pdwHelpStringContext
,
4007 pbstrHelpStringDll
);
4009 ITypeInfo2_Release(pTInfo2
);
4012 ITypeInfo_Release(pTInfo
);
4018 /* ITypeLib2::GetAllCustData
4020 * Gets all custom data items for the library.
4023 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4025 CUSTDATA
*pCustData
)
4027 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4028 TLBCustData
*pCData
;
4030 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4031 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4032 if(pCustData
->prgCustData
){
4033 pCustData
->cCustData
=This
->ctCustData
;
4034 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4035 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4036 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4039 ERR(" OUT OF MEMORY!\n");
4040 return E_OUTOFMEMORY
;
4045 static const ITypeLib2Vtbl tlbvt
= {
4046 ITypeLib2_fnQueryInterface
,
4048 ITypeLib2_fnRelease
,
4049 ITypeLib2_fnGetTypeInfoCount
,
4050 ITypeLib2_fnGetTypeInfo
,
4051 ITypeLib2_fnGetTypeInfoType
,
4052 ITypeLib2_fnGetTypeInfoOfGuid
,
4053 ITypeLib2_fnGetLibAttr
,
4054 ITypeLib2_fnGetTypeComp
,
4055 ITypeLib2_fnGetDocumentation
,
4057 ITypeLib2_fnFindName
,
4058 ITypeLib2_fnReleaseTLibAttr
,
4060 ITypeLib2_fnGetCustData
,
4061 ITypeLib2_fnGetLibStatistics
,
4062 ITypeLib2_fnGetDocumentation2
,
4063 ITypeLib2_fnGetAllCustData
4067 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4069 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4071 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4074 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4076 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4078 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4081 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4083 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4085 return ITypeLib2_Release((ITypeLib2
*)This
);
4088 static HRESULT WINAPI
ITypeLibComp_fnBind(
4093 ITypeInfo
** ppTInfo
,
4094 DESCKIND
* pDescKind
,
4097 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4098 ITypeInfoImpl
*pTypeInfo
;
4100 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4102 *pDescKind
= DESCKIND_NONE
;
4103 pBindPtr
->lptcomp
= NULL
;
4106 for (pTypeInfo
= This
->pTypeInfo
; pTypeInfo
; pTypeInfo
= pTypeInfo
->next
)
4108 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4110 /* FIXME: check wFlags here? */
4111 /* FIXME: we should use a hash table to look this info up using lHash
4112 * instead of an O(n) search */
4113 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4114 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4116 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4118 *pDescKind
= DESCKIND_TYPECOMP
;
4119 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4120 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4121 TRACE("module or enum: %s\n", debugstr_w(szName
));
4126 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4127 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4129 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4132 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4133 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4135 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4140 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4141 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4143 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4145 ITypeInfo
*subtypeinfo
;
4147 DESCKIND subdesckind
;
4149 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4150 &subtypeinfo
, &subdesckind
, &subbindptr
);
4151 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4153 TYPEDESC tdesc_appobject
=
4156 (TYPEDESC
*)pTypeInfo
->hreftype
4160 const VARDESC vardesc_appobject
=
4163 NULL
, /* lpstrSchema */
4178 VAR_STATIC
/* varkind */
4181 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4183 /* cleanup things filled in by Bind call so we can put our
4184 * application object data in there instead */
4185 switch (subdesckind
)
4187 case DESCKIND_FUNCDESC
:
4188 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4190 case DESCKIND_VARDESC
:
4191 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4196 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4198 if (pTypeInfo
->hreftype
== -1)
4199 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4201 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4205 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4206 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4207 ITypeInfo_AddRef(*ppTInfo
);
4213 TRACE("name not found %s\n", debugstr_w(szName
));
4217 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4221 ITypeInfo
** ppTInfo
,
4222 ITypeComp
** ppTComp
)
4224 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4228 static const ITypeCompVtbl tlbtcvt
=
4231 ITypeLibComp_fnQueryInterface
,
4232 ITypeLibComp_fnAddRef
,
4233 ITypeLibComp_fnRelease
,
4235 ITypeLibComp_fnBind
,
4236 ITypeLibComp_fnBindType
4239 /*================== ITypeInfo(2) Methods ===================================*/
4240 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4242 ITypeInfoImpl
* pTypeInfoImpl
;
4244 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4247 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4248 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4249 pTypeInfoImpl
->ref
=1;
4250 pTypeInfoImpl
->hreftype
= -1;
4251 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
4252 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
4254 TRACE("(%p)\n", pTypeInfoImpl
);
4255 return (ITypeInfo2
*) pTypeInfoImpl
;
4258 /* ITypeInfo::QueryInterface
4260 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4265 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4267 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4270 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4271 IsEqualIID(riid
,&IID_ITypeInfo
)||
4272 IsEqualIID(riid
,&IID_ITypeInfo2
))
4276 ITypeInfo_AddRef(iface
);
4277 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4280 TRACE("-- Interface: E_NOINTERFACE\n");
4281 return E_NOINTERFACE
;
4284 /* ITypeInfo::AddRef
4286 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4288 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4289 ULONG ref
= InterlockedIncrement(&This
->ref
);
4291 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4293 TRACE("(%p)->ref is %lu\n",This
, ref
);
4297 /* ITypeInfo::Release
4299 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4301 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4302 ULONG ref
= InterlockedDecrement(&This
->ref
);
4304 TRACE("(%p)->(%lu)\n",This
, ref
);
4307 /* We don't release ITypeLib when ref=0 because
4308 it means that function is called by ITypeLib2_Release */
4309 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4311 static int once
= 0;
4315 FIXME("destroy child objects\n");
4318 TRACE("destroying ITypeInfo(%p)\n",This
);
4321 SysFreeString(This
->Name
);
4325 if (This
->DocString
)
4327 SysFreeString(This
->DocString
);
4328 This
->DocString
= 0;
4333 SysFreeString(This
->DllName
);
4339 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4342 HeapFree(GetProcessHeap(),0,This
);
4348 /* ITypeInfo::GetTypeAttr
4350 * Retrieves a TYPEATTR structure that contains the attributes of the type
4354 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4355 LPTYPEATTR
*ppTypeAttr
)
4357 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4360 TRACE("(%p)\n",This
);
4362 size
= sizeof(**ppTypeAttr
);
4363 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4364 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
4366 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, size
);
4368 return E_OUTOFMEMORY
;
4370 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4372 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
4373 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
4374 &This
->TypeAttr
.tdescAlias
, (void *)(*ppTypeAttr
+ 1));
4376 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
4377 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4379 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4380 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4385 /* ITypeInfo::GetTypeComp
4387 * Retrieves the ITypeComp interface for the type description, which enables a
4388 * client compiler to bind to the type description's members.
4391 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4392 ITypeComp
* *ppTComp
)
4394 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4396 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4398 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4399 ITypeComp_AddRef(*ppTComp
);
4403 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
4405 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
4406 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4407 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
4411 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
4413 memcpy(dest
, src
, sizeof(ELEMDESC
));
4414 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
4415 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4417 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
4418 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
4419 *buffer
+= sizeof(PARAMDESCEX
);
4420 memcpy(pparamdescex_dest
, pparamdescex_src
, sizeof(PARAMDESCEX
));
4421 VariantInit(&pparamdescex_dest
->varDefaultValue
);
4422 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
4423 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
4426 dest
->u
.paramdesc
.pparamdescex
= NULL
;
4430 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
4432 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4433 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
4436 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
4440 SIZE_T size
= sizeof(*src
);
4444 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4445 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
4446 for (i
= 0; i
< src
->cParams
; i
++)
4448 size
+= sizeof(ELEMDESC
);
4449 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
4452 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
4453 if (!dest
) return E_OUTOFMEMORY
;
4455 memcpy(dest
, src
, sizeof(FUNCDESC
));
4456 buffer
= (char *)(dest
+ 1);
4458 dest
->lprgscode
= (SCODE
*)buffer
;
4459 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
4460 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
4462 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
4465 SysFreeString((BSTR
)dest
);
4469 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
4470 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
4471 for (i
= 0; i
< src
->cParams
; i
++)
4473 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
4479 /* undo the above actions */
4480 for (i
= i
- 1; i
>= 0; i
--)
4481 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
4482 TLB_FreeElemDesc(&dest
->elemdescFunc
);
4483 SysFreeString((BSTR
)dest
);
4487 /* special treatment for dispinterfaces: this makes functions appear
4488 * to return their [retval] value when it is really returning an
4490 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
4492 if (dest
->cParams
&&
4493 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
4495 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
4496 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
4498 ERR("elemdesc should have started with VT_PTR instead of:\n");
4500 dump_ELEMDESC(elemdesc
);
4501 return E_UNEXPECTED
;
4504 /* copy last parameter to the return value. we are using a flat
4505 * buffer so there is no danger of leaking memory in
4507 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
4509 /* remove the last parameter */
4513 /* otherwise this function is made to appear to have no return
4515 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
4523 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
4525 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4526 const TLBFuncDesc
*pFDesc
;
4529 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4534 *ppFuncDesc
= &pFDesc
->funcdesc
;
4538 return E_INVALIDARG
;
4541 /* ITypeInfo::GetFuncDesc
4543 * Retrieves the FUNCDESC structure that contains information about a
4544 * specified function.
4547 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4548 LPFUNCDESC
*ppFuncDesc
)
4550 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4551 const FUNCDESC
*internal_funcdesc
;
4554 TRACE("(%p) index %d\n", This
, index
);
4556 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &internal_funcdesc
);
4560 return TLB_AllocAndInitFuncDesc(
4563 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
4566 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
4570 SIZE_T size
= sizeof(*src
);
4573 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
4574 if (src
->varkind
== VAR_CONST
)
4575 size
+= sizeof(VARIANT
);
4576 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
4578 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
4579 if (!dest
) return E_OUTOFMEMORY
;
4582 buffer
= (char *)(dest
+ 1);
4583 if (src
->lpstrSchema
)
4586 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
4587 len
= strlenW(src
->lpstrSchema
);
4588 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
4589 buffer
+= (len
+ 1) * sizeof(WCHAR
);
4592 if (src
->varkind
== VAR_CONST
)
4596 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
4597 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
4598 buffer
+= sizeof(VARIANT
);
4599 VariantInit(dest
->u
.lpvarValue
);
4600 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
4603 SysFreeString((BSTR
)dest_ptr
);
4607 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
4610 if (src
->varkind
== VAR_CONST
)
4611 VariantClear(dest
->u
.lpvarValue
);
4612 SysFreeString((BSTR
)dest
);
4619 /* ITypeInfo::GetVarDesc
4621 * Retrieves a VARDESC structure that describes the specified variable.
4624 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4625 LPVARDESC
*ppVarDesc
)
4627 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4629 const TLBVarDesc
*pVDesc
;
4631 TRACE("(%p) index %d\n", This
, index
);
4633 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4637 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
4639 return E_INVALIDARG
;
4642 /* ITypeInfo_GetNames
4644 * Retrieves the variable with the specified member ID (or the name of the
4645 * property or method and its parameters) that correspond to the specified
4648 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4649 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4651 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4652 const TLBFuncDesc
*pFDesc
;
4653 const TLBVarDesc
*pVDesc
;
4655 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4656 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4659 /* function found, now return function and parameter names */
4660 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4663 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4665 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4671 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4674 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4679 if(This
->TypeAttr
.cImplTypes
&&
4680 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4681 /* recursive search */
4684 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4686 if(SUCCEEDED(result
))
4688 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4689 ITypeInfo_Release(pTInfo
);
4692 WARN("Could not search inherited interface!\n");
4696 WARN("no names found\n");
4699 return TYPE_E_ELEMENTNOTFOUND
;
4706 /* ITypeInfo::GetRefTypeOfImplType
4708 * If a type description describes a COM class, it retrieves the type
4709 * description of the implemented interface types. For an interface,
4710 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4714 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4719 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4722 const TLBImplType
*pImpl
= This
->impltypelist
;
4724 TRACE("(%p) index %d\n", This
, index
);
4725 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4729 /* only valid on dual interfaces;
4730 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4732 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4734 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4735 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4741 hr
= TYPE_E_ELEMENTNOTFOUND
;
4746 /* get element n from linked list */
4747 for(i
=0; pImpl
&& i
<index
; i
++)
4749 pImpl
= pImpl
->next
;
4753 *pRefType
= pImpl
->hRef
;
4755 hr
= TYPE_E_ELEMENTNOTFOUND
;
4761 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType
);
4763 TRACE("FAILURE -- hresult = 0x%08lx\n", hr
);
4769 /* ITypeInfo::GetImplTypeFlags
4771 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4772 * or base interface in a type description.
4774 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4775 UINT index
, INT
*pImplTypeFlags
)
4777 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4781 TRACE("(%p) index %d\n", This
, index
);
4782 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4783 i
++, pImpl
=pImpl
->next
)
4785 if(i
==index
&& pImpl
){
4786 *pImplTypeFlags
=pImpl
->implflags
;
4790 return TYPE_E_ELEMENTNOTFOUND
;
4794 * Maps between member names and member IDs, and parameter names and
4797 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4798 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4800 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4801 const TLBFuncDesc
*pFDesc
;
4802 const TLBVarDesc
*pVDesc
;
4806 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4809 /* init out parameters in case of failure */
4810 for (i
= 0; i
< cNames
; i
++)
4811 pMemId
[i
] = MEMBERID_NIL
;
4813 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4815 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4816 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4817 for(i
=1; i
< cNames
; i
++){
4818 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4819 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4821 if( j
<pFDesc
->funcdesc
.cParams
)
4824 ret
=DISP_E_UNKNOWNNAME
;
4826 TRACE("-- 0x%08lx\n", ret
);
4830 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4831 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4832 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4836 /* not found, see if it can be found in an inherited interface */
4837 if(This
->TypeAttr
.cImplTypes
) {
4838 /* recursive search */
4840 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4841 This
->impltypelist
->hRef
, &pTInfo
);
4843 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4844 ITypeInfo_Release(pTInfo
);
4847 WARN("Could not search inherited interface!\n");
4849 WARN("no names found\n");
4850 return DISP_E_UNKNOWNNAME
;
4853 /* ITypeInfo::Invoke
4855 * Invokes a method, or accesses a property of an object, that implements the
4856 * interface described by the type description.
4859 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4862 if (TRACE_ON(ole
)) {
4864 TRACE("Calling %p(",func
);
4865 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4877 res
= func(args
[0]);
4880 res
= func(args
[0],args
[1]);
4883 res
= func(args
[0],args
[1],args
[2]);
4886 res
= func(args
[0],args
[1],args
[2],args
[3]);
4889 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4892 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4895 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4898 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4901 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4904 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
4907 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
4910 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]);
4913 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]);
4916 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]);
4919 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14]);
4922 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15]);
4925 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16]);
4928 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17]);
4931 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18]);
4934 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19]);
4937 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20]);
4940 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21]);
4943 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10],args
[11],args
[12],args
[13],args
[14],args
[15],args
[16],args
[17],args
[18],args
[19],args
[20],args
[21],args
[22]);
4946 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4952 FIXME("unsupported calling convention %d\n",callconv
);
4956 TRACE("returns %08lx\n",res
);
4960 extern int _argsize(DWORD vt
);
4962 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
4965 ITypeInfo
*tinfo2
= NULL
;
4966 TYPEATTR
*tattr
= NULL
;
4968 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
4971 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4973 tdesc
->u
.hreftype
, hr
);
4976 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
4979 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr
);
4980 ITypeInfo_Release(tinfo2
);
4984 switch (tattr
->typekind
)
4991 tdesc
= &tattr
->tdescAlias
;
4992 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
4995 case TKIND_INTERFACE
:
4996 if (IsEqualIID(&IID_IDispatch
, &tattr
->guid
))
5002 case TKIND_DISPATCH
:
5007 FIXME("TKIND_RECORD unhandled.\n");
5012 FIXME("TKIND_UNION unhandled.\n");
5017 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5021 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5022 ITypeInfo_Release(tinfo2
);
5026 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5030 /* enforce only one level of pointer indirection */
5031 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5033 tdesc
= tdesc
->u
.lptdesc
;
5035 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5036 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5037 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5038 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5039 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5041 VARTYPE vt_userdefined
= 0;
5042 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5043 if (tdesc
->vt
== VT_PTR
)
5045 vt_userdefined
= VT_BYREF
;
5046 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5048 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5050 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5051 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5053 *vt
|= vt_userdefined
;
5065 case VT_USERDEFINED
:
5066 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5073 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5074 hr
= DISP_E_BADVARTYPE
;
5078 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
5087 /***********************************************************************
5088 * DispCallFunc (OLEAUT32.@)
5090 * Invokes a function of the specifed calling convention, passing the
5091 * specified arguments and returns the result.
5094 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5095 * oVft [I] The offset in the vtable. See notes.
5096 * cc [I] Calling convention of the function to call.
5097 * vtReturn [I] The return type of the function.
5098 * cActuals [I] Number of parameters.
5099 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5100 * prgpvarg [I] The arguments to pass.
5101 * pvargResult [O] The return value of the function. Can be NULL.
5105 * Failure: HRESULT code.
5108 * The HRESULT return value of this function is not affected by the return
5109 * value of the user supplied function, which is returned in pvargResult.
5111 * If pvInstance is NULL then a non-object function is to be called and oVft
5112 * is the address of the function to call.
5114 * The cc parameter can be one of the following values:
5127 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
5128 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
5130 int i
, argsize
, argspos
;
5134 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5135 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
5136 pvargResult
, V_VT(pvargResult
));
5140 argsize
++; /* for This pointer */
5142 for (i
=0;i
<cActuals
;i
++)
5144 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
5145 dump_Variant(prgpvarg
[i
]);
5146 argsize
+= _argsize(prgvt
[i
]);
5148 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
5153 args
[0] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
5157 for (i
=0;i
<cActuals
;i
++)
5159 VARIANT
*arg
= prgpvarg
[i
];
5160 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
5161 if (prgvt
[i
] == VT_VARIANT
)
5162 memcpy(&args
[argspos
], arg
, _argsize(prgvt
[i
]) * sizeof(DWORD
));
5164 memcpy(&args
[argspos
], &V_NONE(arg
), _argsize(prgvt
[i
]) * sizeof(DWORD
));
5165 argspos
+= _argsize(prgvt
[i
]);
5170 FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
5171 hres
= _invoke(vtable
[oVft
/sizeof(void *)], cc
, argsize
, args
);
5174 /* if we aren't invoking an object then the function pointer is stored
5176 hres
= _invoke((FARPROC
)oVft
, cc
, argsize
, args
);
5178 if (pvargResult
&& (vtReturn
!= VT_EMPTY
))
5180 TRACE("Method returned 0x%08lx\n",hres
);
5181 V_VT(pvargResult
) = vtReturn
;
5182 V_UI4(pvargResult
) = hres
;
5185 HeapFree(GetProcessHeap(),0,args
);
5189 #define INVBUF_ELEMENT_SIZE \
5190 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5191 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5192 ((VARIANTARG *)(buffer))
5193 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5194 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5195 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5196 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5197 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5198 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5200 static HRESULT WINAPI
ITypeInfo_fnInvoke(
5205 DISPPARAMS
*pDispParams
,
5206 VARIANT
*pVarResult
,
5207 EXCEPINFO
*pExcepInfo
,
5210 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5212 unsigned int var_index
;
5215 const TLBFuncDesc
*pFuncInfo
;
5217 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5218 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
5220 dump_DispParms(pDispParams
);
5222 /* we do this instead of using GetFuncDesc since it will return a fake
5223 * FUNCDESC for dispinterfaces and we want the real function description */
5224 for (pFuncInfo
= This
->funclist
; pFuncInfo
; pFuncInfo
=pFuncInfo
->next
)
5225 if (memid
== pFuncInfo
->funcdesc
.memid
&& (wFlags
& pFuncInfo
->funcdesc
.invkind
))
5229 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
5233 TRACE("invoking:\n");
5234 dump_TLBFuncDescOne(pFuncInfo
);
5237 switch (func_desc
->funckind
) {
5238 case FUNC_PUREVIRTUAL
:
5239 case FUNC_VIRTUAL
: {
5240 void *buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
5242 VARIANT retval
; /* pointer for storing byref retvals in */
5243 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
5244 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
5245 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
5248 for (i
= 0; i
< func_desc
->cParams
; i
++)
5250 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
5251 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
5256 TRACE("changing args\n");
5257 for (i
= 0; i
< func_desc
->cParams
; i
++)
5259 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5261 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5263 /* note: this check is placed so that if the caller passes
5264 * in a VARIANTARG for the retval we just ignore it, like
5266 if (i
== func_desc
->cParams
- 1)
5269 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5270 memset(arg
, 0, sizeof(*arg
));
5271 V_VT(arg
) = rgvt
[i
];
5272 memset(&retval
, 0, sizeof(retval
));
5273 V_BYREF(arg
) = &retval
;
5277 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
5278 hres
= E_UNEXPECTED
;
5282 else if (i
< pDispParams
->cArgs
)
5284 VARIANTARG
*src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
];
5285 dump_Variant(src_arg
);
5287 if (rgvt
[i
] == VT_VARIANT
)
5288 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
5289 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
5291 if (rgvt
[i
] == V_VT(src_arg
))
5292 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
5295 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5296 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
5297 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
5299 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5301 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
5303 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5304 V_VT(&missing_arg
[i
]) = V_VT(src_arg
);
5305 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
5306 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
5307 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5309 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
5311 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
5312 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5316 /* FIXME: this doesn't work for VT_BYREF arguments if
5317 * they are not the same type as in the paramdesc */
5318 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
5319 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
5320 V_VT(&rgvarg
[i
]) = rgvt
[i
];
5325 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
5326 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
5327 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
5330 prgpvarg
[i
] = &rgvarg
[i
];
5332 else if (wParamFlags
& PARAMFLAG_FOPT
)
5335 arg
= prgpvarg
[i
] = &rgvarg
[i
];
5336 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5338 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
5344 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
5345 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
5346 V_VARIANTREF(arg
) = &missing_arg
[i
];
5347 V_VT(V_VARIANTREF(arg
)) = VT_ERROR
;
5348 V_ERROR(V_VARIANTREF(arg
)) = DISP_E_PARAMNOTFOUND
;
5353 hres
= DISP_E_BADPARAMCOUNT
;
5357 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5358 if (func_desc
->cParamsOpt
< 0)
5360 FIXME("Does not support safearray optional parameters\n");
5361 hres
= DISP_E_BADPARAMCOUNT
;
5362 goto func_fail
; /* FIXME: we don't free changed types here */
5365 V_VT(&varresult
) = 0;
5366 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
5367 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
5369 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
5370 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
5371 prgpvarg
, &varresult
);
5373 for (i
= 0; i
< func_desc
->cParams
; i
++)
5375 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
5376 if (wParamFlags
& PARAMFLAG_FRETVAL
)
5380 TRACE("[retval] value: ");
5381 dump_Variant(prgpvarg
[i
]);
5385 /* deref return value */
5386 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
5388 /* free data stored in varresult. Note that
5389 * VariantClear doesn't do what we want because we are
5390 * working with byref types. */
5391 /* FIXME: clear safearrays, bstrs, records and
5392 * variants here too */
5393 if ((V_VT(prgpvarg
[i
]) == (VT_UNKNOWN
| VT_BYREF
)) ||
5394 (V_VT(prgpvarg
[i
]) == (VT_DISPATCH
| VT_BYREF
)))
5396 if(*V_UNKNOWNREF(prgpvarg
[i
]))
5397 IUnknown_Release(*V_UNKNOWNREF(prgpvarg
[i
]));
5401 else if (i
< pDispParams
->cArgs
)
5403 if (wParamFlags
& PARAMFLAG_FOUT
)
5405 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
];
5407 if ((rgvt
[i
] == VT_BYREF
) && (V_VT(arg
) != VT_BYREF
))
5408 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
5412 ERR("failed to convert param %d to vt %d\n", i
,
5413 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
]));
5417 VariantClear(&rgvarg
[i
]);
5419 else if (wParamFlags
& PARAMFLAG_FOPT
)
5421 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5422 VariantClear(&rgvarg
[i
]);
5426 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
5428 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult
));
5429 hres
= DISP_E_EXCEPTION
;
5430 if (pExcepInfo
) pExcepInfo
->scode
= V_ERROR(&varresult
);
5434 HeapFree(GetProcessHeap(), 0, buffer
);
5437 case FUNC_DISPATCH
: {
5440 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
5441 if (SUCCEEDED(hres
)) {
5442 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5443 hres
= IDispatch_Invoke(
5444 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
5445 pVarResult
,pExcepInfo
,pArgErr
5448 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres
);
5449 IDispatch_Release(disp
);
5451 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5455 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
5460 TRACE("-- 0x%08lx\n", hres
);
5463 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
5466 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
5467 if(FAILED(hres
)) return hres
;
5469 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5470 dump_VARDESC(var_desc
);
5471 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
5475 /* not found, look for it in inherited interfaces */
5476 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
5477 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
5479 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface
, 0, &ref_type
))) {
5480 /* recursive search */
5482 hres
= ITypeInfo_GetRefTypeInfo(iface
, ref_type
, &pTInfo
);
5483 if(SUCCEEDED(hres
)){
5484 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
5485 ITypeInfo_Release(pTInfo
);
5488 WARN("Could not search inherited interface!\n");
5491 ERR("did not find member id %ld, flags 0x%x!\n", memid
, wFlags
);
5492 return DISP_E_MEMBERNOTFOUND
;
5495 /* ITypeInfo::GetDocumentation
5497 * Retrieves the documentation string, the complete Help file name and path,
5498 * and the context ID for the Help topic for a specified type description.
5500 * (Can be tested by the Visual Basic Editor in Word for instance.)
5502 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
5503 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
5504 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
5506 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5507 const TLBFuncDesc
*pFDesc
;
5508 const TLBVarDesc
*pVDesc
;
5509 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5510 " HelpContext(%p) HelpFile(%p)\n",
5511 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
5512 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5514 *pBstrName
=SysAllocString(This
->Name
);
5516 *pBstrDocString
=SysAllocString(This
->DocString
);
5518 *pdwHelpContext
=This
->dwHelpContext
;
5520 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
5522 }else {/* for a member */
5523 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5524 if(pFDesc
->funcdesc
.memid
==memid
){
5526 *pBstrName
= SysAllocString(pFDesc
->Name
);
5528 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
5530 *pdwHelpContext
=pFDesc
->helpcontext
;
5533 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5534 if(pVDesc
->vardesc
.memid
==memid
){
5536 *pBstrName
= SysAllocString(pVDesc
->Name
);
5538 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
5540 *pdwHelpContext
=pVDesc
->HelpContext
;
5544 WARN("member %ld not found\n", memid
);
5545 return TYPE_E_ELEMENTNOTFOUND
;
5548 /* ITypeInfo::GetDllEntry
5550 * Retrieves a description or specification of an entry point for a function
5553 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5554 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5557 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5558 const TLBFuncDesc
*pFDesc
;
5560 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5562 if (pBstrDllName
) *pBstrDllName
= NULL
;
5563 if (pBstrName
) *pBstrName
= NULL
;
5564 if (pwOrdinal
) *pwOrdinal
= 0;
5566 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
5567 return TYPE_E_BADMODULEKIND
;
5569 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5570 if(pFDesc
->funcdesc
.memid
==memid
){
5571 dump_TypeInfo(This
);
5573 dump_TLBFuncDescOne(pFDesc
);
5576 *pBstrDllName
= SysAllocString(This
->DllName
);
5578 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5580 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5588 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5591 return TYPE_E_ELEMENTNOTFOUND
;
5594 /* ITypeInfo::GetRefTypeInfo
5596 * If a type description references other type descriptions, it retrieves
5597 * the referenced type descriptions.
5599 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5602 ITypeInfo
**ppTInfo
)
5604 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5605 HRESULT result
= E_FAIL
;
5607 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
5609 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5610 ITypeInfo_AddRef(*ppTInfo
);
5613 else if (hRefType
== -1 &&
5614 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5615 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5617 /* when we meet a DUAL dispinterface, we must create the interface
5620 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5623 /* the interface version contains the same information as the dispinterface
5624 * copy the contents of the structs.
5626 *pTypeInfoImpl
= *This
;
5627 pTypeInfoImpl
->ref
= 1;
5629 /* change the type to interface */
5630 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5632 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5634 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
5639 TLBRefType
*pRefType
;
5640 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5641 if(pRefType
->reference
== hRefType
)
5645 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
5646 if(pRefType
&& hRefType
!= -1) {
5647 ITypeLib
*pTLib
= NULL
;
5649 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5651 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5653 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5654 TRACE("typeinfo in imported typelib that is already loaded\n");
5655 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5656 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5659 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5660 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5661 pRefType
->pImpTLInfo
->wVersionMajor
,
5662 pRefType
->pImpTLInfo
->wVersionMinor
,
5663 pRefType
->pImpTLInfo
->lcid
,
5666 if(!SUCCEEDED(result
)) {
5667 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5668 result
=LoadTypeLib(libnam
, &pTLib
);
5669 SysFreeString(libnam
);
5671 if(SUCCEEDED(result
)) {
5672 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5673 ITypeLib2_AddRef(pTLib
);
5677 if(SUCCEEDED(result
)) {
5678 if(pRefType
->index
== TLB_REF_USE_GUID
)
5679 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5683 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5687 ITypeLib2_Release(pTLib
);
5691 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
5692 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5696 /* ITypeInfo::AddressOfMember
5698 * Retrieves the addresses of static functions or variables, such as those
5701 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5702 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5704 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5710 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
5712 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
5716 module
= LoadLibraryW(dll
);
5719 ERR("couldn't load %s\n", debugstr_w(dll
));
5721 if (entry
) SysFreeString(entry
);
5722 return STG_E_FILENOTFOUND
;
5724 /* FIXME: store library somewhere where we can free it */
5729 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
5730 entryA
= HeapAlloc(GetProcessHeap(), 0, len
);
5731 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
5733 *ppv
= GetProcAddress(module
, entryA
);
5735 ERR("function not found %s\n", debugstr_a(entryA
));
5737 HeapFree(GetProcessHeap(), 0, entryA
);
5741 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
5743 ERR("function not found %d\n", ordinal
);
5747 if (entry
) SysFreeString(entry
);
5750 return TYPE_E_DLLFUNCTIONNOTFOUND
;
5755 /* ITypeInfo::CreateInstance
5757 * Creates a new instance of a type that describes a component object class
5760 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
5761 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
5763 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5764 FIXME("(%p) stub!\n", This
);
5768 /* ITypeInfo::GetMops
5770 * Retrieves marshalling information.
5772 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
5775 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5776 FIXME("(%p) stub!\n", This
);
5780 /* ITypeInfo::GetContainingTypeLib
5782 * Retrieves the containing type library and the index of the type description
5783 * within that type library.
5785 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
5786 ITypeLib
* *ppTLib
, UINT
*pIndex
)
5788 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5790 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5792 *pIndex
=This
->index
;
5793 TRACE("returning pIndex=%d\n", *pIndex
);
5797 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
5798 ITypeLib2_AddRef(*ppTLib
);
5799 TRACE("returning ppTLib=%p\n", *ppTLib
);
5805 /* ITypeInfo::ReleaseTypeAttr
5807 * Releases a TYPEATTR previously returned by GetTypeAttr.
5810 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
5811 TYPEATTR
* pTypeAttr
)
5813 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5814 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
5815 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
5818 /* ITypeInfo::ReleaseFuncDesc
5820 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5822 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
5824 FUNCDESC
*pFuncDesc
)
5826 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5829 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
5831 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5832 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
5833 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
5835 SysFreeString((BSTR
)pFuncDesc
);
5838 /* ITypeInfo::ReleaseVarDesc
5840 * Releases a VARDESC previously returned by GetVarDesc.
5842 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5845 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5846 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5848 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
5849 if (pVarDesc
->varkind
== VAR_CONST
)
5850 VariantClear(pVarDesc
->u
.lpvarValue
);
5851 SysFreeString((BSTR
)pVarDesc
);
5854 /* ITypeInfo2::GetTypeKind
5856 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5859 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5860 TYPEKIND
*pTypeKind
)
5862 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5863 *pTypeKind
=This
->TypeAttr
.typekind
;
5864 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5868 /* ITypeInfo2::GetTypeFlags
5870 * Returns the type flags without any allocations. This returns a DWORD type
5871 * flag, which expands the type flags without growing the TYPEATTR (type
5875 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5877 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5878 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5879 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5883 /* ITypeInfo2::GetFuncIndexOfMemId
5884 * Binds to a specific member based on a known DISPID, where the member name
5885 * is not known (for example, when binding to a default member).
5888 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5889 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5891 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5892 const TLBFuncDesc
*pFuncInfo
;
5896 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
5897 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
5903 result
= TYPE_E_ELEMENTNOTFOUND
;
5905 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5906 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5910 /* TypeInfo2::GetVarIndexOfMemId
5912 * Binds to a specific member based on a known DISPID, where the member name
5913 * is not known (for example, when binding to a default member).
5916 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5917 MEMBERID memid
, UINT
*pVarIndex
)
5919 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5920 TLBVarDesc
*pVarInfo
;
5923 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5924 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5930 result
= TYPE_E_ELEMENTNOTFOUND
;
5932 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5933 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5937 /* ITypeInfo2::GetCustData
5939 * Gets the custom data
5941 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5946 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5947 TLBCustData
*pCData
;
5949 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5950 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5952 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5956 VariantInit( pVarVal
);
5957 VariantCopy( pVarVal
, &pCData
->data
);
5960 return E_INVALIDARG
; /* FIXME: correct? */
5963 /* ITypeInfo2::GetFuncCustData
5965 * Gets the custom data
5967 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5973 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5974 TLBCustData
*pCData
=NULL
;
5975 TLBFuncDesc
* pFDesc
;
5977 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5978 pFDesc
=pFDesc
->next
);
5981 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5982 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5984 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5987 VariantInit( pVarVal
);
5988 VariantCopy( pVarVal
, &pCData
->data
);
5991 return E_INVALIDARG
; /* FIXME: correct? */
5994 /* ITypeInfo2::GetParamCustData
5996 * Gets the custom data
5998 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
6005 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6006 TLBCustData
*pCData
=NULL
;
6007 TLBFuncDesc
* pFDesc
;
6010 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
6012 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
6013 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
6014 pCData
= pCData
->next
)
6015 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6017 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6021 VariantInit( pVarVal
);
6022 VariantCopy( pVarVal
, &pCData
->data
);
6025 return E_INVALIDARG
; /* FIXME: correct? */
6028 /* ITypeInfo2::GetVarCustData
6030 * Gets the custom data
6032 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
6038 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6039 TLBCustData
*pCData
=NULL
;
6040 TLBVarDesc
* pVDesc
;
6043 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
6047 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6049 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6053 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6057 VariantInit( pVarVal
);
6058 VariantCopy( pVarVal
, &pCData
->data
);
6061 return E_INVALIDARG
; /* FIXME: correct? */
6064 /* ITypeInfo2::GetImplCustData
6066 * Gets the custom data
6068 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
6074 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6075 TLBCustData
*pCData
=NULL
;
6076 TLBImplType
* pRDesc
;
6079 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
6083 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
6085 if( IsEqualIID(guid
, &pCData
->guid
)) break;
6089 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
6093 VariantInit( pVarVal
);
6094 VariantCopy( pVarVal
, &pCData
->data
);
6097 return E_INVALIDARG
; /* FIXME: correct? */
6100 /* ITypeInfo2::GetDocumentation2
6102 * Retrieves the documentation string, the complete Help file name and path,
6103 * the localization context to use, and the context ID for the library Help
6104 * topic in the Help file.
6107 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
6111 BSTR
*pbstrHelpString
,
6112 DWORD
*pdwHelpStringContext
,
6113 BSTR
*pbstrHelpStringDll
)
6115 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6116 const TLBFuncDesc
*pFDesc
;
6117 const TLBVarDesc
*pVDesc
;
6118 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6119 "HelpStringContext(%p) HelpStringDll(%p)\n",
6120 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
6121 pbstrHelpStringDll
);
6122 /* the help string should be obtained from the helpstringdll,
6123 * using the _DLLGetDocumentation function, based on the supplied
6124 * lcid. Nice to do sometime...
6126 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6128 *pbstrHelpString
=SysAllocString(This
->Name
);
6129 if(pdwHelpStringContext
)
6130 *pdwHelpStringContext
=This
->dwHelpStringContext
;
6131 if(pbstrHelpStringDll
)
6132 *pbstrHelpStringDll
=
6133 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6135 }else {/* for a member */
6136 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
6137 if(pFDesc
->funcdesc
.memid
==memid
){
6139 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
6140 if(pdwHelpStringContext
)
6141 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
6142 if(pbstrHelpStringDll
)
6143 *pbstrHelpStringDll
=
6144 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6147 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
6148 if(pVDesc
->vardesc
.memid
==memid
){
6150 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
6151 if(pdwHelpStringContext
)
6152 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
6153 if(pbstrHelpStringDll
)
6154 *pbstrHelpStringDll
=
6155 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
6159 return TYPE_E_ELEMENTNOTFOUND
;
6162 /* ITypeInfo2::GetAllCustData
6164 * Gets all custom data items for the Type info.
6167 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
6169 CUSTDATA
*pCustData
)
6171 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6172 TLBCustData
*pCData
;
6175 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
6177 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
6178 if(pCustData
->prgCustData
){
6179 pCustData
->cCustData
=This
->ctCustData
;
6180 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
6181 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6182 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
6185 ERR(" OUT OF MEMORY!\n");
6186 return E_OUTOFMEMORY
;
6191 /* ITypeInfo2::GetAllFuncCustData
6193 * Gets all custom data items for the specified Function
6196 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
6199 CUSTDATA
*pCustData
)
6201 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6202 TLBCustData
*pCData
;
6203 TLBFuncDesc
* pFDesc
;
6205 TRACE("(%p) index %d\n", This
, index
);
6206 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
6207 pFDesc
=pFDesc
->next
)
6210 pCustData
->prgCustData
=
6211 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6212 if(pCustData
->prgCustData
){
6213 pCustData
->cCustData
=pFDesc
->ctCustData
;
6214 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
6215 pCData
= pCData
->next
){
6216 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6217 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6221 ERR(" OUT OF MEMORY!\n");
6222 return E_OUTOFMEMORY
;
6226 return TYPE_E_ELEMENTNOTFOUND
;
6229 /* ITypeInfo2::GetAllParamCustData
6231 * Gets all custom data items for the Functions
6234 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
6235 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
6237 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6238 TLBCustData
*pCData
=NULL
;
6239 TLBFuncDesc
* pFDesc
;
6241 TRACE("(%p) index %d\n", This
, indexFunc
);
6242 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
6243 pFDesc
=pFDesc
->next
)
6245 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
6246 pCustData
->prgCustData
=
6247 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
6248 sizeof(CUSTDATAITEM
));
6249 if(pCustData
->prgCustData
){
6250 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
6251 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
6252 pCData
; i
++, pCData
= pCData
->next
){
6253 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6254 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6258 ERR(" OUT OF MEMORY!\n");
6259 return E_OUTOFMEMORY
;
6263 return TYPE_E_ELEMENTNOTFOUND
;
6266 /* ITypeInfo2::GetAllVarCustData
6268 * Gets all custom data items for the specified Variable
6271 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
6272 UINT index
, CUSTDATA
*pCustData
)
6274 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6275 TLBCustData
*pCData
;
6276 TLBVarDesc
* pVDesc
;
6278 TRACE("(%p) index %d\n", This
, index
);
6279 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
6280 pVDesc
=pVDesc
->next
)
6283 pCustData
->prgCustData
=
6284 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6285 if(pCustData
->prgCustData
){
6286 pCustData
->cCustData
=pVDesc
->ctCustData
;
6287 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
6288 pCData
= pCData
->next
){
6289 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6290 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6294 ERR(" OUT OF MEMORY!\n");
6295 return E_OUTOFMEMORY
;
6299 return TYPE_E_ELEMENTNOTFOUND
;
6302 /* ITypeInfo2::GetAllImplCustData
6304 * Gets all custom data items for the specified implementation type
6307 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
6310 CUSTDATA
*pCustData
)
6312 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6313 TLBCustData
*pCData
;
6314 TLBImplType
* pRDesc
;
6316 TRACE("(%p) index %d\n", This
, index
);
6317 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
6318 pRDesc
=pRDesc
->next
)
6321 pCustData
->prgCustData
=
6322 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
6323 if(pCustData
->prgCustData
){
6324 pCustData
->cCustData
=pRDesc
->ctCustData
;
6325 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
6326 pCData
= pCData
->next
){
6327 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
6328 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
6332 ERR(" OUT OF MEMORY!\n");
6333 return E_OUTOFMEMORY
;
6337 return TYPE_E_ELEMENTNOTFOUND
;
6340 static const ITypeInfo2Vtbl tinfvt
=
6343 ITypeInfo_fnQueryInterface
,
6345 ITypeInfo_fnRelease
,
6347 ITypeInfo_fnGetTypeAttr
,
6348 ITypeInfo_fnGetTypeComp
,
6349 ITypeInfo_fnGetFuncDesc
,
6350 ITypeInfo_fnGetVarDesc
,
6351 ITypeInfo_fnGetNames
,
6352 ITypeInfo_fnGetRefTypeOfImplType
,
6353 ITypeInfo_fnGetImplTypeFlags
,
6354 ITypeInfo_fnGetIDsOfNames
,
6356 ITypeInfo_fnGetDocumentation
,
6357 ITypeInfo_fnGetDllEntry
,
6358 ITypeInfo_fnGetRefTypeInfo
,
6359 ITypeInfo_fnAddressOfMember
,
6360 ITypeInfo_fnCreateInstance
,
6361 ITypeInfo_fnGetMops
,
6362 ITypeInfo_fnGetContainingTypeLib
,
6363 ITypeInfo_fnReleaseTypeAttr
,
6364 ITypeInfo_fnReleaseFuncDesc
,
6365 ITypeInfo_fnReleaseVarDesc
,
6367 ITypeInfo2_fnGetTypeKind
,
6368 ITypeInfo2_fnGetTypeFlags
,
6369 ITypeInfo2_fnGetFuncIndexOfMemId
,
6370 ITypeInfo2_fnGetVarIndexOfMemId
,
6371 ITypeInfo2_fnGetCustData
,
6372 ITypeInfo2_fnGetFuncCustData
,
6373 ITypeInfo2_fnGetParamCustData
,
6374 ITypeInfo2_fnGetVarCustData
,
6375 ITypeInfo2_fnGetImplTypeCustData
,
6376 ITypeInfo2_fnGetDocumentation2
,
6377 ITypeInfo2_fnGetAllCustData
,
6378 ITypeInfo2_fnGetAllFuncCustData
,
6379 ITypeInfo2_fnGetAllParamCustData
,
6380 ITypeInfo2_fnGetAllVarCustData
,
6381 ITypeInfo2_fnGetAllImplTypeCustData
,
6384 /******************************************************************************
6385 * CreateDispTypeInfo [OLEAUT32.31]
6387 * Build type information for an object so it can be called through an
6388 * IDispatch interface.
6391 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6392 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6395 * This call allows an objects methods to be accessed through IDispatch, by
6396 * building an ITypeInfo object that IDispatch can use to call through.
6398 HRESULT WINAPI
CreateDispTypeInfo(
6399 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
6400 LCID lcid
, /* [I] Locale Id */
6401 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
6403 ITypeInfoImpl
*pTIClass
, *pTIIface
;
6404 ITypeLibImpl
*pTypeLibImpl
;
6406 TLBFuncDesc
**ppFuncDesc
;
6409 pTypeLibImpl
= TypeLibImpl_Constructor();
6410 if (!pTypeLibImpl
) return E_FAIL
;
6412 pTIIface
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
6413 pTIIface
->pTypeLib
= pTypeLibImpl
;
6414 pTIIface
->index
= 0;
6415 pTIIface
->Name
= NULL
;
6416 pTIIface
->dwHelpContext
= -1;
6417 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
6418 pTIIface
->TypeAttr
.lcid
= lcid
;
6419 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6420 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
6421 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
6422 pTIIface
->TypeAttr
.cbAlignment
= 2;
6423 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
6424 pTIIface
->TypeAttr
.cbSizeVft
= -1;
6425 pTIIface
->TypeAttr
.cFuncs
= 0;
6426 pTIIface
->TypeAttr
.cImplTypes
= 0;
6427 pTIIface
->TypeAttr
.cVars
= 0;
6428 pTIIface
->TypeAttr
.wTypeFlags
= 0;
6430 ppFuncDesc
= &pTIIface
->funclist
;
6431 for(func
= 0; func
< pidata
->cMembers
; func
++) {
6432 METHODDATA
*md
= pidata
->pmethdata
+ func
;
6433 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
6434 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
6435 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
6436 (*ppFuncDesc
)->funcdesc
.funckind
= FUNC_VIRTUAL
;
6437 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
6438 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
6439 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
6440 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
6441 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
<< 2;
6442 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0;
6443 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
6444 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
6445 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
6446 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6447 md
->cArgs
* sizeof(ELEMDESC
));
6448 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
6449 md
->cArgs
* sizeof(TLBParDesc
));
6450 for(param
= 0; param
< md
->cArgs
; param
++) {
6451 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
6452 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
6454 (*ppFuncDesc
)->helpcontext
= 0;
6455 (*ppFuncDesc
)->HelpStringContext
= 0;
6456 (*ppFuncDesc
)->HelpString
= NULL
;
6457 (*ppFuncDesc
)->Entry
= NULL
;
6458 (*ppFuncDesc
)->ctCustData
= 0;
6459 (*ppFuncDesc
)->pCustData
= NULL
;
6460 (*ppFuncDesc
)->next
= NULL
;
6461 ppFuncDesc
= &(*ppFuncDesc
)->next
;
6464 dump_TypeInfo(pTIIface
);
6466 pTypeLibImpl
->pTypeInfo
= pTIIface
;
6467 pTypeLibImpl
->TypeInfoCount
++;
6469 pTIClass
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
6470 pTIClass
->pTypeLib
= pTypeLibImpl
;
6471 pTIClass
->index
= 1;
6472 pTIClass
->Name
= NULL
;
6473 pTIClass
->dwHelpContext
= -1;
6474 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
6475 pTIClass
->TypeAttr
.lcid
= lcid
;
6476 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
6477 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
6478 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
6479 pTIClass
->TypeAttr
.cbAlignment
= 2;
6480 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
6481 pTIClass
->TypeAttr
.cbSizeVft
= -1;
6482 pTIClass
->TypeAttr
.cFuncs
= 0;
6483 pTIClass
->TypeAttr
.cImplTypes
= 1;
6484 pTIClass
->TypeAttr
.cVars
= 0;
6485 pTIClass
->TypeAttr
.wTypeFlags
= 0;
6487 pTIClass
->impltypelist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->impltypelist
));
6488 pTIClass
->impltypelist
->hRef
= 1;
6490 pTIClass
->reflist
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(*pTIClass
->reflist
));
6491 pTIClass
->reflist
->index
= 0;
6492 pTIClass
->reflist
->reference
= 1;
6493 pTIClass
->reflist
->pImpTLInfo
= TLB_REF_INTERNAL
;
6495 dump_TypeInfo(pTIClass
);
6497 pTIIface
->next
= pTIClass
;
6498 pTypeLibImpl
->TypeInfoCount
++;
6500 *pptinfo
= (ITypeInfo
*)pTIClass
;
6505 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
6507 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6509 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
6512 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
6514 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6516 return ITypeInfo_AddRef((ITypeInfo
*)This
);
6519 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
6521 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6523 return ITypeInfo_Release((ITypeInfo
*)This
);
6526 static HRESULT WINAPI
ITypeComp_fnBind(
6531 ITypeInfo
** ppTInfo
,
6532 DESCKIND
* pDescKind
,
6535 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6536 const TLBFuncDesc
*pFDesc
;
6537 const TLBVarDesc
*pVDesc
;
6539 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6541 *pDescKind
= DESCKIND_NONE
;
6542 pBindPtr
->lpfuncdesc
= NULL
;
6545 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
6546 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
6547 if (!strcmpW(pFDesc
->Name
, szName
)) {
6553 HRESULT hr
= TLB_AllocAndInitFuncDesc(
6555 &pBindPtr
->lpfuncdesc
,
6556 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
6559 *pDescKind
= DESCKIND_FUNCDESC
;
6560 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6561 ITypeInfo_AddRef(*ppTInfo
);
6564 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
6565 if (!strcmpW(pVDesc
->Name
, szName
)) {
6566 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
6569 *pDescKind
= DESCKIND_VARDESC
;
6570 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6571 ITypeInfo_AddRef(*ppTInfo
);
6576 /* FIXME: search each inherited interface, not just the first */
6577 if (This
->TypeAttr
.cImplTypes
) {
6578 /* recursive search */
6582 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
6585 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
6586 ITypeInfo_Release(pTInfo
);
6590 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6591 ITypeComp_Release(pTComp
);
6594 WARN("Could not search inherited interface!\n");
6596 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
6597 return DISP_E_MEMBERNOTFOUND
;
6600 static HRESULT WINAPI
ITypeComp_fnBindType(
6604 ITypeInfo
** ppTInfo
,
6605 ITypeComp
** ppTComp
)
6607 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
6609 /* strange behaviour (does nothing) but like the
6612 if (!ppTInfo
|| !ppTComp
)
6621 static const ITypeCompVtbl tcompvt
=
6624 ITypeComp_fnQueryInterface
,
6626 ITypeComp_fnRelease
,
6629 ITypeComp_fnBindType