4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
65 #define NONAMELESSUNION
66 #define NONAMELESSSTRUCT
75 #include "wine/unicode.h"
78 #include "wine/debug.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface
= { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, TYPEDESC
*tdesc
, VARTYPE
*vt
);
89 /****************************************************************************
92 * Takes p_iVal (which is in little endian) and returns it
93 * in the host machine's byte order.
95 #ifdef WORDS_BIGENDIAN
96 static WORD
FromLEWord(WORD p_iVal
)
98 return (((p_iVal
& 0x00FF) << 8) |
99 ((p_iVal
& 0xFF00) >> 8));
103 static DWORD
FromLEDWord(DWORD p_iVal
)
105 return (((p_iVal
& 0x000000FF) << 24) |
106 ((p_iVal
& 0x0000FF00) << 8) |
107 ((p_iVal
& 0x00FF0000) >> 8) |
108 ((p_iVal
& 0xFF000000) >> 24));
111 #define FromLEWord(X) (X)
112 #define FromLEDWord(X) (X)
116 /****************************************************************************
119 * Fix byte order in any structure if necessary
121 #ifdef WORDS_BIGENDIAN
122 static void FromLEWords(void *p_Val
, int p_iSize
)
126 p_iSize
/= sizeof(WORD
);
129 *Val
= FromLEWord(*Val
);
136 static void FromLEDWords(void *p_Val
, int p_iSize
)
140 p_iSize
/= sizeof(DWORD
);
143 *Val
= FromLEDWord(*Val
);
149 #define FromLEWords(X,Y) /*nothing*/
150 #define FromLEDWords(X,Y) /*nothing*/
153 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
154 /* buffer must be at least 60 characters long */
155 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
157 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
158 static const WCHAR VersionFormatW
[] = {'\\','%','u','.','%','u',0};
160 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
161 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
162 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
166 /* get the path of an interface key, in the form "Interface\\<guid>" */
167 /* buffer must be at least 50 characters long */
168 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
170 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
172 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
173 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
177 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
178 /* buffer must be at least 16 characters long */
179 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
181 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
182 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
183 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
185 sprintfW( buffer
, LcidFormatW
, lcid
);
188 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
189 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
191 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
197 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
200 /****************************************************************************
201 * QueryPathOfRegTypeLib [OLEAUT32.164]
203 * Gets the path to a registered type library.
206 * guid [I] referenced guid
207 * wMaj [I] major version
208 * wMin [I] minor version
210 * path [O] path of typelib
214 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
215 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
218 HRESULT WINAPI
QueryPathOfRegTypeLib(
225 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
229 WCHAR Path
[MAX_PATH
];
232 TRACE_(typelib
)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
234 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
236 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
237 if (res
== ERROR_FILE_NOT_FOUND
)
239 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
240 return TYPE_E_LIBNOTREGISTERED
;
242 else if (res
!= ERROR_SUCCESS
)
244 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
245 return TYPE_E_REGISTRYACCESS
;
250 LONG dwPathLen
= sizeof(Path
);
252 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
254 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
258 else if (myLCID
== lcid
)
260 /* try with sub-langid */
261 myLCID
= SUBLANGID(lcid
);
263 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
265 /* try with system langid */
275 *path
= SysAllocString( Path
);
280 TRACE_(typelib
)("-- 0x%08lx\n", hr
);
284 /******************************************************************************
285 * CreateTypeLib [OLEAUT32.160] creates a typelib
291 HRESULT WINAPI
CreateTypeLib(
292 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
294 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
298 /******************************************************************************
299 * LoadTypeLib [OLEAUT32.161]
301 * Loads a type library
304 * szFile [I] Name of file to load from.
305 * pptLib [O] Pointer that receives ITypeLib object on success.
312 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
314 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
316 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
317 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
320 /******************************************************************************
321 * LoadTypeLibEx [OLEAUT32.183]
323 * Loads and optionally registers a type library
329 HRESULT WINAPI
LoadTypeLibEx(
330 LPCOLESTR szFile
, /* [in] Name of file to load from */
331 REGKIND regkind
, /* [in] Specify kind of registration */
332 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
334 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
339 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
341 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
342 memcpy(szPath
, szFile
, (strlenW(szFile
)+1)*sizeof(WCHAR
));
345 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
348 /* Look for a trailing '\\' followed by an index */
349 pIndexStr
= strrchrW(szFile
, '\\');
350 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
351 index
= atoiW(pIndexStr
);
352 memcpy(szFileCopy
, szFile
,
353 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
354 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
355 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
357 return TYPE_E_CANTLOADLIBRARY
;
358 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
359 return TYPE_E_CANTLOADLIBRARY
;
363 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
365 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
370 case REGKIND_DEFAULT
:
371 /* don't register typelibs supplied with full path. Experimentation confirms the following */
373 ((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
374 (szFile
[0] && (szFile
[1] == ':'))) break;
375 /* else fall-through */
377 case REGKIND_REGISTER
:
378 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
380 IUnknown_Release(*pptLib
);
388 TRACE(" returns %08lx\n",res
);
392 /******************************************************************************
393 * LoadRegTypeLib [OLEAUT32.162]
395 * Loads a registered type library.
398 * rguid [I] GUID of the registered type library.
399 * wVerMajor [I] major version.
400 * wVerMinor [I] minor version.
401 * lcid [I] locale ID.
402 * ppTLib [O] pointer that receives an ITypeLib object on success.
406 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
409 HRESULT WINAPI
LoadRegTypeLib(
417 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
421 res
= LoadTypeLib(bstr
, ppTLib
);
425 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
431 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
432 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
433 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
434 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
435 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
436 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
438 /******************************************************************************
439 * RegisterTypeLib [OLEAUT32.163]
440 * Adds information about a type library to the System Registry
442 * Docs: ITypeLib FAR * ptlib
443 * Docs: OLECHAR FAR* szFullPath
444 * Docs: OLECHAR FAR* szHelpDir
450 HRESULT WINAPI
RegisterTypeLib(
451 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
452 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
453 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
456 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
457 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
458 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
468 if (ptlib
== NULL
|| szFullPath
== NULL
)
471 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
474 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
477 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
478 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
482 /* Set the human-readable name of the typelib */
483 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
485 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
486 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
494 /* Make up the name of the typelib path subkey */
495 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
497 /* Create the typelib path subkey */
498 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
499 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
501 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
502 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
510 /* Create the flags subkey */
511 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
512 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
514 /* FIXME: is %u correct? */
515 static const WCHAR formatW
[] = {'%','u',0};
517 sprintfW(buf
, formatW
, attr
->wLibFlags
);
518 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
519 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
527 /* create the helpdir subkey */
528 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
529 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
531 BOOL freeHelpDir
= FALSE
;
534 /* if we created a new key, and helpDir was null, set the helpdir
535 to the directory which contains the typelib. However,
536 if we just opened an existing key, we leave the helpdir alone */
537 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
538 szHelpDir
= SysAllocString(szFullPath
);
539 pIndexStr
= strrchrW(szHelpDir
, '\\');
546 /* if we have an szHelpDir, set it! */
547 if (szHelpDir
!= NULL
) {
548 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
549 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
555 if (freeHelpDir
) SysFreeString(szHelpDir
);
567 /* register OLE Automation-compatible interfaces for this typelib */
568 types
= ITypeLib_GetTypeInfoCount(ptlib
);
569 for (tidx
=0; tidx
<types
; tidx
++) {
570 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
571 LPOLESTR name
= NULL
;
572 ITypeInfo
*tinfo
= NULL
;
574 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
577 case TKIND_INTERFACE
:
578 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
579 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
583 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
584 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
588 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
593 TYPEATTR
*tattr
= NULL
;
594 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
597 TRACE_(typelib
)("guid=%s, flags=%04x (",
598 debugstr_guid(&tattr
->guid
),
601 if (TRACE_ON(typelib
)) {
602 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
622 if (tattr
->wTypeFlags
& (TYPEFLAG_FOLEAUTOMATION
|TYPEFLAG_FDUAL
))
624 /* register interface<->typelib coupling */
625 get_interface_key( &tattr
->guid
, keyName
);
626 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
627 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
630 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
631 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
633 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
634 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
635 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
636 (BYTE
*)PSOA
, sizeof PSOA
);
640 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
641 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
642 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
643 (BYTE
*)PSOA
, sizeof PSOA
);
647 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
648 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
651 static const WCHAR fmtver
[] = {'%','u','.','%','u',0 };
652 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
654 StringFromGUID2(&attr
->guid
, buffer
, 40);
655 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
656 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
657 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
658 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
659 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
667 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
670 ITypeInfo_Release(tinfo
);
677 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
683 /******************************************************************************
684 * UnRegisterTypeLib [OLEAUT32.186]
685 * Removes information about a type library from the System Registry
692 HRESULT WINAPI
UnRegisterTypeLib(
693 REFGUID libid
, /* [in] Guid of the library */
694 WORD wVerMajor
, /* [in] major version */
695 WORD wVerMinor
, /* [in] minor version */
696 LCID lcid
, /* [in] locale id */
699 BSTR tlibPath
= NULL
;
702 WCHAR subKeyName
[50];
705 BOOL deleteOtherStuff
;
708 TYPEATTR
* typeAttr
= NULL
;
710 ITypeInfo
* typeInfo
= NULL
;
711 ITypeLib
* typeLib
= NULL
;
714 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
716 /* Create the path to the key */
717 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
719 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
721 TRACE("Unsupported syskind %i\n", syskind
);
722 result
= E_INVALIDARG
;
726 /* get the path to the typelib on disk */
727 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
728 result
= E_INVALIDARG
;
732 /* Try and open the key to the type library. */
733 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != S_OK
) {
734 result
= E_INVALIDARG
;
738 /* Try and load the type library */
739 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
740 result
= TYPE_E_INVALIDSTATE
;
744 /* remove any types registered with this typelib */
745 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
746 for (i
=0; i
<numTypes
; i
++) {
747 /* get the kind of type */
748 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
752 /* skip non-interfaces, and get type info for the type */
753 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
756 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
759 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
763 /* the path to the type */
764 get_interface_key( &typeAttr
->guid
, subKeyName
);
766 /* Delete its bits */
767 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != S_OK
) {
770 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
771 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
772 RegDeleteKeyW(subKey
, TypeLibW
);
775 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
778 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
780 if (typeInfo
) ITypeInfo_Release(typeInfo
);
784 /* Now, delete the type library path subkey */
785 get_lcid_subkey( lcid
, syskind
, subKeyName
);
786 RegDeleteKeyW(key
, subKeyName
);
787 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
788 RegDeleteKeyW(key
, subKeyName
);
790 /* check if there is anything besides the FLAGS/HELPDIR keys.
791 If there is, we don't delete them */
792 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
793 deleteOtherStuff
= TRUE
;
795 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == S_OK
) {
796 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
798 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
799 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
800 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
801 deleteOtherStuff
= FALSE
;
805 /* only delete the other parts of the key if we're absolutely sure */
806 if (deleteOtherStuff
) {
807 RegDeleteKeyW(key
, FLAGSW
);
808 RegDeleteKeyW(key
, HELPDIRW
);
812 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
813 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
814 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
818 if (tlibPath
) SysFreeString(tlibPath
);
819 if (typeLib
) ITypeLib_Release(typeLib
);
820 if (subKey
) RegCloseKey(subKey
);
821 if (key
) RegCloseKey(key
);
825 /*======================= ITypeLib implementation =======================*/
827 typedef struct tagTLBCustData
831 struct tagTLBCustData
* next
;
834 /* data structure for import typelibs */
835 typedef struct tagTLBImpLib
837 int offset
; /* offset in the file (MSFT)
838 offset in nametable (SLTG)
839 just used to identify library while reading
841 GUID guid
; /* libid */
842 BSTR name
; /* name */
844 LCID lcid
; /* lcid of imported typelib */
846 WORD wVersionMajor
; /* major version number */
847 WORD wVersionMinor
; /* minor version number */
849 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
850 NULL if not yet loaded */
851 struct tagTLBImpLib
* next
;
854 /* internal ITypeLib data */
855 typedef struct tagITypeLibImpl
857 const ITypeLib2Vtbl
*lpVtbl
;
858 const ITypeCompVtbl
*lpVtblTypeComp
;
860 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
862 /* strings can be stored in tlb as multibyte strings BUT they are *always*
863 * exported to the application as a UNICODE string.
869 unsigned long dwHelpContext
;
870 int TypeInfoCount
; /* nr of typeinfo's in librarry */
871 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
872 int ctCustData
; /* number of items in cust data list */
873 TLBCustData
* pCustData
; /* linked list to cust data */
874 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
875 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
876 libary. Only used while read MSFT
879 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
880 struct tagITypeLibImpl
*next
, *prev
;
885 static const ITypeLib2Vtbl tlbvt
;
886 static const ITypeCompVtbl tlbtcvt
;
888 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
890 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
893 /* ITypeLib methods */
894 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
895 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
897 /*======================= ITypeInfo implementation =======================*/
899 /* data for referenced types */
900 typedef struct tagTLBRefType
902 INT index
; /* Type index for internal ref or for external ref
903 it the format is SLTG. -2 indicates to
906 GUID guid
; /* guid of the referenced type */
907 /* if index == TLB_REF_USE_GUID */
909 HREFTYPE reference
; /* The href of this ref */
910 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
911 TLB_REF_INTERNAL for internal refs
912 TLB_REF_NOT_FOUND for broken refs */
914 struct tagTLBRefType
* next
;
917 #define TLB_REF_USE_GUID -2
919 #define TLB_REF_INTERNAL (void*)-2
920 #define TLB_REF_NOT_FOUND (void*)-1
922 /* internal Parameter data */
923 typedef struct tagTLBParDesc
927 TLBCustData
* pCustData
; /* linked list to cust data */
930 /* internal Function data */
931 typedef struct tagTLBFuncDesc
933 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
934 BSTR Name
; /* the name of this function */
935 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
937 int HelpStringContext
;
939 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
941 TLBCustData
* pCustData
; /* linked list to cust data; */
942 struct tagTLBFuncDesc
* next
;
945 /* internal Variable data */
946 typedef struct tagTLBVarDesc
948 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
949 BSTR Name
; /* the name of this variable */
951 int HelpStringContext
; /* FIXME: where? */
954 TLBCustData
* pCustData
;/* linked list to cust data; */
955 struct tagTLBVarDesc
* next
;
958 /* internal implemented interface data */
959 typedef struct tagTLBImplType
961 HREFTYPE hRef
; /* hRef of interface */
962 int implflags
; /* IMPLFLAG_*s */
964 TLBCustData
* pCustData
;/* linked list to custom data; */
965 struct tagTLBImplType
*next
;
968 /* internal TypeInfo data */
969 typedef struct tagITypeInfoImpl
971 const ITypeInfo2Vtbl
*lpVtbl
;
972 const ITypeCompVtbl
*lpVtblTypeComp
;
974 TYPEATTR TypeAttr
; /* _lots_ of type information. */
975 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
976 int index
; /* index in this typelib; */
977 /* type libs seem to store the doc strings in ascii
978 * so why should we do it in unicode?
982 unsigned long dwHelpContext
;
983 unsigned long dwHelpStringContext
;
986 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
989 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
991 /* Implemented Interfaces */
992 TLBImplType
* impltypelist
;
994 TLBRefType
* reflist
;
996 TLBCustData
* pCustData
; /* linked list to cust data; */
997 struct tagITypeInfoImpl
* next
;
1000 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1002 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1005 static const ITypeInfo2Vtbl tinfvt
;
1006 static const ITypeCompVtbl tcompvt
;
1008 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
1010 typedef struct tagTLBContext
1012 unsigned int oStart
; /* start of TLB in file */
1013 unsigned int pos
; /* current pos */
1014 unsigned int length
; /* total length */
1015 void *mapping
; /* memory mapping */
1016 MSFT_SegDir
* pTblDir
;
1017 ITypeLibImpl
* pLibInfo
;
1021 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
1026 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
1027 if (pTD
->vt
& VT_RESERVED
)
1028 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1029 if (pTD
->vt
& VT_BYREF
)
1030 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1031 if (pTD
->vt
& VT_ARRAY
)
1032 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1033 if (pTD
->vt
& VT_VECTOR
)
1034 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1035 switch(pTD
->vt
& VT_TYPEMASK
) {
1036 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1037 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1038 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1039 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1040 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1041 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1042 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1043 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1044 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1045 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1046 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1047 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1048 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1049 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1050 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1051 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1052 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1053 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1054 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1055 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1056 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
1057 pTD
->u
.hreftype
); break;
1058 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1059 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1061 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1062 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1064 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1065 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1066 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1069 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1073 static void dump_ELEMDESC(ELEMDESC
*edesc
) {
1075 dump_TypeDesc(&edesc
->tdesc
,buf
);
1076 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1077 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
1078 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1080 static void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
1082 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
1083 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1084 MESSAGE("Param %d:\n",i
);
1085 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1087 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1088 switch (funcdesc
->funckind
) {
1089 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1090 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1091 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1092 case FUNC_STATIC
: MESSAGE("static");break;
1093 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1094 default: MESSAGE("unknown");break;
1096 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1097 switch (funcdesc
->invkind
) {
1098 case INVOKE_FUNC
: MESSAGE("func");break;
1099 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1100 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1101 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1103 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1104 switch (funcdesc
->callconv
) {
1105 case CC_CDECL
: MESSAGE("cdecl");break;
1106 case CC_PASCAL
: MESSAGE("pascal");break;
1107 case CC_STDCALL
: MESSAGE("stdcall");break;
1108 case CC_SYSCALL
: MESSAGE("syscall");break;
1111 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1112 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1113 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1115 MESSAGE("\telemdescFunc (return value type):\n");
1116 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1119 static const char * typekind_desc
[] =
1132 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
1135 if (!TRACE_ON(typelib
))
1137 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1138 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1139 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1142 dump_FUNCDESC(&(pfd
->funcdesc
));
1144 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1145 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1147 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
1151 dump_TLBFuncDescOne(pfd
);
1155 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
1159 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1164 static void dump_TLBImpLib(TLBImpLib
*import
)
1166 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1167 debugstr_w(import
->name
));
1168 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1169 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1172 static void dump_TLBRefType(TLBRefType
* prt
)
1176 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1177 if(prt
->index
== -1)
1178 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1180 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1182 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1183 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1184 TRACE_(typelib
)("in lib\n");
1185 dump_TLBImpLib(prt
->pImpTLInfo
);
1191 static void dump_TLBImplType(TLBImplType
* impl
)
1195 "implementing/inheriting interface hRef = %lx implflags %x\n",
1196 impl
->hRef
, impl
->implflags
);
1201 void dump_Variant(VARIANT
* pvar
)
1205 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1209 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1210 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1212 TRACE(",%p", V_BYREF(pvar
));
1214 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1218 else switch (V_TYPE(pvar
))
1220 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1221 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1222 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1223 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1225 case VT_I4
: TRACE(",%ld", V_I4(pvar
)); break;
1227 case VT_UI4
: TRACE(",%ld", V_UI4(pvar
)); break;
1228 case VT_I8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_I8(pvar
) >> 32),
1229 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1230 case VT_UI8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_UI8(pvar
) >> 32),
1231 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1232 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1233 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1234 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1235 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1236 case VT_CY
: TRACE(",0x%08lx,0x%08lx", V_CY(pvar
).s
.Hi
,
1237 V_CY(pvar
).s
.Lo
); break;
1239 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1240 TRACE(",<invalid>");
1242 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1243 st
.wHour
, st
.wMinute
, st
.wSecond
);
1247 case VT_USERDEFINED
:
1249 case VT_NULL
: break;
1250 default: TRACE(",?"); break;
1256 static void dump_DispParms(DISPPARAMS
* pdp
)
1260 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1262 while (index
< pdp
->cArgs
)
1264 dump_Variant( &pdp
->rgvarg
[index
] );
1269 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1271 TRACE("%p ref=%lu\n", pty
, pty
->ref
);
1272 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1273 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1274 TRACE("fct:%u var:%u impl:%u\n",
1275 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1276 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1277 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1278 dump_TLBFuncDesc(pty
->funclist
);
1279 dump_TLBVarDesc(pty
->varlist
);
1280 dump_TLBImplType(pty
->impltypelist
);
1283 static void dump_VARDESC(VARDESC
*v
)
1285 MESSAGE("memid %ld\n",v
->memid
);
1286 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1287 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1288 dump_ELEMDESC(&(v
->elemdescVar
));
1289 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1290 MESSAGE("varkind %d\n",v
->varkind
);
1293 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1295 /* VT_LPWSTR is largest type that */
1296 /* may appear in type description*/
1297 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1298 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1299 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1300 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1301 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1302 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1306 static void TLB_abort(void)
1310 static void * TLB_Alloc(unsigned size
)
1313 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1315 ERR("cannot allocate memory\n");
1320 static void TLB_Free(void * ptr
)
1322 HeapFree(GetProcessHeap(), 0, ptr
);
1325 /* deep copy a typedesc */
1326 static void copy_typedesc(TYPEDESC
*out
, const TYPEDESC
*in
)
1331 out
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC
));
1332 copy_typedesc(out
->u
.lptdesc
, in
->u
.lptdesc
);
1334 case VT_USERDEFINED
:
1335 out
->u
.hreftype
= in
->u
.hreftype
;
1338 out
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC
) +
1339 (in
->u
.lpadesc
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
1340 copy_typedesc(&out
->u
.lpadesc
->tdescElem
, &in
->u
.lpadesc
->tdescElem
);
1341 out
->u
.lpadesc
->cDims
= in
->u
.lpadesc
->cDims
;
1342 memcpy(out
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->cDims
* sizeof(SAFEARRAYBOUND
));
1349 /* free()s any allocated memory pointed to by the tdesc. NB does not
1350 free the tdesc itself - this is because the tdesc is typically part
1351 of a larger structure */
1352 static void free_deep_typedesc(TYPEDESC
*tdesc
)
1356 free_deep_typedesc(tdesc
->u
.lptdesc
);
1357 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lptdesc
);
1358 tdesc
->u
.lptdesc
= NULL
;
1361 free_deep_typedesc(&tdesc
->u
.lpadesc
->tdescElem
);
1362 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lpadesc
);
1363 tdesc
->u
.lpadesc
= NULL
;
1370 /**********************************************************************
1372 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1375 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1377 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1378 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1380 if (where
!= DO_NOT_SEEK
)
1382 where
+= pcx
->oStart
;
1383 if (where
> pcx
->length
)
1386 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1391 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1392 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1397 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1402 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1403 FromLEDWords(buffer
, ret
);
1408 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1413 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1414 FromLEWords(buffer
, ret
);
1419 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1421 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1422 memset(pGuid
,0, sizeof(GUID
));
1425 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1426 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1427 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1428 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1429 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1432 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1435 MSFT_NameIntro niName
;
1437 WCHAR
* pwstring
= NULL
;
1438 BSTR bstrName
= NULL
;
1440 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1441 pcx
->pTblDir
->pNametab
.offset
+offset
);
1442 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1443 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1444 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1445 name
[niName
.namelen
& 0xff]='\0';
1447 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1450 /* no invalid characters in string */
1453 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1455 /* don't check for invalid character since this has been done previously */
1456 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1458 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1459 lengthInChars
= SysStringLen(bstrName
);
1460 HeapFree(GetProcessHeap(), 0, pwstring
);
1463 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1467 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1474 if(offset
<0) return NULL
;
1475 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1476 if(length
<= 0) return 0;
1477 string
=TLB_Alloc(length
+1);
1478 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1479 string
[length
]='\0';
1481 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1482 string
, -1, NULL
, 0);
1484 /* no invalid characters in string */
1487 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1489 /* don't check for invalid character since this has been done previously */
1490 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1492 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1493 lengthInChars
= SysStringLen(bstr
);
1494 HeapFree(GetProcessHeap(), 0, pwstring
);
1497 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1501 * read a value and fill a VARIANT structure
1503 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1507 TRACE_(typelib
)("\n");
1509 if(offset
<0) { /* data are packed in here */
1510 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1511 V_I2(pVar
) = offset
& 0x3ffffff;
1514 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1515 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1516 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1517 switch (V_VT(pVar
)){
1518 case VT_EMPTY
: /* FIXME: is this right? */
1519 case VT_NULL
: /* FIXME: is this right? */
1520 case VT_I2
: /* this should not happen */
1531 case VT_VOID
: /* FIXME: is this right? */
1539 case VT_DECIMAL
: /* FIXME: is this right? */
1542 /* pointer types with known behaviour */
1545 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1547 FIXME("BSTR length = %d?\n", size
);
1549 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1550 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1551 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1552 /* FIXME: do we need a AtoW conversion here? */
1553 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1554 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1559 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1566 case VT_USERDEFINED
:
1572 case VT_STREAMED_OBJECT
:
1573 case VT_STORED_OBJECT
:
1574 case VT_BLOB_OBJECT
:
1579 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1583 if(size
>0) /* (big|small) endian correct? */
1584 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1588 * create a linked list with custom data
1590 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1596 TRACE_(typelib
)("\n");
1600 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1601 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1602 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1603 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1604 /* add new custom data at head of the list */
1605 pNew
->next
=*ppCustData
;
1607 offset
= entry
.next
;
1612 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1616 pTd
->vt
=type
& VT_TYPEMASK
;
1618 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1620 if(pTd
->vt
== VT_USERDEFINED
)
1621 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1623 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1627 MSFT_DoFuncs(TLBContext
* pcx
,
1632 TLBFuncDesc
** pptfd
)
1635 * member information is stored in a data structure at offset
1636 * indicated by the memoffset field of the typeinfo structure
1637 * There are several distinctive parts.
1638 * The first part starts with a field that holds the total length
1639 * of this (first) part excluding this field. Then follow the records,
1640 * for each member there is one record.
1642 * The first entry is always the length of the record (including this
1644 * The rest of the record depends on the type of the member. If there is
1645 * a field indicating the member type (function, variable, interface, etc)
1646 * I have not found it yet. At this time we depend on the information
1647 * in the type info and the usual order how things are stored.
1649 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1652 * Third is an equal sized array with file offsets to the name entry
1655 * The fourth and last (?) part is an array with offsets to the records
1656 * in the first part of this file segment.
1659 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1660 int recoffset
= offset
+ sizeof(INT
);
1663 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1665 TRACE_(typelib
)("\n");
1667 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1669 for ( i
= 0; i
< cFuncs
; i
++ )
1671 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1673 /* name, eventually add to a hash table */
1674 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1675 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1677 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1679 /* read the function information record */
1680 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1684 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1686 /* do the attributes */
1687 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1690 if ( nrattributes
> 0 )
1692 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1694 if ( nrattributes
> 1 )
1696 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1697 pFuncRec
->OptAttr
[1]) ;
1699 if ( nrattributes
> 2 )
1701 if ( pFuncRec
->FKCCIC
& 0x2000 )
1703 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1707 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1708 pFuncRec
->OptAttr
[2]);
1710 if( nrattributes
> 5 )
1712 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1714 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1717 pFuncRec
->OptAttr
[6],
1718 &(*pptfd
)->pCustData
);
1725 /* fill the FuncDesc Structure */
1726 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1727 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1729 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1730 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1731 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1732 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1733 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1734 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1735 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1739 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1742 /* do the parameters/arguments */
1743 if(pFuncRec
->nrargs
)
1746 MSFT_ParameterInfo paraminfo
;
1748 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1749 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1751 (*pptfd
)->pParamDesc
=
1752 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1754 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1755 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1757 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1759 TYPEDESC
* lpArgTypeDesc
= 0;
1763 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1766 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1768 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1770 /* SEEK value = jump to offset,
1771 * from there jump to the end of record,
1772 * go back by (j-1) arguments
1774 MSFT_ReadLEDWords( ¶minfo
,
1775 sizeof(MSFT_ParameterInfo
), pcx
,
1776 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1777 * sizeof(MSFT_ParameterInfo
)));
1779 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1781 while ( lpArgTypeDesc
!= NULL
)
1783 switch ( lpArgTypeDesc
->vt
)
1786 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1790 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1793 case VT_USERDEFINED
:
1794 MSFT_DoRefType(pcx
, pTI
,
1795 lpArgTypeDesc
->u
.hreftype
);
1797 lpArgTypeDesc
= NULL
;
1801 lpArgTypeDesc
= NULL
;
1807 /* parameter is the return value! */
1808 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1810 TYPEDESC
* lpArgTypeDesc
;
1812 (*pptfd
)->funcdesc
.elemdescFunc
=
1813 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1815 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1817 while ( lpArgTypeDesc
!= NULL
)
1819 switch ( lpArgTypeDesc
->vt
)
1822 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1826 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1830 case VT_USERDEFINED
:
1833 lpArgTypeDesc
->u
.hreftype
);
1835 lpArgTypeDesc
= NULL
;
1839 lpArgTypeDesc
= NULL
;
1844 /* second time around */
1845 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1848 (*pptfd
)->pParamDesc
[j
].Name
=
1849 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1852 if ( (PARAMFLAG_FHASDEFAULT
&
1853 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1854 ((pFuncRec
->FKCCIC
) & 0x1000) )
1856 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1858 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1860 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1862 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1863 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1865 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1869 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1872 pFuncRec
->OptAttr
[7+j
],
1873 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1878 /* scode is not used: archaic win16 stuff FIXME: right? */
1879 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1880 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1882 pptfd
= & ((*pptfd
)->next
);
1883 recoffset
+= reclength
;
1887 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1888 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1890 int infolen
, nameoffset
, reclength
;
1892 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1896 TRACE_(typelib
)("\n");
1898 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1899 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1900 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1901 recoffset
+= offset
+sizeof(INT
);
1902 for(i
=0;i
<cVars
;i
++){
1903 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1904 /* name, eventually add to a hash table */
1905 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1906 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1907 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1908 /* read the variable information record */
1909 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1911 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1913 if(reclength
>(6*sizeof(INT
)) )
1914 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1915 if(reclength
>(7*sizeof(INT
)) )
1916 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1917 if(reclength
>(8*sizeof(INT
)) )
1918 if(reclength
>(9*sizeof(INT
)) )
1919 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1920 /* fill the VarDesc Structure */
1921 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1922 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1923 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1924 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1925 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1926 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1927 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1928 if(pVarRec
->VarKind
== VAR_CONST
){
1929 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1930 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1931 pVarRec
->OffsValue
, pcx
);
1933 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1934 pptvd
=&((*pptvd
)->next
);
1935 recoffset
+= reclength
;
1938 /* fill in data for a hreftype (offset). When the referenced type is contained
1939 * in the typelib, it's just an (file) offset in the type info base dir.
1940 * If comes from import, it's an offset+1 in the ImpInfo table
1942 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1946 TLBRefType
**ppRefType
= &pTI
->reflist
;
1948 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1951 if((*ppRefType
)->reference
== offset
)
1953 ppRefType
= &(*ppRefType
)->next
;
1956 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1957 sizeof(**ppRefType
));
1959 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1960 /* external typelib */
1961 MSFT_ImpInfo impinfo
;
1962 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1964 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1966 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1967 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1968 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1969 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1970 pImpLib
=pImpLib
->next
;
1973 (*ppRefType
)->reference
=offset
;
1974 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1975 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
1976 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1977 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1979 (*ppRefType
)->index
= impinfo
.oGuid
;
1981 ERR("Cannot find a reference\n");
1982 (*ppRefType
)->reference
=-1;
1983 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1986 /* in this typelib */
1987 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1988 (*ppRefType
)->reference
=offset
;
1989 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1993 /* process Implemented Interfaces of a com class */
1994 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1998 MSFT_RefRecord refrec
;
1999 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2001 TRACE_(typelib
)("\n");
2003 for(i
=0;i
<count
;i
++){
2004 if(offset
<0) break; /* paranoia */
2005 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2006 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2007 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
2008 (*ppImpl
)->hRef
= refrec
.reftype
;
2009 (*ppImpl
)->implflags
=refrec
.flags
;
2010 (*ppImpl
)->ctCustData
=
2011 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2012 offset
=refrec
.onext
;
2013 ppImpl
=&((*ppImpl
)->next
);
2017 * process a typeinfo record
2019 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2022 ITypeLibImpl
* pLibInfo
)
2024 MSFT_TypeInfoBase tiBase
;
2025 ITypeInfoImpl
*ptiRet
;
2027 TRACE_(typelib
)("count=%u\n", count
);
2029 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2030 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2031 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2032 /* this is where we are coming from */
2033 ptiRet
->pTypeLib
= pLibInfo
;
2034 ptiRet
->index
=count
;
2035 /* fill in the typeattr fields */
2036 WARN("Assign constructor/destructor memid\n");
2038 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2039 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2040 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
2041 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
2042 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2043 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2044 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2045 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2046 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2047 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2048 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2049 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2050 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2051 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2052 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2053 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2054 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2055 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2058 /* IDLDESC idldescType; *//* never saw this one != zero */
2060 /* name, eventually add to a hash table */
2061 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2062 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2064 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2065 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2066 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2067 /* note: InfoType's Help file and HelpStringDll come from the containing
2068 * library. Further HelpString and Docstring appear to be the same thing :(
2071 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2072 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2073 ptiRet
->TypeAttr
.cVars
,
2074 tiBase
.memoffset
, & ptiRet
->funclist
);
2076 if(ptiRet
->TypeAttr
.cVars
>0 )
2077 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2078 ptiRet
->TypeAttr
.cVars
,
2079 tiBase
.memoffset
, & ptiRet
->varlist
);
2080 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2081 switch(ptiRet
->TypeAttr
.typekind
)
2084 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2087 case TKIND_DISPATCH
:
2088 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2090 if (tiBase
.datatype1
!= -1)
2092 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2093 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2096 { /* FIXME: This is a really bad hack to add IDispatch */
2097 const char* szStdOle
= "stdole2.tlb\0";
2098 int nStdOleLen
= strlen(szStdOle
);
2099 TLBRefType
**ppRef
= &ptiRet
->reflist
;
2102 if((*ppRef
)->reference
== -1)
2104 ppRef
= &(*ppRef
)->next
;
2107 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
2108 (*ppRef
)->guid
= IID_IDispatch
;
2109 (*ppRef
)->reference
= -1;
2110 (*ppRef
)->index
= TLB_REF_USE_GUID
;
2111 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
2112 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
2113 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
2116 MultiByteToWideChar(CP_ACP
,
2120 (*ppRef
)->pImpTLInfo
->name
,
2121 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
2123 (*ppRef
)->pImpTLInfo
->lcid
= 0;
2124 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
2125 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
2130 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2131 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2132 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2137 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2139 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2140 debugstr_w(ptiRet
->Name
),
2141 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2142 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2147 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2148 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2149 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2152 static ITypeLibImpl
*tlb_cache_first
;
2153 static CRITICAL_SECTION cache_section
;
2154 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2156 0, 0, &cache_section
,
2157 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2158 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2160 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2163 /****************************************************************************
2166 * find the type of the typelib file and map the typelib resource into
2169 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2170 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2171 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2173 ITypeLibImpl
*entry
;
2174 int ret
= TYPE_E_CANTLOADLIBRARY
;
2175 DWORD dwSignature
= 0;
2178 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2182 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2183 EnterCriticalSection(&cache_section
);
2184 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2186 if (!strcmpiW(entry
->path
, pszFileName
) && entry
->index
== index
)
2188 TRACE("cache hit\n");
2189 *ppTypeLib
= (ITypeLib2
*)entry
;
2190 ITypeLib_AddRef(*ppTypeLib
);
2191 LeaveCriticalSection(&cache_section
);
2195 LeaveCriticalSection(&cache_section
);
2197 /* check the signature of the file */
2198 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2199 if (INVALID_HANDLE_VALUE
!= hFile
)
2201 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2204 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2207 /* retrieve file size */
2208 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2210 /* first try to load as *.tlb */
2211 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2212 if ( dwSignature
== MSFT_SIGNATURE
)
2214 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2216 else if ( dwSignature
== SLTG_SIGNATURE
)
2218 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2220 UnmapViewOfFile(pBase
);
2222 CloseHandle(hMapping
);
2228 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName
));
2231 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2232 if (((WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
) || (dwSignature
== 0))
2234 /* find the typelibrary resource*/
2235 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2236 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2239 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2240 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2243 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2246 LPVOID pBase
= LockResource(hGlobal
);
2247 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2251 /* try to load as incore resource */
2252 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2253 if ( dwSignature
== MSFT_SIGNATURE
)
2255 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2257 else if ( dwSignature
== SLTG_SIGNATURE
)
2259 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2263 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2266 FreeResource( hGlobal
);
2269 FreeLibrary(hinstDLL
);
2274 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2276 TRACE("adding to cache\n");
2277 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2278 lstrcpyW(impl
->path
, pszFileName
);
2279 /* We should really canonicalise the path here. */
2280 impl
->index
= index
;
2282 /* FIXME: check if it has added already in the meantime */
2283 EnterCriticalSection(&cache_section
);
2284 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2286 tlb_cache_first
= impl
;
2287 LeaveCriticalSection(&cache_section
);
2290 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2295 /*================== ITypeLib(2) Methods ===================================*/
2297 /****************************************************************************
2298 * ITypeLib2_Constructor_MSFT
2300 * loading an MSFT typelib from an in-memory image
2302 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2306 MSFT_Header tlbHeader
;
2307 MSFT_SegDir tlbSegDir
;
2308 ITypeLibImpl
* pTypeLibImpl
;
2310 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2312 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2313 if (!pTypeLibImpl
) return NULL
;
2315 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2316 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2317 pTypeLibImpl
->ref
= 1;
2319 /* get pointer to beginning of typelib data */
2323 cx
.pLibInfo
= pTypeLibImpl
;
2324 cx
.length
= dwTLBLength
;
2327 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2329 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2330 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2331 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2334 /* there is a small amount of information here until the next important
2336 * the segment directory . Try to calculate the amount of data */
2337 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2339 /* now read the segment directory */
2340 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2341 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2342 cx
.pTblDir
= &tlbSegDir
;
2344 /* just check two entries */
2345 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2347 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2348 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2352 /* now fill our internal data */
2353 /* TLIBATTR fields */
2354 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2356 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2357 /* Windows seems to have zero here, is this correct? */
2358 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2359 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2361 pTypeLibImpl
->LibAttr
.lcid
= 0;
2363 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2364 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2365 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2366 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2368 /* name, eventually add to a hash table */
2369 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2372 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2373 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2375 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2378 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2379 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2382 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2385 if(tlbHeader
.CustomDataOffset
>= 0)
2387 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2390 /* fill in typedescriptions */
2391 if(tlbSegDir
.pTypdescTab
.length
> 0)
2393 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2395 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2396 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2399 /* FIXME: add several sanity checks here */
2400 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2401 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2403 /* FIXME: check safearray */
2405 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2407 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2409 else if(td
[0] == VT_CARRAY
)
2411 /* array descr table here */
2412 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2414 else if(td
[0] == VT_USERDEFINED
)
2416 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2418 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2421 /* second time around to fill the array subscript info */
2424 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2425 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2427 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2428 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2431 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2433 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2435 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2437 for(j
= 0; j
<td
[2]; j
++)
2439 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2440 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2441 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2442 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2447 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2448 ERR("didn't find array description data\n");
2453 /* imported type libs */
2454 if(tlbSegDir
.pImpFiles
.offset
>0)
2456 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2457 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2460 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2465 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2466 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2467 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2469 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2470 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2471 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2472 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2475 name
= TLB_Alloc(size
+1);
2476 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2477 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2478 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2479 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2482 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2483 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2485 ppImpLib
= &(*ppImpLib
)->next
;
2490 if(tlbHeader
.nrtypeinfos
>= 0 )
2492 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2493 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2496 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2498 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2500 ppTI
= &((*ppTI
)->next
);
2501 (pTypeLibImpl
->TypeInfoCount
)++;
2505 TRACE("(%p)\n", pTypeLibImpl
);
2506 return (ITypeLib2
*) pTypeLibImpl
;
2510 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2516 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2517 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2518 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2519 ret
= SysAllocString(nameW
);
2520 HeapFree(GetProcessHeap(), 0, nameW
);
2524 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2530 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2531 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2535 guid
->Data4
[0] = s
>> 8;
2536 guid
->Data4
[1] = s
& 0xff;
2539 for(i
= 0; i
< 6; i
++) {
2540 memcpy(b
, str
+ 24 + 2 * i
, 2);
2541 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2546 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2553 bytelen
= *(WORD
*)ptr
;
2554 if(bytelen
== 0xffff) return 2;
2555 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2556 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2557 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2558 *pBstr
= SysAllocStringLen(nameW
, len
);
2559 HeapFree(GetProcessHeap(), 0, nameW
);
2563 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2568 bytelen
= *(WORD
*)ptr
;
2569 if(bytelen
== 0xffff) return 2;
2570 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2571 memcpy(*str
, ptr
+ 2, bytelen
);
2572 (*str
)[bytelen
] = '\0';
2576 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2578 char *ptr
= pLibBlk
;
2581 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2582 FIXME("libblk magic = %04x\n", w
);
2587 if((w
= *(WORD
*)ptr
) != 0xffff) {
2588 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2593 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2595 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2597 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2600 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2603 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2604 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2606 pTypeLibImpl
->LibAttr
.lcid
= 0;
2609 ptr
+= 4; /* skip res12 */
2611 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2614 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2617 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2620 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2621 ptr
+= sizeof(GUID
);
2623 return ptr
- (char*)pLibBlk
;
2626 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2629 TYPEDESC
*pTD
= &pElem
->tdesc
;
2631 /* Handle [in/out] first */
2632 if((*pType
& 0xc000) == 0xc000)
2633 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2634 else if(*pType
& 0x8000)
2635 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2636 else if(*pType
& 0x4000)
2637 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2639 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2642 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2645 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2648 if((*pType
& 0xe00) == 0xe00) {
2650 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2652 pTD
= pTD
->u
.lptdesc
;
2654 switch(*pType
& 0x7f) {
2657 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2659 pTD
= pTD
->u
.lptdesc
;
2662 case VT_USERDEFINED
:
2663 pTD
->vt
= VT_USERDEFINED
;
2664 pTD
->u
.hreftype
= *(++pType
) / 4;
2670 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2673 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2675 pTD
->vt
= VT_CARRAY
;
2676 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2678 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2679 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2680 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2681 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2683 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2689 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2693 pTD
->vt
= VT_SAFEARRAY
;
2694 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2696 pTD
= pTD
->u
.lptdesc
;
2700 pTD
->vt
= *pType
& 0x7f;
2710 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2715 TLBRefType
**ppRefType
;
2717 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2718 FIXME("Ref magic = %x\n", pRef
->magic
);
2721 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2723 ppRefType
= &pTI
->reflist
;
2724 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2726 unsigned int lib_offs
, type_num
;
2728 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2729 sizeof(**ppRefType
));
2731 name
+= SLTG_ReadStringA(name
, &refname
);
2732 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2733 FIXME("Can't sscanf ref\n");
2734 if(lib_offs
!= 0xffff) {
2735 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2738 if((*import
)->offset
== lib_offs
)
2740 import
= &(*import
)->next
;
2743 char fname
[MAX_PATH
+1];
2746 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2748 (*import
)->offset
= lib_offs
;
2749 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2751 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2752 &(*import
)->wVersionMajor
,
2753 &(*import
)->wVersionMinor
,
2754 &(*import
)->lcid
, fname
) != 4) {
2755 FIXME("can't sscanf ref %s\n",
2756 pNameTable
+ lib_offs
+ 40);
2758 len
= strlen(fname
);
2759 if(fname
[len
-1] != '#')
2760 FIXME("fname = %s\n", fname
);
2761 fname
[len
-1] = '\0';
2762 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2764 (*ppRefType
)->pImpTLInfo
= *import
;
2765 } else { /* internal ref */
2766 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2768 (*ppRefType
)->reference
= ref
;
2769 (*ppRefType
)->index
= type_num
;
2771 HeapFree(GetProcessHeap(), 0, refname
);
2772 ppRefType
= &(*ppRefType
)->next
;
2774 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2775 FIXME("End of ref block magic = %x\n", *name
);
2776 dump_TLBRefType(pTI
->reflist
);
2779 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2782 SLTG_ImplInfo
*info
;
2783 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2784 /* I don't really get this structure, usually it's 0x16 bytes
2785 long, but iuser.tlb contains some that are 0x18 bytes long.
2786 That's ok because we can use the next ptr to jump to the next
2787 one. But how do we know the length of the last one? The WORD
2788 at offs 0x8 might be the clue. For now I'm just assuming that
2789 the last one is the regular 0x16 bytes. */
2791 info
= (SLTG_ImplInfo
*)pBlk
;
2793 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2794 sizeof(**ppImplType
));
2795 (*ppImplType
)->hRef
= info
->ref
;
2796 (*ppImplType
)->implflags
= info
->impltypeflags
;
2797 pTI
->TypeAttr
.cImplTypes
++;
2798 ppImplType
= &(*ppImplType
)->next
;
2800 if(info
->next
== 0xffff)
2803 FIXME("Interface inheriting more than one interface\n");
2804 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2806 info
++; /* see comment at top of function */
2810 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2813 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2814 SLTG_MemberHeader
*pMemHeader
;
2815 char *pFirstItem
, *pNextItem
;
2817 if(pTIHeader
->href_table
!= 0xffffffff) {
2818 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2823 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2825 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2827 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2828 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2831 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2835 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2838 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2839 SLTG_MemberHeader
*pMemHeader
;
2840 SLTG_Function
*pFunc
;
2841 char *pFirstItem
, *pNextItem
;
2842 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2845 if(pTIHeader
->href_table
!= 0xffffffff) {
2846 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2850 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2852 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2854 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2855 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2858 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2859 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2864 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2865 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2866 FIXME("func magic = %02x\n", pFunc
->magic
);
2869 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2870 sizeof(**ppFuncDesc
));
2871 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2873 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2874 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2875 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2876 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2877 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2878 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2880 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2881 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2883 if(pFunc
->retnextopt
& 0x80)
2884 pType
= &pFunc
->rettype
;
2886 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2889 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2891 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2892 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2893 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2894 (*ppFuncDesc
)->pParamDesc
=
2895 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2896 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2898 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2900 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2901 char *paramName
= pNameTable
+ *pArg
;
2903 /* If arg type follows then paramName points to the 2nd
2904 letter of the name, else the next WORD is an offset to
2905 the arg type and paramName points to the first letter.
2906 So let's take one char off paramName and see if we're
2907 pointing at an alpha-numeric char. However if *pArg is
2908 0xffff or 0xfffe then the param has no name, the former
2909 meaning that the next WORD is the type, the latter
2910 meaning the the next WORD is an offset to the type. */
2915 else if(*pArg
== 0xfffe) {
2919 else if(paramName
[-1] && !isalnum(paramName
[-1]))
2924 if(HaveOffs
) { /* the next word is an offset to type */
2925 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2926 SLTG_DoType(pType
, pFirstItem
,
2927 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2932 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2933 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2936 /* Are we an optional param ? */
2937 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2938 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2939 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2942 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2943 TLB_MultiByteToBSTR(paramName
);
2947 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2948 if(pFunc
->next
== 0xffff) break;
2950 pTI
->TypeAttr
.cFuncs
= num
;
2951 dump_TLBFuncDesc(pTI
->funclist
);
2952 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2955 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2958 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2959 SLTG_MemberHeader
*pMemHeader
;
2960 SLTG_RecordItem
*pItem
;
2962 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2967 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2969 pFirstItem
= (char*)(pMemHeader
+ 1);
2970 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2971 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2972 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2973 FIXME("record magic = %02x\n", pItem
->magic
);
2976 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2977 sizeof(**ppVarDesc
));
2978 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2979 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2980 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2981 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2983 if(pItem
->typepos
== 0x02)
2984 pType
= &pItem
->type
;
2985 else if(pItem
->typepos
== 0x00)
2986 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2988 FIXME("typepos = %02x\n", pItem
->typepos
);
2992 SLTG_DoType(pType
, pFirstItem
,
2993 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2995 /* FIXME("helpcontext, helpstring\n"); */
2997 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2999 ppVarDesc
= &((*ppVarDesc
)->next
);
3000 if(pItem
->next
== 0xffff) break;
3002 pTI
->TypeAttr
.cVars
= num
;
3003 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3006 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3009 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3010 SLTG_MemberHeader
*pMemHeader
;
3011 SLTG_AliasItem
*pItem
;
3014 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3015 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3018 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3019 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
3020 if (pItem
->vt
== 0xffff) {
3021 if (i
<(pMemHeader
->cbExtra
/4-1))
3022 FIXME("Endmarker too early in process alias data!\n");
3026 FIXME("Chain extends over last entry?\n");
3029 if (pItem
->vt
== VT_USERDEFINED
) {
3030 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
3031 /* guessing here ... */
3032 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
3033 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
3036 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
3037 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
3041 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3044 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3047 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3048 SLTG_MemberHeader
*pMemHeader
;
3049 SLTG_AliasItem
*pItem
;
3051 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3052 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3053 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
3054 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
3055 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3058 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3061 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3062 SLTG_MemberHeader
*pMemHeader
;
3063 SLTG_EnumItem
*pItem
;
3065 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3068 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3070 pFirstItem
= (char*)(pMemHeader
+ 1);
3071 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
3072 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
3073 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
3074 FIXME("enumitem magic = %04x\n", pItem
->magic
);
3077 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3078 sizeof(**ppVarDesc
));
3079 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3080 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3081 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3083 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3084 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
3085 *(INT
*)(pItem
->value
+ pFirstItem
);
3086 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
3087 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3088 /* FIXME("helpcontext, helpstring\n"); */
3090 ppVarDesc
= &((*ppVarDesc
)->next
);
3091 if(pItem
->next
== 0xffff) break;
3093 pTI
->TypeAttr
.cVars
= num
;
3094 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3097 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3098 managable copy of it into this */
3111 } SLTG_InternalOtherTypeInfo
;
3113 /****************************************************************************
3114 * ITypeLib2_Constructor_SLTG
3116 * loading a SLTG typelib from an in-memory image
3118 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3120 ITypeLibImpl
*pTypeLibImpl
;
3121 SLTG_Header
*pHeader
;
3122 SLTG_BlkEntry
*pBlkEntry
;
3126 LPVOID pBlk
, pFirstBlk
;
3127 SLTG_LibBlk
*pLibBlk
;
3128 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3129 char *pAfterOTIBlks
= NULL
;
3130 char *pNameTable
, *ptr
;
3133 ITypeInfoImpl
**ppTypeInfoImpl
;
3135 TRACE_(typelib
)("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3137 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
3138 if (!pTypeLibImpl
) return NULL
;
3140 pTypeLibImpl
->lpVtbl
= &tlbvt
;
3141 pTypeLibImpl
->ref
= 1;
3145 TRACE_(typelib
)("header:\n");
3146 TRACE_(typelib
)("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
3147 pHeader
->nrOfFileBlks
);
3148 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3149 FIXME("Header type magic 0x%08lx not supported.\n",
3150 pHeader
->SLTG_magic
);
3154 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3155 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3157 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3158 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3160 /* Next we have a magic block */
3161 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3163 /* Let's see if we're still in sync */
3164 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3165 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3166 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3169 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3170 sizeof(SLTG_DIR_MAGIC
))) {
3171 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3175 pIndex
= (SLTG_Index
*)(pMagic
+1);
3177 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3179 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3181 /* We'll set up a ptr to the main library block, which is the last one. */
3183 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3184 pBlkEntry
[order
].next
!= 0;
3185 order
= pBlkEntry
[order
].next
- 1, i
++) {
3186 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3190 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3192 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3197 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3199 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3200 sizeof(*pOtherTypeInfoBlks
) *
3201 pTypeLibImpl
->TypeInfoCount
);
3204 ptr
= (char*)pLibBlk
+ len
;
3206 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3210 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3212 w
= *(WORD
*)(ptr
+ 2);
3215 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3217 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3218 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3220 w
= *(WORD
*)(ptr
+ 4 + len
);
3222 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3224 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3226 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3227 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3229 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3230 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3231 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3233 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3235 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3238 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3239 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3240 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3241 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3242 len
+= sizeof(SLTG_OtherTypeInfo
);
3246 pAfterOTIBlks
= ptr
;
3248 /* Skip this WORD and get the next DWORD */
3249 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3251 /* Now add this to pLibBLk look at what we're pointing at and
3252 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3253 dust and we should be pointing at the beginning of the name
3256 pNameTable
= (char*)pLibBlk
+ len
;
3258 switch(*(WORD
*)pNameTable
) {
3265 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3269 pNameTable
+= 0x216;
3273 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3275 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3278 /* Hopefully we now have enough ptrs set up to actually read in
3279 some TypeInfos. It's not clear which order to do them in, so
3280 I'll just follow the links along the BlkEntry chain and read
3281 them in in the order in which they're in the file */
3283 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3285 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3286 pBlkEntry
[order
].next
!= 0;
3287 order
= pBlkEntry
[order
].next
- 1, i
++) {
3289 SLTG_TypeInfoHeader
*pTIHeader
;
3290 SLTG_TypeInfoTail
*pTITail
;
3292 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3293 pOtherTypeInfoBlks
[i
].index_name
)) {
3294 FIXME("Index strings don't match\n");
3299 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3300 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3303 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3304 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3305 (*ppTypeInfoImpl
)->index
= i
;
3306 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3307 pOtherTypeInfoBlks
[i
].name_offs
+
3309 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3310 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3312 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3313 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3314 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3315 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3316 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3318 if((pTIHeader
->typeflags1
& 7) != 2)
3319 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3320 if(pTIHeader
->typeflags3
!= 2)
3321 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3323 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3324 debugstr_w((*ppTypeInfoImpl
)->Name
),
3325 typekind_desc
[pTIHeader
->typekind
],
3326 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3327 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3329 switch(pTIHeader
->typekind
) {
3331 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3335 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3338 case TKIND_INTERFACE
:
3339 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3343 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3347 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3348 if (pTITail
->tdescalias_vt
)
3349 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3352 case TKIND_DISPATCH
:
3353 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3357 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3363 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3364 but we've already set those */
3365 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3366 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3367 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3369 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3391 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3392 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3395 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3396 FIXME("Somehow processed %d TypeInfos\n", i
);
3400 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3401 return (ITypeLib2
*)pTypeLibImpl
;
3404 /* ITypeLib::QueryInterface
3406 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3411 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3413 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3416 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3417 IsEqualIID(riid
,&IID_ITypeLib
)||
3418 IsEqualIID(riid
,&IID_ITypeLib2
))
3425 ITypeLib2_AddRef(iface
);
3426 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3429 TRACE("-- Interface: E_NOINTERFACE\n");
3430 return E_NOINTERFACE
;
3435 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3437 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3438 ULONG ref
= InterlockedIncrement(&This
->ref
);
3440 TRACE("(%p)->ref was %lu\n",This
, ref
- 1);
3445 /* ITypeLib::Release
3447 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3449 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3450 ULONG ref
= InterlockedDecrement(&This
->ref
);
3452 TRACE("(%p)->(%lu)\n",This
, ref
);
3456 /* remove cache entry */
3457 TRACE("removing from cache list\n");
3458 EnterCriticalSection(&cache_section
);
3459 if (This
->next
) This
->next
->prev
= This
->prev
;
3460 if (This
->prev
) This
->prev
->next
= This
->next
;
3461 else tlb_cache_first
= This
->next
;
3462 LeaveCriticalSection(&cache_section
);
3464 /* FIXME destroy child objects */
3465 TRACE(" destroying ITypeLib(%p)\n",This
);
3469 SysFreeString(This
->Name
);
3473 if (This
->DocString
)
3475 SysFreeString(This
->DocString
);
3476 This
->DocString
= NULL
;
3481 SysFreeString(This
->HelpFile
);
3482 This
->HelpFile
= NULL
;
3485 if (This
->HelpStringDll
)
3487 SysFreeString(This
->HelpStringDll
);
3488 This
->HelpStringDll
= NULL
;
3491 if (This
->pTypeInfo
) /* can be NULL */
3492 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3493 HeapFree(GetProcessHeap(),0,This
);
3500 /* ITypeLib::GetTypeInfoCount
3502 * Returns the number of type descriptions in the type library
3504 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3506 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3507 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3508 return This
->TypeInfoCount
;
3511 /* ITypeLib::GetTypeInfo
3513 * retrieves the specified type description in the library.
3515 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3518 ITypeInfo
**ppTInfo
)
3522 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3523 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3525 TRACE("(%p)->(index=%d) \n", This
, index
);
3527 if (!ppTInfo
) return E_INVALIDARG
;
3529 /* search element n in list */
3530 for(i
=0; i
< index
; i
++)
3532 pTypeInfo
= pTypeInfo
->next
;
3535 TRACE("-- element not found\n");
3536 return TYPE_E_ELEMENTNOTFOUND
;
3540 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3542 ITypeInfo_AddRef(*ppTInfo
);
3543 TRACE("-- found (%p)\n",*ppTInfo
);
3548 /* ITypeLibs::GetTypeInfoType
3550 * Retrieves the type of a type description.
3552 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3557 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3559 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3561 TRACE("(%p) index %d \n",This
, index
);
3563 if(!pTKind
) return E_INVALIDARG
;
3565 /* search element n in list */
3566 for(i
=0; i
< index
; i
++)
3570 TRACE("-- element not found\n");
3571 return TYPE_E_ELEMENTNOTFOUND
;
3573 pTInfo
= pTInfo
->next
;
3576 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3577 TRACE("-- found Type (%d)\n", *pTKind
);
3581 /* ITypeLib::GetTypeInfoOfGuid
3583 * Retrieves the type description that corresponds to the specified GUID.
3586 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3589 ITypeInfo
**ppTInfo
)
3591 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3592 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3594 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3596 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3598 /* search linked list for guid */
3599 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3601 pTypeInfo
= pTypeInfo
->next
;
3605 /* end of list reached */
3606 TRACE("-- element not found\n");
3607 return TYPE_E_ELEMENTNOTFOUND
;
3611 TRACE("-- found (%p, %s)\n",
3613 debugstr_w(pTypeInfo
->Name
));
3615 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3616 ITypeInfo_AddRef(*ppTInfo
);
3620 /* ITypeLib::GetLibAttr
3622 * Retrieves the structure that contains the library's attributes.
3625 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3627 LPTLIBATTR
*ppTLibAttr
)
3629 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3630 TRACE("(%p)\n",This
);
3631 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3632 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3636 /* ITypeLib::GetTypeComp
3638 * Enables a client compiler to bind to a library's types, variables,
3639 * constants, and global functions.
3642 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3644 ITypeComp
**ppTComp
)
3646 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3648 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3649 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3650 ITypeComp_AddRef(*ppTComp
);
3655 /* ITypeLib::GetDocumentation
3657 * Retrieves the library's documentation string, the complete Help file name
3658 * and path, and the context identifier for the library Help topic in the Help
3661 * On a successful return all non-null BSTR pointers will have been set,
3664 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3668 BSTR
*pBstrDocString
,
3669 DWORD
*pdwHelpContext
,
3670 BSTR
*pBstrHelpFile
)
3672 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3674 HRESULT result
= E_INVALIDARG
;
3679 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3681 pBstrName
, pBstrDocString
,
3682 pdwHelpContext
, pBstrHelpFile
);
3686 /* documentation for the typelib */
3690 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3696 if (This
->DocString
)
3697 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3698 else if (This
->Name
)
3699 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3701 *pBstrDocString
= NULL
;
3705 *pdwHelpContext
= This
->dwHelpContext
;
3710 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3712 *pBstrHelpFile
= NULL
;
3719 /* for a typeinfo */
3720 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3722 if(SUCCEEDED(result
))
3724 result
= ITypeInfo_GetDocumentation(pTInfo
,
3728 pdwHelpContext
, pBstrHelpFile
);
3730 ITypeInfo_Release(pTInfo
);
3735 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3737 if (pBstrName
) SysFreeString (*pBstrName
);
3739 return STG_E_INSUFFICIENTMEMORY
;
3744 * Indicates whether a passed-in string contains the name of a type or member
3745 * described in the library.
3748 static HRESULT WINAPI
ITypeLib2_fnIsName(
3754 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3755 ITypeInfoImpl
*pTInfo
;
3756 TLBFuncDesc
*pFInfo
;
3759 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3761 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3765 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3766 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3767 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3768 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3769 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3770 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3771 goto ITypeLib2_fnIsName_exit
;
3773 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3774 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3779 ITypeLib2_fnIsName_exit
:
3780 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3781 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3786 /* ITypeLib::FindName
3788 * Finds occurrences of a type description in a type library. This may be used
3789 * to quickly verify that a name exists in a type library.
3792 static HRESULT WINAPI
ITypeLib2_fnFindName(
3796 ITypeInfo
**ppTInfo
,
3800 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3801 ITypeInfoImpl
*pTInfo
;
3802 TLBFuncDesc
*pFInfo
;
3805 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
3807 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3808 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3809 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3810 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3811 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++) {
3812 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3813 goto ITypeLib2_fnFindName_exit
;
3816 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3817 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3819 ITypeLib2_fnFindName_exit
:
3820 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3821 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3824 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3825 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3832 /* ITypeLib::ReleaseTLibAttr
3834 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3837 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3839 TLIBATTR
*pTLibAttr
)
3841 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3842 TRACE("freeing (%p)\n",This
);
3843 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3847 /* ITypeLib2::GetCustData
3849 * gets the custom data
3851 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3856 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3857 TLBCustData
*pCData
;
3859 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3861 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3864 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3868 VariantInit( pVarVal
);
3869 VariantCopy( pVarVal
, &pCData
->data
);
3872 return E_INVALIDARG
; /* FIXME: correct? */
3875 /* ITypeLib2::GetLibStatistics
3877 * Returns statistics about a type library that are required for efficient
3878 * sizing of hash tables.
3881 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3883 ULONG
*pcUniqueNames
,
3884 ULONG
*pcchUniqueNames
)
3886 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3888 FIXME("(%p): stub!\n", This
);
3890 if(pcUniqueNames
) *pcUniqueNames
=1;
3891 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3895 /* ITypeLib2::GetDocumentation2
3897 * Retrieves the library's documentation string, the complete Help file name
3898 * and path, the localization context to use, and the context ID for the
3899 * library Help topic in the Help file.
3902 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3906 BSTR
*pbstrHelpString
,
3907 DWORD
*pdwHelpStringContext
,
3908 BSTR
*pbstrHelpStringDll
)
3910 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3914 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3916 /* the help string should be obtained from the helpstringdll,
3917 * using the _DLLGetDocumentation function, based on the supplied
3918 * lcid. Nice to do sometime...
3922 /* documentation for the typelib */
3924 *pbstrHelpString
=SysAllocString(This
->DocString
);
3925 if(pdwHelpStringContext
)
3926 *pdwHelpStringContext
=This
->dwHelpContext
;
3927 if(pbstrHelpStringDll
)
3928 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3934 /* for a typeinfo */
3935 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3937 if(SUCCEEDED(result
))
3939 ITypeInfo2
* pTInfo2
;
3940 result
= ITypeInfo_QueryInterface(pTInfo
,
3942 (LPVOID
*) &pTInfo2
);
3944 if(SUCCEEDED(result
))
3946 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3950 pdwHelpStringContext
,
3951 pbstrHelpStringDll
);
3953 ITypeInfo2_Release(pTInfo2
);
3956 ITypeInfo_Release(pTInfo
);
3962 /* ITypeLib2::GetAllCustData
3964 * Gets all custom data items for the library.
3967 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3969 CUSTDATA
*pCustData
)
3971 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3972 TLBCustData
*pCData
;
3974 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3975 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3976 if(pCustData
->prgCustData
){
3977 pCustData
->cCustData
=This
->ctCustData
;
3978 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3979 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3980 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3983 ERR(" OUT OF MEMORY! \n");
3984 return E_OUTOFMEMORY
;
3989 static const ITypeLib2Vtbl tlbvt
= {
3990 ITypeLib2_fnQueryInterface
,
3992 ITypeLib2_fnRelease
,
3993 ITypeLib2_fnGetTypeInfoCount
,
3994 ITypeLib2_fnGetTypeInfo
,
3995 ITypeLib2_fnGetTypeInfoType
,
3996 ITypeLib2_fnGetTypeInfoOfGuid
,
3997 ITypeLib2_fnGetLibAttr
,
3998 ITypeLib2_fnGetTypeComp
,
3999 ITypeLib2_fnGetDocumentation
,
4001 ITypeLib2_fnFindName
,
4002 ITypeLib2_fnReleaseTLibAttr
,
4004 ITypeLib2_fnGetCustData
,
4005 ITypeLib2_fnGetLibStatistics
,
4006 ITypeLib2_fnGetDocumentation2
,
4007 ITypeLib2_fnGetAllCustData
4011 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4013 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4015 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4018 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4020 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4022 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4025 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4027 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4029 return ITypeLib2_Release((ITypeLib2
*)This
);
4032 static HRESULT WINAPI
ITypeLibComp_fnBind(
4037 ITypeInfo
** ppTInfo
,
4038 DESCKIND
* pDescKind
,
4041 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4045 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4049 ITypeInfo
** ppTInfo
,
4050 ITypeComp
** ppTComp
)
4052 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4056 static const ITypeCompVtbl tlbtcvt
=
4059 ITypeLibComp_fnQueryInterface
,
4060 ITypeLibComp_fnAddRef
,
4061 ITypeLibComp_fnRelease
,
4063 ITypeLibComp_fnBind
,
4064 ITypeLibComp_fnBindType
4067 /*================== ITypeInfo(2) Methods ===================================*/
4068 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4070 ITypeInfoImpl
* pTypeInfoImpl
;
4072 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4075 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4076 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4077 pTypeInfoImpl
->ref
=1;
4079 TRACE("(%p)\n", pTypeInfoImpl
);
4080 return (ITypeInfo2
*) pTypeInfoImpl
;
4083 /* ITypeInfo::QueryInterface
4085 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4090 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4092 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4095 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4096 IsEqualIID(riid
,&IID_ITypeInfo
)||
4097 IsEqualIID(riid
,&IID_ITypeInfo2
))
4101 ITypeInfo_AddRef(iface
);
4102 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4105 TRACE("-- Interface: E_NOINTERFACE\n");
4106 return E_NOINTERFACE
;
4109 /* ITypeInfo::AddRef
4111 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4113 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4114 ULONG ref
= InterlockedIncrement(&This
->ref
);
4116 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4118 TRACE("(%p)->ref is %lu\n",This
, ref
);
4122 /* ITypeInfo::Release
4124 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4126 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4127 ULONG ref
= InterlockedDecrement(&This
->ref
);
4129 TRACE("(%p)->(%lu)\n",This
, ref
);
4132 /* We don't release ITypeLib when ref=0 because
4133 it means that function is called by ITypeLib2_Release */
4134 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4136 FIXME("destroy child objects\n");
4138 TRACE("destroying ITypeInfo(%p)\n",This
);
4141 SysFreeString(This
->Name
);
4145 if (This
->DocString
)
4147 SysFreeString(This
->DocString
);
4148 This
->DocString
= 0;
4153 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4156 HeapFree(GetProcessHeap(),0,This
);
4162 /* ITypeInfo::GetTypeAttr
4164 * Retrieves a TYPEATTR structure that contains the attributes of the type
4168 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4169 LPTYPEATTR
*ppTypeAttr
)
4171 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4172 TRACE("(%p)\n",This
);
4173 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr
));
4174 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4176 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
) /* need to deep copy typedesc */
4177 copy_typedesc(&(*ppTypeAttr
)->tdescAlias
, &This
->TypeAttr
.tdescAlias
);
4179 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
4180 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4182 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4183 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4188 /* ITypeInfo::GetTypeComp
4190 * Retrieves the ITypeComp interface for the type description, which enables a
4191 * client compiler to bind to the type description's members.
4194 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4195 ITypeComp
* *ppTComp
)
4197 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4199 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4201 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4202 ITypeComp_AddRef(*ppTComp
);
4206 /* ITypeInfo::GetFuncDesc
4208 * Retrieves the FUNCDESC structure that contains information about a
4209 * specified function.
4212 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4213 LPFUNCDESC
*ppFuncDesc
)
4215 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4217 TLBFuncDesc
* pFDesc
;
4218 TRACE("(%p) index %d\n", This
, index
);
4219 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4222 /* FIXME: must do a copy here */
4223 *ppFuncDesc
=&pFDesc
->funcdesc
;
4226 return E_INVALIDARG
;
4229 /* ITypeInfo::GetVarDesc
4231 * Retrieves a VARDESC structure that describes the specified variable.
4234 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4235 LPVARDESC
*ppVarDesc
)
4237 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4239 TLBVarDesc
* pVDesc
;
4240 TRACE("(%p) index %d\n", This
, index
);
4241 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4244 /* FIXME: must do a copy here */
4245 *ppVarDesc
=&pVDesc
->vardesc
;
4248 return E_INVALIDARG
;
4251 /* ITypeInfo_GetNames
4253 * Retrieves the variable with the specified member ID (or the name of the
4254 * property or method and its parameters) that correspond to the specified
4257 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4258 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4260 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4261 TLBFuncDesc
* pFDesc
;
4262 TLBVarDesc
* pVDesc
;
4264 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4265 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4268 /* function found, now return function and parameter names */
4269 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4272 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4274 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4280 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4283 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4288 if(This
->TypeAttr
.cImplTypes
&&
4289 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4290 /* recursive search */
4293 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4295 if(SUCCEEDED(result
))
4297 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4298 ITypeInfo_Release(pTInfo
);
4301 WARN("Could not search inherited interface!\n");
4305 WARN("no names found\n");
4308 return TYPE_E_ELEMENTNOTFOUND
;
4315 /* ITypeInfo::GetRefTypeOfImplType
4317 * If a type description describes a COM class, it retrieves the type
4318 * description of the implemented interface types. For an interface,
4319 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4323 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4328 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4330 TLBImplType
*pImpl
= This
->impltypelist
;
4332 TRACE("(%p) index %d\n", This
, index
);
4333 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4337 /* only valid on dual interfaces;
4338 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4340 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4342 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4343 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4349 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4350 *pRefType
= pImpl
->hRef
;
4355 /* get element n from linked list */
4356 for(i
=0; pImpl
&& i
<index
; i
++)
4358 pImpl
= pImpl
->next
;
4361 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4363 *pRefType
= pImpl
->hRef
;
4365 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4372 /* ITypeInfo::GetImplTypeFlags
4374 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4375 * or base interface in a type description.
4377 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4378 UINT index
, INT
*pImplTypeFlags
)
4380 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4384 TRACE("(%p) index %d\n", This
, index
);
4385 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4386 i
++, pImpl
=pImpl
->next
)
4388 if(i
==index
&& pImpl
){
4389 *pImplTypeFlags
=pImpl
->implflags
;
4393 return TYPE_E_ELEMENTNOTFOUND
;
4397 * Maps between member names and member IDs, and parameter names and
4400 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4401 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4403 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4404 TLBFuncDesc
* pFDesc
;
4405 TLBVarDesc
* pVDesc
;
4408 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4410 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4412 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4413 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4414 for(i
=1; i
< cNames
; i
++){
4415 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4416 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4418 if( j
<pFDesc
->funcdesc
.cParams
)
4421 ret
=DISP_E_UNKNOWNNAME
;
4426 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4427 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4428 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4432 /* not found, see if this is and interface with an inheritance */
4433 if(This
->TypeAttr
.cImplTypes
&&
4434 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4435 /* recursive search */
4437 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4438 This
->impltypelist
->hRef
, &pTInfo
);
4440 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4441 ITypeInfo_Release(pTInfo
);
4444 WARN("Could not search inherited interface!\n");
4446 WARN("no names found\n");
4447 return DISP_E_UNKNOWNNAME
;
4450 /* ITypeInfo::Invoke
4452 * Invokes a method, or accesses a property of an object, that implements the
4453 * interface described by the type description.
4456 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4459 if (TRACE_ON(ole
)) {
4461 TRACE("Calling %p(",func
);
4462 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4474 res
= func(args
[0]);
4477 res
= func(args
[0],args
[1]);
4480 res
= func(args
[0],args
[1],args
[2]);
4483 res
= func(args
[0],args
[1],args
[2],args
[3]);
4486 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4489 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4492 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4495 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4498 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4501 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
4504 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
4507 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]);
4510 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]);
4513 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]);
4516 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4522 FIXME("unsupported calling convention %d\n",callconv
);
4526 TRACE("returns %08lx\n",res
);
4530 extern int _argsize(DWORD vt
);
4532 /****************************************************************************
4533 * Helper functions for Dispcall / Invoke, which copies one variant
4534 * with target type onto the argument stack.
4537 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4538 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4540 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4543 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4544 memcpy(argpos
,&arg
,sizeof(void*));
4548 if (V_VT(arg
) == vt
) {
4549 memcpy(argpos
, &V_I4(arg
), arglen
);
4553 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4554 memcpy(argpos
, &V_ARRAY(arg
), sizeof(SAFEARRAY
*));
4558 if (vt
== VT_VARIANT
) {
4559 memcpy(argpos
, arg
, arglen
);
4562 /* Deref BYREF vars if there is need */
4563 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4564 memcpy(argpos
,(void*)V_I4(arg
), arglen
);
4567 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4568 /* in this context, if the type lib specifies IUnknown*, giving an
4569 IDispatch* is correct; so, don't invoke VariantChangeType */
4570 memcpy(argpos
,&V_I4(arg
), arglen
);
4573 if ((vt
== VT_PTR
) && tdesc
)
4574 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4576 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4577 ITypeInfo
*tinfo2
= NULL
;
4578 TYPEATTR
*tattr
= NULL
;
4581 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4583 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4584 "while coercing from vt 0x%x. Copying 4 byte.\n",
4585 tdesc
->u
.hreftype
,V_VT(arg
));
4586 memcpy(argpos
, &V_I4(arg
), 4);
4589 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4592 ERR("GetTypeAttr failed\n");
4593 ITypeInfo_Release(tinfo2
);
4596 switch (tattr
->typekind
) {
4598 switch ( V_VT( arg
) ) {
4600 *argpos
= V_I2(arg
);
4604 memcpy(argpos
, &V_I4(arg
), 4);
4607 case VT_BYREF
|VT_I4
:
4608 memcpy(argpos
, V_I4REF(arg
), 4);
4612 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4619 tdesc
= &(tattr
->tdescAlias
);
4620 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4623 case TKIND_INTERFACE
:
4624 if (V_VT(arg
) == VT_DISPATCH
) {
4626 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4627 memcpy(argpos
, &V_DISPATCH(arg
), 4);
4631 hres
=IUnknown_QueryInterface(V_DISPATCH(arg
),
4632 &IID_IDispatch
,(LPVOID
*)&disp
);
4633 if (SUCCEEDED(hres
)) {
4634 memcpy(argpos
,&disp
,4);
4635 IUnknown_Release(V_DISPATCH(arg
));
4639 FIXME("Failed to query IDispatch interface from %s while "
4640 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4644 if (V_VT(arg
) == VT_UNKNOWN
) {
4645 memcpy(argpos
, &V_UNKNOWN(arg
), 4);
4649 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4650 V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4654 case TKIND_DISPATCH
:
4655 if (V_VT(arg
) == VT_DISPATCH
) {
4656 memcpy(argpos
, &V_DISPATCH(arg
), 4);
4661 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4665 FIXME("TKIND_RECORD unhandled.\n");
4669 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4673 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4674 ITypeInfo_Release(tinfo2
);
4679 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4680 memcpy(argpos
,&V_I4(&va
), arglen
);
4681 FIXME("Should not use VariantChangeType here."
4682 " (conversion from 0x%x -> 0x%x) %08lx\n",
4683 V_VT(arg
), vt
, *argpos
4687 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4691 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, TYPEDESC
*tdesc
, VARTYPE
*vt
)
4694 ITypeInfo
*tinfo2
= NULL
;
4695 TYPEATTR
*tattr
= NULL
;
4697 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
4700 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4702 tdesc
->u
.hreftype
, hr
);
4705 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
4708 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr
);
4709 ITypeInfo_Release(tinfo2
);
4713 switch (tattr
->typekind
)
4720 tdesc
= &tattr
->tdescAlias
;
4721 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
4724 case TKIND_INTERFACE
:
4725 if (IsEqualIID(&IID_IDispatch
, &tattr
->guid
))
4731 case TKIND_DISPATCH
:
4736 FIXME("TKIND_RECORD unhandled.\n");
4741 FIXME("TKIND_RECORD unhandled.\n");
4746 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4750 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4751 ITypeInfo_Release(tinfo2
);
4755 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, TYPEDESC
*tdesc
, VARTYPE
*vt
)
4759 /* enforce only one level of pointer indirection */
4760 if (!(*vt
& VT_BYREF
) && (tdesc
->vt
== VT_PTR
))
4762 tdesc
= tdesc
->u
.lptdesc
;
4764 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4765 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4766 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4767 if ((tdesc
->vt
== VT_USERDEFINED
) ||
4768 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
4770 VARTYPE vt_userdefined
= 0;
4771 TYPEDESC
*tdesc_userdefined
= tdesc
;
4772 if (tdesc
->vt
== VT_PTR
)
4774 vt_userdefined
= VT_BYREF
;
4775 tdesc_userdefined
= tdesc
->u
.lptdesc
;
4777 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
4779 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
4780 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
4782 *vt
|= vt_userdefined
;
4794 case VT_USERDEFINED
:
4795 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
4798 ERR("cannot convert VT_PTR into variant VT\n");
4808 /***********************************************************************
4809 * DispCallFunc (OLEAUT32.@)
4813 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4814 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4816 int i
, argsize
, argspos
;
4820 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4821 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4823 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4824 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4826 for (i
=0;i
<cActuals
;i
++) {
4827 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4828 dump_Variant(prgpvarg
[i
]);
4829 argsize
+= _argsize(prgvt
[i
]);
4831 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4832 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4834 for (i
=0;i
<cActuals
;i
++) {
4835 VARIANT
*arg
= prgpvarg
[i
];
4836 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4837 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4838 argspos
+= _argsize(prgvt
[i
]);
4841 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4843 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4848 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4849 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4850 FIXME("Method returned %lx\n",hres
);
4852 HeapFree(GetProcessHeap(),0,args
);
4856 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4861 DISPPARAMS
*pDispParams
,
4862 VARIANT
*pVarResult
,
4863 EXCEPINFO
*pExcepInfo
,
4866 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4868 unsigned int func_index
, var_index
;
4872 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4873 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4875 dump_DispParms(pDispParams
);
4877 hres
= ITypeInfo2_GetFuncIndexOfMemId(iface
, memid
, dwFlags
, &func_index
);
4878 if (SUCCEEDED(hres
)) {
4879 FUNCDESC
*func_desc
;
4881 hres
= ITypeInfo2_GetFuncDesc(iface
, func_index
, &func_desc
);
4882 if(FAILED(hres
)) return hres
;
4885 TRACE("invoking:\n");
4886 dump_FUNCDESC(func_desc
);
4889 switch (func_desc
->funckind
) {
4890 case FUNC_PUREVIRTUAL
:
4891 case FUNC_VIRTUAL
: {
4893 int numargs
, numargs2
, argspos
, args2pos
;
4894 DWORD
*args
, *args2
;
4895 VARIANT
*rgvarg
= HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT
) * func_desc
->cParams
);
4896 memcpy(rgvarg
,pDispParams
->rgvarg
,sizeof(VARIANT
)*pDispParams
->cArgs
);
4899 numargs
= 1; /* sizeof(thisptr) */
4901 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4902 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4904 numargs
+= _argsize(tdesc
->vt
);
4905 if (i
>=pDispParams
->cArgs
) { /* arguments to return */
4906 if (tdesc
->vt
== VT_PTR
) {
4907 numargs2
+= _argsize(tdesc
->u
.lptdesc
->vt
);
4909 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc
->vt
);
4910 numargs2
+= _argsize(tdesc
->vt
);
4915 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4916 args2
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DWORD
)*numargs2
);
4918 args
[0] = (DWORD
)pIUnk
;
4919 argspos
= 1; args2pos
= 0;
4920 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4921 ELEMDESC
*elemdesc
= &(func_desc
->lprgelemdescParam
[i
]);
4922 TYPEDESC
*tdesc
= &(elemdesc
->tdesc
);
4923 USHORT paramFlags
= elemdesc
->u
.paramdesc
.wParamFlags
;
4924 int arglen
= _argsize(tdesc
->vt
);
4926 if (i
<pDispParams
->cArgs
) {
4927 VARIANT
*arg
= &rgvarg
[pDispParams
->cArgs
-i
-1];
4929 if (paramFlags
& PARAMFLAG_FOPT
) {
4930 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4931 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4932 if(V_VT(arg
) == VT_EMPTY
4933 || ((V_ISBYREF(arg
)) && !V_BYREF(arg
))) {
4934 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4935 How to determine it? */
4937 if(paramFlags
& PARAMFLAG_FHASDEFAULT
)
4938 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4939 V_VT(arg
) = VT_ERROR
;
4940 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4941 arglen
= _argsize(VT_ERROR
);
4944 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4945 if (FAILED(hres
)) goto func_fail
;
4947 } else if (paramFlags
& PARAMFLAG_FOPT
) {
4948 VARIANT
*arg
= &rgvarg
[i
];
4950 if (i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4951 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4952 if (paramFlags
& PARAMFLAG_FHASDEFAULT
)
4953 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4955 V_VT(arg
) = VT_ERROR
;
4956 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4957 arglen
= _argsize(VT_ERROR
);
4958 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4959 if (FAILED(hres
)) goto func_fail
;
4962 if (tdesc
->vt
== VT_PTR
)
4963 arglen
= _argsize(tdesc
->u
.lptdesc
->vt
);
4965 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4967 /* Supply pointers for the rest, so propertyget works*/
4968 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4970 /* If pointer to variant, pass reference it. */
4971 if ((tdesc
->vt
== VT_PTR
) &&
4972 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4975 args
[argspos
]= (DWORD
)pVarResult
;
4980 if (func_desc
->cParamsOpt
< 0)
4981 FIXME("Does not support optional parameters (%d)\n", func_desc
->cParamsOpt
);
4983 res
= _invoke((*(FARPROC
**)pIUnk
)[func_desc
->oVft
/4],
4984 func_desc
->callconv
,
4990 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4991 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
4992 if (wParamFlags
& PARAMFLAG_FRETVAL
) {
4993 ELEMDESC
*elemdesc
= &func_desc
->lprgelemdescParam
[i
];
4994 TYPEDESC
*tdesc
= &elemdesc
->tdesc
;
4995 VARIANTARG varresult
;
4996 V_VT(&varresult
) = 0;
4997 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &V_VT(&varresult
));
5000 /* FIXME: this is really messy - we should keep the
5001 * args in VARIANTARGs rather than a DWORD array */
5002 memcpy(&V_UI4(&varresult
), &args
[i
+1], sizeof(DWORD
));
5005 TRACE("varresult: ");
5006 dump_Variant(&varresult
);
5008 hres
= VariantCopyInd(pVarResult
, &varresult
);
5009 /* free data stored in varresult. Note that
5010 * VariantClear doesn't do what we want because we are
5011 * working with byref types. */
5012 /* FIXME: clear safearrays, bstrs, records and
5013 * variants here too */
5014 if ((V_VT(&varresult
) == (VT_UNKNOWN
| VT_BYREF
)) ||
5015 (V_VT(&varresult
) == (VT_DISPATCH
| VT_BYREF
)))
5016 IUnknown_Release(*V_UNKNOWNREF(&varresult
));
5022 if ((func_desc
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
) && FAILED(res
)) {
5023 WARN("invoked function failed with error 0x%08lx\n", res
);
5024 hres
= DISP_E_EXCEPTION
;
5025 if (pExcepInfo
) pExcepInfo
->scode
= res
;
5028 HeapFree(GetProcessHeap(), 0, rgvarg
);
5029 HeapFree(GetProcessHeap(),0,args2
);
5030 HeapFree(GetProcessHeap(),0,args
);
5033 case FUNC_DISPATCH
: {
5036 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
5037 if (SUCCEEDED(hres
)) {
5038 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5039 hres
= IDispatch_Invoke(
5040 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
5041 pVarResult
,pExcepInfo
,pArgErr
5044 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres
);
5045 IDispatch_Release(disp
);
5047 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5051 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
5056 ITypeInfo2_ReleaseFuncDesc(iface
, func_desc
);
5059 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
5062 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
5063 if(FAILED(hres
)) return hres
;
5065 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5066 dump_VARDESC(var_desc
);
5067 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
5071 /* not found, look for it in inherited interfaces */
5072 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
5073 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
5075 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface
, 0, &ref_type
))) {
5076 /* recursive search */
5078 hres
= ITypeInfo_GetRefTypeInfo(iface
, ref_type
, &pTInfo
);
5079 if(SUCCEEDED(hres
)){
5080 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
5081 ITypeInfo_Release(pTInfo
);
5084 WARN("Could not search inherited interface!\n");
5087 ERR("did not find member id %08lx, flags %d!\n", memid
, dwFlags
);
5088 return DISP_E_MEMBERNOTFOUND
;
5091 /* ITypeInfo::GetDocumentation
5093 * Retrieves the documentation string, the complete Help file name and path,
5094 * and the context ID for the Help topic for a specified type description.
5096 * (Can be tested by the Visual Basic Editor in Word for instance.)
5098 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
5099 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
5100 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
5102 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5103 TLBFuncDesc
* pFDesc
;
5104 TLBVarDesc
* pVDesc
;
5105 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5106 " HelpContext(%p) HelpFile(%p)\n",
5107 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
5108 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5110 *pBstrName
=SysAllocString(This
->Name
);
5112 *pBstrDocString
=SysAllocString(This
->DocString
);
5114 *pdwHelpContext
=This
->dwHelpContext
;
5116 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
5118 }else {/* for a member */
5119 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5120 if(pFDesc
->funcdesc
.memid
==memid
){
5122 *pBstrName
= SysAllocString(pFDesc
->Name
);
5124 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
5126 *pdwHelpContext
=pFDesc
->helpcontext
;
5129 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5130 if(pVDesc
->vardesc
.memid
==memid
){
5132 *pBstrName
= SysAllocString(pVDesc
->Name
);
5134 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
5136 *pdwHelpContext
=pVDesc
->HelpContext
;
5140 WARN("member %ld not found\n", memid
);
5141 return TYPE_E_ELEMENTNOTFOUND
;
5144 /* ITypeInfo::GetDllEntry
5146 * Retrieves a description or specification of an entry point for a function
5149 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5150 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5153 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5154 TLBFuncDesc
*pFDesc
;
5156 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5158 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5159 if(pFDesc
->funcdesc
.memid
==memid
){
5160 dump_TypeInfo(This
);
5161 dump_TLBFuncDescOne(pFDesc
);
5163 /* FIXME: This is wrong, but how do you find that out? */
5165 static const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5166 *pBstrDllName
= SysAllocString(oleaut32W
);
5169 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5171 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5179 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5185 /* ITypeInfo::GetRefTypeInfo
5187 * If a type description references other type descriptions, it retrieves
5188 * the referenced type descriptions.
5190 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5193 ITypeInfo
**ppTInfo
)
5195 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5196 HRESULT result
= E_FAIL
;
5198 if (hRefType
== -1 &&
5199 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5200 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5202 /* when we meet a DUAL dispinterface, we must create the interface
5205 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5208 /* the interface version contains the same information as the dispinterface
5209 * copy the contents of the structs.
5211 *pTypeInfoImpl
= *This
;
5212 pTypeInfoImpl
->ref
= 1;
5214 /* change the type to interface */
5215 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5217 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5219 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
5224 TLBRefType
*pRefType
;
5225 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5226 if(pRefType
->reference
== hRefType
)
5230 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
5231 if(pRefType
&& hRefType
!= -1) {
5232 ITypeLib
*pTLib
= NULL
;
5234 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5236 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5238 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5239 TRACE("typeinfo in imported typelib that is already loaded\n");
5240 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5241 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5244 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5245 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5246 pRefType
->pImpTLInfo
->wVersionMajor
,
5247 pRefType
->pImpTLInfo
->wVersionMinor
,
5248 pRefType
->pImpTLInfo
->lcid
,
5251 if(!SUCCEEDED(result
)) {
5252 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5253 result
=LoadTypeLib(libnam
, &pTLib
);
5254 SysFreeString(libnam
);
5256 if(SUCCEEDED(result
)) {
5257 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5258 ITypeLib2_AddRef(pTLib
);
5262 if(SUCCEEDED(result
)) {
5263 if(pRefType
->index
== TLB_REF_USE_GUID
)
5264 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5268 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5272 ITypeLib2_Release(pTLib
);
5276 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
5277 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5281 /* ITypeInfo::AddressOfMember
5283 * Retrieves the addresses of static functions or variables, such as those
5286 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5287 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5289 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5290 FIXME("(%p) stub!\n", This
);
5294 /* ITypeInfo::CreateInstance
5296 * Creates a new instance of a type that describes a component object class
5299 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
5300 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
5302 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5303 FIXME("(%p) stub!\n", This
);
5307 /* ITypeInfo::GetMops
5309 * Retrieves marshalling information.
5311 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
5314 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5315 FIXME("(%p) stub!\n", This
);
5319 /* ITypeInfo::GetContainingTypeLib
5321 * Retrieves the containing type library and the index of the type description
5322 * within that type library.
5324 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
5325 ITypeLib
* *ppTLib
, UINT
*pIndex
)
5327 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5329 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5331 *pIndex
=This
->index
;
5332 TRACE("returning pIndex=%d\n", *pIndex
);
5336 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
5337 ITypeLib2_AddRef(*ppTLib
);
5338 TRACE("returning ppTLib=%p\n", *ppTLib
);
5344 /* ITypeInfo::ReleaseTypeAttr
5346 * Releases a TYPEATTR previously returned by GetTypeAttr.
5349 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
5350 TYPEATTR
* pTypeAttr
)
5352 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5353 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
5354 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5355 free_deep_typedesc(&pTypeAttr
->tdescAlias
);
5356 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
5359 /* ITypeInfo::ReleaseFuncDesc
5361 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5363 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
5365 FUNCDESC
*pFuncDesc
)
5367 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5368 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
5371 /* ITypeInfo::ReleaseVarDesc
5373 * Releases a VARDESC previously returned by GetVarDesc.
5375 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5378 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5379 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5382 /* ITypeInfo2::GetTypeKind
5384 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5387 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5388 TYPEKIND
*pTypeKind
)
5390 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5391 *pTypeKind
=This
->TypeAttr
.typekind
;
5392 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5396 /* ITypeInfo2::GetTypeFlags
5398 * Returns the type flags without any allocations. This returns a DWORD type
5399 * flag, which expands the type flags without growing the TYPEATTR (type
5403 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5405 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5406 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5407 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5411 /* ITypeInfo2::GetFuncIndexOfMemId
5412 * Binds to a specific member based on a known DISPID, where the member name
5413 * is not known (for example, when binding to a default member).
5416 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5417 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5419 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5420 TLBFuncDesc
*pFuncInfo
;
5424 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
5425 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
5431 result
= TYPE_E_ELEMENTNOTFOUND
;
5433 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5434 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5438 /* TypeInfo2::GetVarIndexOfMemId
5440 * Binds to a specific member based on a known DISPID, where the member name
5441 * is not known (for example, when binding to a default member).
5444 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5445 MEMBERID memid
, UINT
*pVarIndex
)
5447 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5448 TLBVarDesc
*pVarInfo
;
5451 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5452 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5458 result
= TYPE_E_ELEMENTNOTFOUND
;
5460 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5461 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5465 /* ITypeInfo2::GetCustData
5467 * Gets the custom data
5469 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5474 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5475 TLBCustData
*pCData
;
5477 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5478 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5480 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5484 VariantInit( pVarVal
);
5485 VariantCopy( pVarVal
, &pCData
->data
);
5488 return E_INVALIDARG
; /* FIXME: correct? */
5491 /* ITypeInfo2::GetFuncCustData
5493 * Gets the custom data
5495 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5501 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5502 TLBCustData
*pCData
=NULL
;
5503 TLBFuncDesc
* pFDesc
;
5505 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5506 pFDesc
=pFDesc
->next
);
5509 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5510 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5512 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5515 VariantInit( pVarVal
);
5516 VariantCopy( pVarVal
, &pCData
->data
);
5519 return E_INVALIDARG
; /* FIXME: correct? */
5522 /* ITypeInfo2::GetParamCustData
5524 * Gets the custom data
5526 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5533 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5534 TLBCustData
*pCData
=NULL
;
5535 TLBFuncDesc
* pFDesc
;
5538 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5540 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5541 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5542 pCData
= pCData
->next
)
5543 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5545 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5549 VariantInit( pVarVal
);
5550 VariantCopy( pVarVal
, &pCData
->data
);
5553 return E_INVALIDARG
; /* FIXME: correct? */
5556 /* ITypeInfo2::GetVarCustData
5558 * Gets the custom data
5560 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5566 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5567 TLBCustData
*pCData
=NULL
;
5568 TLBVarDesc
* pVDesc
;
5571 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5575 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5577 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5581 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5585 VariantInit( pVarVal
);
5586 VariantCopy( pVarVal
, &pCData
->data
);
5589 return E_INVALIDARG
; /* FIXME: correct? */
5592 /* ITypeInfo2::GetImplCustData
5594 * Gets the custom data
5596 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5602 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5603 TLBCustData
*pCData
=NULL
;
5604 TLBImplType
* pRDesc
;
5607 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5611 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5613 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5617 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5621 VariantInit( pVarVal
);
5622 VariantCopy( pVarVal
, &pCData
->data
);
5625 return E_INVALIDARG
; /* FIXME: correct? */
5628 /* ITypeInfo2::GetDocumentation2
5630 * Retrieves the documentation string, the complete Help file name and path,
5631 * the localization context to use, and the context ID for the library Help
5632 * topic in the Help file.
5635 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5639 BSTR
*pbstrHelpString
,
5640 DWORD
*pdwHelpStringContext
,
5641 BSTR
*pbstrHelpStringDll
)
5643 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5644 TLBFuncDesc
* pFDesc
;
5645 TLBVarDesc
* pVDesc
;
5646 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5647 "HelpStringContext(%p) HelpStringDll(%p)\n",
5648 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5649 pbstrHelpStringDll
);
5650 /* the help string should be obtained from the helpstringdll,
5651 * using the _DLLGetDocumentation function, based on the supplied
5652 * lcid. Nice to do sometime...
5654 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5656 *pbstrHelpString
=SysAllocString(This
->Name
);
5657 if(pdwHelpStringContext
)
5658 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5659 if(pbstrHelpStringDll
)
5660 *pbstrHelpStringDll
=
5661 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5663 }else {/* for a member */
5664 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5665 if(pFDesc
->funcdesc
.memid
==memid
){
5667 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5668 if(pdwHelpStringContext
)
5669 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5670 if(pbstrHelpStringDll
)
5671 *pbstrHelpStringDll
=
5672 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5675 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5676 if(pVDesc
->vardesc
.memid
==memid
){
5678 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5679 if(pdwHelpStringContext
)
5680 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5681 if(pbstrHelpStringDll
)
5682 *pbstrHelpStringDll
=
5683 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5687 return TYPE_E_ELEMENTNOTFOUND
;
5690 /* ITypeInfo2::GetAllCustData
5692 * Gets all custom data items for the Type info.
5695 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5697 CUSTDATA
*pCustData
)
5699 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5700 TLBCustData
*pCData
;
5703 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5705 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5706 if(pCustData
->prgCustData
){
5707 pCustData
->cCustData
=This
->ctCustData
;
5708 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5709 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5710 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5713 ERR(" OUT OF MEMORY! \n");
5714 return E_OUTOFMEMORY
;
5719 /* ITypeInfo2::GetAllFuncCustData
5721 * Gets all custom data items for the specified Function
5724 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5727 CUSTDATA
*pCustData
)
5729 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5730 TLBCustData
*pCData
;
5731 TLBFuncDesc
* pFDesc
;
5733 TRACE("(%p) index %d\n", This
, index
);
5734 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5735 pFDesc
=pFDesc
->next
)
5738 pCustData
->prgCustData
=
5739 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5740 if(pCustData
->prgCustData
){
5741 pCustData
->cCustData
=pFDesc
->ctCustData
;
5742 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5743 pCData
= pCData
->next
){
5744 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5745 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5749 ERR(" OUT OF MEMORY! \n");
5750 return E_OUTOFMEMORY
;
5754 return TYPE_E_ELEMENTNOTFOUND
;
5757 /* ITypeInfo2::GetAllParamCustData
5759 * Gets all custom data items for the Functions
5762 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5763 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5765 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5766 TLBCustData
*pCData
=NULL
;
5767 TLBFuncDesc
* pFDesc
;
5769 TRACE("(%p) index %d\n", This
, indexFunc
);
5770 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5771 pFDesc
=pFDesc
->next
)
5773 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5774 pCustData
->prgCustData
=
5775 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5776 sizeof(CUSTDATAITEM
));
5777 if(pCustData
->prgCustData
){
5778 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5779 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5780 pCData
; i
++, pCData
= pCData
->next
){
5781 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5782 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5786 ERR(" OUT OF MEMORY! \n");
5787 return E_OUTOFMEMORY
;
5791 return TYPE_E_ELEMENTNOTFOUND
;
5794 /* ITypeInfo2::GetAllVarCustData
5796 * Gets all custom data items for the specified Variable
5799 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5800 UINT index
, CUSTDATA
*pCustData
)
5802 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5803 TLBCustData
*pCData
;
5804 TLBVarDesc
* pVDesc
;
5806 TRACE("(%p) index %d\n", This
, index
);
5807 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5808 pVDesc
=pVDesc
->next
)
5811 pCustData
->prgCustData
=
5812 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5813 if(pCustData
->prgCustData
){
5814 pCustData
->cCustData
=pVDesc
->ctCustData
;
5815 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5816 pCData
= pCData
->next
){
5817 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5818 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5822 ERR(" OUT OF MEMORY! \n");
5823 return E_OUTOFMEMORY
;
5827 return TYPE_E_ELEMENTNOTFOUND
;
5830 /* ITypeInfo2::GetAllImplCustData
5832 * Gets all custom data items for the specified implementation type
5835 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5838 CUSTDATA
*pCustData
)
5840 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5841 TLBCustData
*pCData
;
5842 TLBImplType
* pRDesc
;
5844 TRACE("(%p) index %d\n", This
, index
);
5845 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5846 pRDesc
=pRDesc
->next
)
5849 pCustData
->prgCustData
=
5850 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5851 if(pCustData
->prgCustData
){
5852 pCustData
->cCustData
=pRDesc
->ctCustData
;
5853 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5854 pCData
= pCData
->next
){
5855 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5856 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5860 ERR(" OUT OF MEMORY! \n");
5861 return E_OUTOFMEMORY
;
5865 return TYPE_E_ELEMENTNOTFOUND
;
5868 static const ITypeInfo2Vtbl tinfvt
=
5871 ITypeInfo_fnQueryInterface
,
5873 ITypeInfo_fnRelease
,
5875 ITypeInfo_fnGetTypeAttr
,
5876 ITypeInfo_fnGetTypeComp
,
5877 ITypeInfo_fnGetFuncDesc
,
5878 ITypeInfo_fnGetVarDesc
,
5879 ITypeInfo_fnGetNames
,
5880 ITypeInfo_fnGetRefTypeOfImplType
,
5881 ITypeInfo_fnGetImplTypeFlags
,
5882 ITypeInfo_fnGetIDsOfNames
,
5884 ITypeInfo_fnGetDocumentation
,
5885 ITypeInfo_fnGetDllEntry
,
5886 ITypeInfo_fnGetRefTypeInfo
,
5887 ITypeInfo_fnAddressOfMember
,
5888 ITypeInfo_fnCreateInstance
,
5889 ITypeInfo_fnGetMops
,
5890 ITypeInfo_fnGetContainingTypeLib
,
5891 ITypeInfo_fnReleaseTypeAttr
,
5892 ITypeInfo_fnReleaseFuncDesc
,
5893 ITypeInfo_fnReleaseVarDesc
,
5895 ITypeInfo2_fnGetTypeKind
,
5896 ITypeInfo2_fnGetTypeFlags
,
5897 ITypeInfo2_fnGetFuncIndexOfMemId
,
5898 ITypeInfo2_fnGetVarIndexOfMemId
,
5899 ITypeInfo2_fnGetCustData
,
5900 ITypeInfo2_fnGetFuncCustData
,
5901 ITypeInfo2_fnGetParamCustData
,
5902 ITypeInfo2_fnGetVarCustData
,
5903 ITypeInfo2_fnGetImplTypeCustData
,
5904 ITypeInfo2_fnGetDocumentation2
,
5905 ITypeInfo2_fnGetAllCustData
,
5906 ITypeInfo2_fnGetAllFuncCustData
,
5907 ITypeInfo2_fnGetAllParamCustData
,
5908 ITypeInfo2_fnGetAllVarCustData
,
5909 ITypeInfo2_fnGetAllImplTypeCustData
,
5912 /******************************************************************************
5913 * CreateDispTypeInfo [OLEAUT32.31]
5915 * Build type information for an object so it can be called through an
5916 * IDispatch interface.
5919 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5920 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5923 * This call allows an objects methods to be accessed through IDispatch, by
5924 * building an ITypeInfo object that IDispatch can use to call through.
5926 HRESULT WINAPI
CreateDispTypeInfo(
5927 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
5928 LCID lcid
, /* [I] Locale Id */
5929 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
5931 ITypeInfoImpl
*pTIImpl
;
5933 TLBFuncDesc
**ppFuncDesc
;
5935 pTIImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
5936 pTIImpl
->pTypeLib
= NULL
;
5938 pTIImpl
->Name
= NULL
;
5939 pTIImpl
->dwHelpContext
= -1;
5940 memset(&pTIImpl
->TypeAttr
.guid
, 0, sizeof(GUID
));
5941 pTIImpl
->TypeAttr
.lcid
= lcid
;
5942 pTIImpl
->TypeAttr
.typekind
= TKIND_COCLASS
;
5943 pTIImpl
->TypeAttr
.wMajorVerNum
= 0;
5944 pTIImpl
->TypeAttr
.wMinorVerNum
= 0;
5945 pTIImpl
->TypeAttr
.cbAlignment
= 2;
5946 pTIImpl
->TypeAttr
.cbSizeInstance
= -1;
5947 pTIImpl
->TypeAttr
.cbSizeVft
= -1;
5948 pTIImpl
->TypeAttr
.cFuncs
= 0;
5949 pTIImpl
->TypeAttr
.cImplTypes
= 1;
5950 pTIImpl
->TypeAttr
.cVars
= 0;
5951 pTIImpl
->TypeAttr
.wTypeFlags
= 0;
5953 ppFuncDesc
= &pTIImpl
->funclist
;
5954 for(func
= 0; func
< pidata
->cMembers
; func
++) {
5955 METHODDATA
*md
= pidata
->pmethdata
+ func
;
5956 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
5957 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
5958 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
5959 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
5960 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
5961 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
5962 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
5963 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
;
5964 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0; /*??*/
5965 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
5966 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5967 md
->cArgs
* sizeof(ELEMDESC
));
5968 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5969 md
->cArgs
* sizeof(TLBParDesc
));
5970 for(param
= 0; param
< md
->cArgs
; param
++) {
5971 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
5972 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
5974 ppFuncDesc
= &(*ppFuncDesc
)->next
;
5976 *pptinfo
= (ITypeInfo
*)pTIImpl
;
5981 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5983 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
5985 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
5988 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
5990 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
5992 return ITypeInfo_AddRef((ITypeInfo
*)This
);
5995 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
5997 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
5999 return ITypeInfo_Release((ITypeInfo
*)This
);
6002 static HRESULT WINAPI
ITypeComp_fnBind(
6007 ITypeInfo
** ppTInfo
,
6008 DESCKIND
* pDescKind
,
6011 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
6012 TLBFuncDesc
* pFDesc
;
6013 TLBVarDesc
* pVDesc
;
6015 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6017 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
6018 if (pFDesc
->funcdesc
.invkind
& wFlags
)
6019 if (!strcmpW(pFDesc
->Name
, szName
)) {
6025 *pDescKind
= DESCKIND_FUNCDESC
;
6026 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
6027 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6030 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
6032 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
6033 if (!strcmpW(pVDesc
->Name
, szName
)) {
6034 *pDescKind
= DESCKIND_VARDESC
;
6035 pBindPtr
->lpvardesc
= &pVDesc
->vardesc
;
6036 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6042 /* not found, look for it in inherited interfaces */
6043 if (This
->TypeAttr
.cImplTypes
&&
6044 (This
->TypeAttr
.typekind
== TKIND_INTERFACE
|| This
->TypeAttr
.typekind
== TKIND_DISPATCH
)) {
6045 /* recursive search */
6049 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
6052 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
6053 ITypeInfo_Release(pTInfo
);
6057 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
6058 ITypeComp_Release(pTComp
);
6061 WARN("Could not search inherited interface!\n");
6063 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
6064 *pDescKind
= DESCKIND_NONE
;
6065 pBindPtr
->lpfuncdesc
= NULL
;
6067 return DISP_E_MEMBERNOTFOUND
;
6070 static HRESULT WINAPI
ITypeComp_fnBindType(
6074 ITypeInfo
** ppTInfo
,
6075 ITypeComp
** ppTComp
)
6077 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
6079 /* strange behaviour (does nothing) but like the
6082 if (!ppTInfo
|| !ppTComp
)
6091 static const ITypeCompVtbl tcompvt
=
6094 ITypeComp_fnQueryInterface
,
6096 ITypeComp_fnRelease
,
6099 ITypeComp_fnBindType