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 /****************************************************************************
90 * Takes p_iVal (which is in little endian) and returns it
91 * in the host machine's byte order.
93 #ifdef WORDS_BIGENDIAN
94 static WORD
FromLEWord(WORD p_iVal
)
96 return (((p_iVal
& 0x00FF) << 8) |
97 ((p_iVal
& 0xFF00) >> 8));
101 static DWORD
FromLEDWord(DWORD p_iVal
)
103 return (((p_iVal
& 0x000000FF) << 24) |
104 ((p_iVal
& 0x0000FF00) << 8) |
105 ((p_iVal
& 0x00FF0000) >> 8) |
106 ((p_iVal
& 0xFF000000) >> 24));
109 #define FromLEWord(X) (X)
110 #define FromLEDWord(X) (X)
114 /****************************************************************************
117 * Fix byte order in any structure if necessary
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val
, int p_iSize
)
124 p_iSize
/= sizeof(WORD
);
127 *Val
= FromLEWord(*Val
);
134 static void FromLEDWords(void *p_Val
, int p_iSize
)
138 p_iSize
/= sizeof(DWORD
);
141 *Val
= FromLEDWord(*Val
);
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
151 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
152 /* buffer must be at least 60 characters long */
153 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
155 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
156 static const WCHAR VersionFormatW
[] = {'\\','%','u','.','%','u',0};
158 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
159 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
160 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
164 /* get the path of an interface key, in the form "Interface\\<guid>" */
165 /* buffer must be at least 50 characters long */
166 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
168 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
170 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
171 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
175 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
176 /* buffer must be at least 16 characters long */
177 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
179 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
180 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
181 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
183 sprintfW( buffer
, LcidFormatW
, lcid
);
186 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
187 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
189 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
196 /****************************************************************************
197 * QueryPathOfRegTypeLib [OLEAUT32.164]
202 QueryPathOfRegTypeLib(
203 REFGUID guid
, /* [in] referenced guid */
204 WORD wMaj
, /* [in] major version */
205 WORD wMin
, /* [in] minor version */
206 LCID lcid
, /* [in] locale id */
207 LPBSTR path
) /* [out] path of typelib */
213 WCHAR Path
[MAX_PATH
];
217 FIXME("(guid %p,%d,%d,0x%04lx,%p),stub!\n", guid
, wMaj
, wMin
, lcid
, path
);
221 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
223 if (RegOpenKeyW( HKEY_CLASSES_ROOT
, buffer
, &hkey
) != ERROR_SUCCESS
)
225 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
231 DWORD dwPathLen
= sizeof(Path
);
233 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
235 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
239 else if (myLCID
== lcid
)
241 /* try with sub-langid */
242 myLCID
= SUBLANGID(lcid
);
244 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
246 /* try with system langid */
256 *path
= SysAllocString( Path
);
264 /******************************************************************************
265 * CreateTypeLib [OLEAUT32.160] creates a typelib
271 HRESULT WINAPI
CreateTypeLib(
272 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
274 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
277 /******************************************************************************
278 * LoadTypeLib [OLEAUT32.161]
279 * Loads and registers a type library
281 * Docs: OLECHAR FAR* szFile
282 * Docs: iTypeLib FAR* FAR* pptLib
288 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
290 HRESULT WINAPI
LoadTypeLib(
291 const OLECHAR
*szFile
,/* [in] Name of file to load from */
292 ITypeLib
* *pptLib
) /* [out] Pointer to pointer to loaded type library */
294 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
295 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
298 /******************************************************************************
299 * LoadTypeLibEx [OLEAUT32.183]
300 * Loads and optionally registers a type library
306 HRESULT WINAPI
LoadTypeLibEx(
307 LPCOLESTR szFile
, /* [in] Name of file to load from */
308 REGKIND regkind
, /* [in] Specify kind of registration */
309 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
311 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
316 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
319 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
322 /* Look for a trailing '\\' followed by an index */
323 pIndexStr
= strrchrW(szFile
, '\\');
324 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
325 index
= atoiW(pIndexStr
);
326 memcpy(szFileCopy
, szFile
,
327 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
328 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
329 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
331 return TYPE_E_CANTLOADLIBRARY
;
332 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
333 return TYPE_E_CANTLOADLIBRARY
;
335 TRACE("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile
));
336 return TYPE_E_CANTLOADLIBRARY
;
340 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
342 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
347 case REGKIND_DEFAULT
:
348 /* don't register typelibs supplied with full path. Experimentation confirms the following */
350 ((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
351 (szFile
[0] && (szFile
[1] == ':'))) break;
352 /* else fall-through */
354 case REGKIND_REGISTER
:
355 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
357 IUnknown_Release(*pptLib
);
365 TRACE(" returns %08lx\n",res
);
369 /******************************************************************************
370 * LoadRegTypeLib [OLEAUT32.162]
372 HRESULT WINAPI
LoadRegTypeLib(
373 REFGUID rguid
, /* [in] referenced guid */
374 WORD wVerMajor
, /* [in] major version */
375 WORD wVerMinor
, /* [in] minor version */
376 LCID lcid
, /* [in] locale id */
377 ITypeLib
**ppTLib
) /* [out] path of typelib */
380 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
384 res
= LoadTypeLib(bstr
, ppTLib
);
388 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
394 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
395 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
396 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
397 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
398 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
399 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
401 /******************************************************************************
402 * RegisterTypeLib [OLEAUT32.163]
403 * Adds information about a type library to the System Registry
405 * Docs: ITypeLib FAR * ptlib
406 * Docs: OLECHAR FAR* szFullPath
407 * Docs: OLECHAR FAR* szHelpDir
413 HRESULT WINAPI
RegisterTypeLib(
414 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
415 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
416 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
419 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
420 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
421 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
431 if (ptlib
== NULL
|| szFullPath
== NULL
)
434 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
437 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
440 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
441 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
445 /* Set the human-readable name of the typelib */
446 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
448 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
449 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
457 /* Make up the name of the typelib path subkey */
458 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
460 /* Create the typelib path subkey */
461 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
462 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
464 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
465 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
473 /* Create the flags subkey */
474 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
475 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
477 /* FIXME: is %u correct? */
478 static const WCHAR formatW
[] = {'%','u',0};
480 sprintfW(buf
, formatW
, attr
->wLibFlags
);
481 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
482 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
490 /* create the helpdir subkey */
491 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
492 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
494 BOOL freeHelpDir
= FALSE
;
497 /* if we created a new key, and helpDir was null, set the helpdir
498 to the directory which contains the typelib. However,
499 if we just opened an existing key, we leave the helpdir alone */
500 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
501 szHelpDir
= SysAllocString(szFullPath
);
502 pIndexStr
= strrchrW(szHelpDir
, '\\');
509 /* if we have an szHelpDir, set it! */
510 if (szHelpDir
!= NULL
) {
511 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
512 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
518 if (freeHelpDir
) SysFreeString(szHelpDir
);
530 /* register OLE Automation-compatible interfaces for this typelib */
531 types
= ITypeLib_GetTypeInfoCount(ptlib
);
532 for (tidx
=0; tidx
<types
; tidx
++) {
533 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
534 LPOLESTR name
= NULL
;
535 ITypeInfo
*tinfo
= NULL
;
537 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
540 case TKIND_INTERFACE
:
541 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
542 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
546 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
547 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
551 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
556 TYPEATTR
*tattr
= NULL
;
557 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
560 TRACE_(typelib
)("guid=%s, flags=%04x (",
561 debugstr_guid(&tattr
->guid
),
564 if (TRACE_ON(typelib
)) {
565 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
586 * FIXME: The 1 is just here until we implement rpcrt4
587 * stub/proxy handling. Until then it helps IShield
590 if (1 || (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
))
592 if (!(tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) {
593 FIXME("Registering non-oleautomation interface!\n");
596 /* register interface<->typelib coupling */
597 get_interface_key( &tattr
->guid
, keyName
);
598 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
599 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
602 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
603 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
605 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
606 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
607 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
608 (BYTE
*)PSOA
, sizeof PSOA
);
612 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
613 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
614 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
615 (BYTE
*)PSOA
, sizeof PSOA
);
619 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
620 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
623 static const WCHAR fmtver
[] = {'%','u','.','%','u',0 };
624 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
626 StringFromGUID2(&attr
->guid
, buffer
, 40);
627 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
628 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
629 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
630 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
631 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
639 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
642 ITypeInfo_Release(tinfo
);
649 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
655 /******************************************************************************
656 * UnRegisterTypeLib [OLEAUT32.186]
657 * Removes information about a type library from the System Registry
664 HRESULT WINAPI
UnRegisterTypeLib(
665 REFGUID libid
, /* [in] Guid of the library */
666 WORD wVerMajor
, /* [in] major version */
667 WORD wVerMinor
, /* [in] minor version */
668 LCID lcid
, /* [in] locale id */
671 BSTR tlibPath
= NULL
;
674 WCHAR subKeyName
[50];
677 BOOL deleteOtherStuff
;
680 TYPEATTR
* typeAttr
= NULL
;
682 ITypeInfo
* typeInfo
= NULL
;
683 ITypeLib
* typeLib
= NULL
;
686 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
688 /* Create the path to the key */
689 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
691 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
693 TRACE("Unsupported syskind %i\n", syskind
);
694 result
= E_INVALIDARG
;
698 /* get the path to the typelib on disk */
699 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
700 result
= E_INVALIDARG
;
704 /* Try and open the key to the type library. */
705 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != S_OK
) {
706 result
= E_INVALIDARG
;
710 /* Try and load the type library */
711 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
712 result
= TYPE_E_INVALIDSTATE
;
716 /* remove any types registered with this typelib */
717 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
718 for (i
=0; i
<numTypes
; i
++) {
719 /* get the kind of type */
720 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
724 /* skip non-interfaces, and get type info for the type */
725 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
728 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
731 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
735 /* the path to the type */
736 get_interface_key( &typeAttr
->guid
, subKeyName
);
738 /* Delete its bits */
739 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != S_OK
) {
742 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
743 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
744 RegDeleteKeyW(subKey
, TypeLibW
);
747 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
750 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
752 if (typeInfo
) ITypeInfo_Release(typeInfo
);
756 /* Now, delete the type library path subkey */
757 get_lcid_subkey( lcid
, syskind
, subKeyName
);
758 RegDeleteKeyW(key
, subKeyName
);
759 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
760 RegDeleteKeyW(key
, subKeyName
);
762 /* check if there is anything besides the FLAGS/HELPDIR keys.
763 If there is, we don't delete them */
764 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
765 deleteOtherStuff
= TRUE
;
767 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == S_OK
) {
768 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
770 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
771 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
772 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
773 deleteOtherStuff
= FALSE
;
777 /* only delete the other parts of the key if we're absolutely sure */
778 if (deleteOtherStuff
) {
779 RegDeleteKeyW(key
, FLAGSW
);
780 RegDeleteKeyW(key
, HELPDIRW
);
784 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
785 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
786 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
790 if (tlibPath
) SysFreeString(tlibPath
);
791 if (typeLib
) ITypeLib_Release(typeLib
);
792 if (subKey
) RegCloseKey(subKey
);
793 if (key
) RegCloseKey(key
);
797 /*======================= ITypeLib implementation =======================*/
799 typedef struct tagTLBCustData
803 struct tagTLBCustData
* next
;
806 /* data structure for import typelibs */
807 typedef struct tagTLBImpLib
809 int offset
; /* offset in the file (MSFT)
810 offset in nametable (SLTG)
811 just used to identify library while reading
813 GUID guid
; /* libid */
814 BSTR name
; /* name */
816 LCID lcid
; /* lcid of imported typelib */
818 WORD wVersionMajor
; /* major version number */
819 WORD wVersionMinor
; /* minor version number */
821 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
822 NULL if not yet loaded */
823 struct tagTLBImpLib
* next
;
826 /* internal ITypeLib data */
827 typedef struct tagITypeLibImpl
829 ITypeLib2Vtbl
*lpVtbl
;
830 ITypeCompVtbl
*lpVtblTypeComp
;
832 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
834 /* strings can be stored in tlb as multibyte strings BUT they are *always*
835 * exported to the application as a UNICODE string.
841 unsigned long dwHelpContext
;
842 int TypeInfoCount
; /* nr of typeinfo's in librarry */
843 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
844 int ctCustData
; /* number of items in cust data list */
845 TLBCustData
* pCustData
; /* linked list to cust data */
846 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
847 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
848 libary. Only used while read MSFT
851 /* typelibs are cached, keyed by path, so store the linked list info within them */
852 struct tagITypeLibImpl
*next
, *prev
;
856 static struct ITypeLib2Vtbl tlbvt
;
857 static struct ITypeCompVtbl tlbtcvt
;
859 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
860 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
862 /* ITypeLib methods */
863 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
864 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
866 /*======================= ITypeInfo implementation =======================*/
868 /* data for refernced types */
869 typedef struct tagTLBRefType
871 INT index
; /* Type index for internal ref or for external ref
872 it the format is SLTG. -2 indicates to
875 GUID guid
; /* guid of the referenced type */
876 /* if index == TLB_REF_USE_GUID */
878 HREFTYPE reference
; /* The href of this ref */
879 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
880 TLB_REF_INTERNAL for internal refs
881 TLB_REF_NOT_FOUND for broken refs */
883 struct tagTLBRefType
* next
;
886 #define TLB_REF_USE_GUID -2
888 #define TLB_REF_INTERNAL (void*)-2
889 #define TLB_REF_NOT_FOUND (void*)-1
891 /* internal Parameter data */
892 typedef struct tagTLBParDesc
896 TLBCustData
* pCustData
; /* linked list to cust data */
899 /* internal Function data */
900 typedef struct tagTLBFuncDesc
902 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
903 BSTR Name
; /* the name of this function */
904 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
906 int HelpStringContext
;
908 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
910 TLBCustData
* pCustData
; /* linked list to cust data; */
911 struct tagTLBFuncDesc
* next
;
914 /* internal Variable data */
915 typedef struct tagTLBVarDesc
917 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
918 BSTR Name
; /* the name of this variable */
920 int HelpStringContext
; /* FIXME: where? */
923 TLBCustData
* pCustData
;/* linked list to cust data; */
924 struct tagTLBVarDesc
* next
;
927 /* internal implemented interface data */
928 typedef struct tagTLBImplType
930 HREFTYPE hRef
; /* hRef of interface */
931 int implflags
; /* IMPLFLAG_*s */
933 TLBCustData
* pCustData
;/* linked list to custom data; */
934 struct tagTLBImplType
*next
;
937 /* internal TypeInfo data */
938 typedef struct tagITypeInfoImpl
940 ITypeInfo2Vtbl
*lpVtbl
;
941 ITypeCompVtbl
*lpVtblTypeComp
;
943 TYPEATTR TypeAttr
; /* _lots_ of type information. */
944 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
945 int index
; /* index in this typelib; */
946 /* type libs seem to store the doc strings in ascii
947 * so why should we do it in unicode?
951 unsigned long dwHelpContext
;
952 unsigned long dwHelpStringContext
;
955 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
958 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
960 /* Implemented Interfaces */
961 TLBImplType
* impltypelist
;
963 TLBRefType
* reflist
;
965 TLBCustData
* pCustData
; /* linked list to cust data; */
966 struct tagITypeInfoImpl
* next
;
969 static struct ITypeInfo2Vtbl tinfvt
;
970 static struct ITypeCompVtbl tcompvt
;
972 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
974 typedef struct tagTLBContext
976 unsigned int oStart
; /* start of TLB in file */
977 unsigned int pos
; /* current pos */
978 unsigned int length
; /* total length */
979 void *mapping
; /* memory mapping */
980 MSFT_SegDir
* pTblDir
;
981 ITypeLibImpl
* pLibInfo
;
985 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
990 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
991 if (pTD
->vt
& VT_RESERVED
)
992 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
993 if (pTD
->vt
& VT_BYREF
)
994 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
995 if (pTD
->vt
& VT_ARRAY
)
996 szVarType
+= strlen(strcpy(szVarType
, "array of "));
997 if (pTD
->vt
& VT_VECTOR
)
998 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
999 switch(pTD
->vt
& VT_TYPEMASK
) {
1000 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1001 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1002 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1003 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1004 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1005 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1006 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1007 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1008 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1009 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1010 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1011 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1012 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1013 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1014 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1015 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1016 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1017 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1018 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1019 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1020 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
1021 pTD
->u
.hreftype
); break;
1022 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1023 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1025 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1026 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1028 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1029 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1030 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1033 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1037 void dump_ELEMDESC(ELEMDESC
*edesc
) {
1039 dump_TypeDesc(&edesc
->tdesc
,buf
);
1040 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1041 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
1042 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1044 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
1046 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
1047 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1048 MESSAGE("Param %d:\n",i
);
1049 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1051 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1052 switch (funcdesc
->funckind
) {
1053 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1054 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1055 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1056 case FUNC_STATIC
: MESSAGE("static");break;
1057 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1058 default: MESSAGE("unknown");break;
1060 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1061 switch (funcdesc
->invkind
) {
1062 case INVOKE_FUNC
: MESSAGE("func");break;
1063 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1064 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1065 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1067 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1068 switch (funcdesc
->callconv
) {
1069 case CC_CDECL
: MESSAGE("cdecl");break;
1070 case CC_PASCAL
: MESSAGE("pascal");break;
1071 case CC_STDCALL
: MESSAGE("stdcall");break;
1072 case CC_SYSCALL
: MESSAGE("syscall");break;
1075 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1076 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1077 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1079 MESSAGE("\telemdescFunc (return value type):\n");
1080 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1083 void dump_IDLDESC(IDLDESC
*idl
) {
1084 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
1087 static const char * typekind_desc
[] =
1100 void dump_TYPEATTR(TYPEATTR
*tattr
) {
1102 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
1103 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
1104 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
1105 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
1106 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
1107 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
1108 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
1109 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
1110 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
1111 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
1112 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
1113 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
1114 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
1115 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
1116 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
1117 MESSAGE("\ttypedesc: %s\n", buf
);
1118 dump_IDLDESC(&tattr
->idldescType
);
1121 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
1124 if (!TRACE_ON(typelib
))
1126 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1127 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1128 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1131 dump_FUNCDESC(&(pfd
->funcdesc
));
1133 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1134 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1136 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
1140 dump_TLBFuncDescOne(pfd
);
1144 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
1148 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1153 static void dump_TLBImpLib(TLBImpLib
*import
)
1155 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1156 debugstr_w(import
->name
));
1157 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1158 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1161 static void dump_TLBRefType(TLBRefType
* prt
)
1165 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1166 if(prt
->index
== -1)
1167 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1169 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1171 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1172 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1173 TRACE_(typelib
)("in lib\n");
1174 dump_TLBImpLib(prt
->pImpTLInfo
);
1180 static void dump_TLBImplType(TLBImplType
* impl
)
1184 "implementing/inheriting interface hRef = %lx implflags %x\n",
1185 impl
->hRef
, impl
->implflags
);
1190 void dump_Variant(VARIANT
* pvar
)
1194 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1198 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1199 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1201 TRACE(",%p", V_BYREF(pvar
));
1203 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1207 else switch (V_TYPE(pvar
))
1209 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1210 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1211 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1212 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1214 case VT_I4
: TRACE(",%ld", V_I4(pvar
)); break;
1216 case VT_UI4
: TRACE(",%ld", V_UI4(pvar
)); break;
1217 case VT_I8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_I8(pvar
) >> 32),
1218 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1219 case VT_UI8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_UI8(pvar
) >> 32),
1220 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1221 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1222 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1223 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1224 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1225 case VT_CY
: TRACE(",0x%08lx,0x%08lx", V_CY(pvar
).s
.Hi
,
1226 V_CY(pvar
).s
.Lo
); break;
1228 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1229 TRACE(",<invalid>");
1231 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1232 st
.wHour
, st
.wMinute
, st
.wSecond
);
1236 case VT_USERDEFINED
:
1238 case VT_NULL
: break;
1239 default: TRACE(",?"); break;
1245 static void dump_DispParms(DISPPARAMS
* pdp
)
1249 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1251 while (index
< pdp
->cArgs
)
1253 dump_Variant( &pdp
->rgvarg
[index
] );
1258 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1260 TRACE("%p ref=%lu\n", pty
, pty
->ref
);
1261 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1262 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1263 TRACE("fct:%u var:%u impl:%u\n",
1264 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1265 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1266 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1267 dump_TLBFuncDesc(pty
->funclist
);
1268 dump_TLBVarDesc(pty
->varlist
);
1269 dump_TLBImplType(pty
->impltypelist
);
1272 void dump_VARDESC(VARDESC
*v
)
1274 MESSAGE("memid %ld\n",v
->memid
);
1275 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1276 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1277 dump_ELEMDESC(&(v
->elemdescVar
));
1278 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1279 MESSAGE("varkind %d\n",v
->varkind
);
1282 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1284 /* VT_LPWSTR is largest type that */
1285 /* may appear in type description*/
1286 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1287 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1288 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1289 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1290 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1291 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1295 static void TLB_abort()
1299 static void * TLB_Alloc(unsigned size
)
1302 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1304 ERR("cannot allocate memory\n");
1309 static void TLB_Free(void * ptr
)
1311 HeapFree(GetProcessHeap(), 0, ptr
);
1314 /* deep copy a typedesc */
1315 static void copy_typedesc(TYPEDESC
*out
, const TYPEDESC
*in
)
1320 out
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC
));
1321 copy_typedesc(out
->u
.lptdesc
, in
->u
.lptdesc
);
1323 case VT_USERDEFINED
:
1324 out
->u
.hreftype
= in
->u
.hreftype
;
1327 out
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC
) +
1328 (in
->u
.lpadesc
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
1329 copy_typedesc(&out
->u
.lpadesc
->tdescElem
, &in
->u
.lpadesc
->tdescElem
);
1330 out
->u
.lpadesc
->cDims
= in
->u
.lpadesc
->cDims
;
1331 memcpy(out
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->cDims
* sizeof(SAFEARRAYBOUND
));
1338 /* free()s any allocated memory pointed to by the tdesc. NB does not
1339 free the tdesc itself - this is because the tdesc is typically part
1340 of a larger structure */
1341 static void free_deep_typedesc(TYPEDESC
*tdesc
)
1345 free_deep_typedesc(tdesc
->u
.lptdesc
);
1346 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lptdesc
);
1347 tdesc
->u
.lptdesc
= NULL
;
1350 free_deep_typedesc(&tdesc
->u
.lpadesc
->tdescElem
);
1351 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lpadesc
);
1352 tdesc
->u
.lpadesc
= NULL
;
1359 /**********************************************************************
1361 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1364 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1366 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1367 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1369 if (where
!= DO_NOT_SEEK
)
1371 where
+= pcx
->oStart
;
1372 if (where
> pcx
->length
)
1375 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1380 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1381 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1386 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1391 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1392 FromLEDWords(buffer
, ret
);
1397 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1402 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1403 FromLEWords(buffer
, ret
);
1408 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1410 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1411 memset(pGuid
,0, sizeof(GUID
));
1414 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1415 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1416 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1417 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1418 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1421 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1424 MSFT_NameIntro niName
;
1426 WCHAR
* pwstring
= NULL
;
1427 BSTR bstrName
= NULL
;
1429 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1430 pcx
->pTblDir
->pNametab
.offset
+offset
);
1431 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1432 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1433 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1434 name
[niName
.namelen
& 0xff]='\0';
1436 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1439 /* no invalid characters in string */
1442 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1444 /* don't check for invalid character since this has been done previously */
1445 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1447 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1448 lengthInChars
= SysStringLen(bstrName
);
1449 HeapFree(GetProcessHeap(), 0, pwstring
);
1452 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1456 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1463 if(offset
<0) return NULL
;
1464 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1465 if(length
<= 0) return 0;
1466 string
=TLB_Alloc(length
+1);
1467 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1468 string
[length
]='\0';
1470 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1471 string
, -1, NULL
, 0);
1473 /* no invalid characters in string */
1476 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1478 /* don't check for invalid character since this has been done previously */
1479 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1481 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1482 lengthInChars
= SysStringLen(bstr
);
1483 HeapFree(GetProcessHeap(), 0, pwstring
);
1486 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1490 * read a value and fill a VARIANT structure
1492 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1496 TRACE_(typelib
)("\n");
1498 if(offset
<0) { /* data are packed in here */
1499 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1500 V_UNION(pVar
, iVal
) = offset
& 0x3ffffff;
1503 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1504 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1505 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1506 switch (V_VT(pVar
)){
1507 case VT_EMPTY
: /* FIXME: is this right? */
1508 case VT_NULL
: /* FIXME: is this right? */
1509 case VT_I2
: /* this should not happen */
1520 case VT_VOID
: /* FIXME: is this right? */
1528 case VT_DECIMAL
: /* FIXME: is this right? */
1531 /* pointer types with known behaviour */
1534 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1536 FIXME("BSTR length = %d?\n", size
);
1538 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1539 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1540 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1541 /* FIXME: do we need a AtoW conversion here? */
1542 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1543 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1548 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1555 case VT_USERDEFINED
:
1561 case VT_STREAMED_OBJECT
:
1562 case VT_STORED_OBJECT
:
1563 case VT_BLOB_OBJECT
:
1568 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1572 if(size
>0) /* (big|small) endian correct? */
1573 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1577 * create a linked list with custom data
1579 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1585 TRACE_(typelib
)("\n");
1589 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1590 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1591 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1592 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1593 /* add new custom data at head of the list */
1594 pNew
->next
=*ppCustData
;
1596 offset
= entry
.next
;
1601 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1605 pTd
->vt
=type
& VT_TYPEMASK
;
1607 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1609 if(pTd
->vt
== VT_USERDEFINED
)
1610 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1612 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1616 MSFT_DoFuncs(TLBContext
* pcx
,
1621 TLBFuncDesc
** pptfd
)
1624 * member information is stored in a data structure at offset
1625 * indicated by the memoffset field of the typeinfo structure
1626 * There are several distinctive parts.
1627 * the first part starts with a field that holds the total length
1628 * of this (first) part excluding this field. Then follow the records,
1629 * for each member there is one record.
1631 * First entry is always the length of the record (including this
1633 * Rest of the record depends on the type of the member. If there is
1634 * a field indicating the member type (function variable intereface etc)
1635 * I have not found it yet. At this time we depend on the information
1636 * in the type info and the usual order how things are stored.
1638 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1641 * Third is a equal sized array with file offsets to the name entry
1644 * Forth and last (?) part is an array with offsets to the records in the
1645 * first part of this file segment.
1648 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1649 int recoffset
= offset
+ sizeof(INT
);
1652 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1654 TRACE_(typelib
)("\n");
1656 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1658 for ( i
= 0; i
< cFuncs
; i
++ )
1660 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1662 /* name, eventually add to a hash table */
1663 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1664 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1666 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1668 /* read the function information record */
1669 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1673 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1675 /* do the attributes */
1676 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1679 if ( nrattributes
> 0 )
1681 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1683 if ( nrattributes
> 1 )
1685 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1686 pFuncRec
->OptAttr
[1]) ;
1688 if ( nrattributes
> 2 )
1690 if ( pFuncRec
->FKCCIC
& 0x2000 )
1692 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1696 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1697 pFuncRec
->OptAttr
[2]);
1699 if( nrattributes
> 5 )
1701 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1703 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1706 pFuncRec
->OptAttr
[6],
1707 &(*pptfd
)->pCustData
);
1714 /* fill the FuncDesc Structure */
1715 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1716 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1718 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1719 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1720 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1721 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1722 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1723 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1724 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1728 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1731 /* do the parameters/arguments */
1732 if(pFuncRec
->nrargs
)
1735 MSFT_ParameterInfo paraminfo
;
1737 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1738 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1740 (*pptfd
)->pParamDesc
=
1741 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1743 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1744 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1746 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1748 TYPEDESC
* lpArgTypeDesc
= 0;
1752 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1755 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1757 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1759 /* SEEK value = jump to offset,
1760 * from there jump to the end of record,
1761 * go back by (j-1) arguments
1763 MSFT_ReadLEDWords( ¶minfo
,
1764 sizeof(MSFT_ParameterInfo
), pcx
,
1765 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1766 * sizeof(MSFT_ParameterInfo
)));
1768 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1770 while ( lpArgTypeDesc
!= NULL
)
1772 switch ( lpArgTypeDesc
->vt
)
1775 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1779 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1782 case VT_USERDEFINED
:
1783 MSFT_DoRefType(pcx
, pTI
,
1784 lpArgTypeDesc
->u
.hreftype
);
1786 lpArgTypeDesc
= NULL
;
1790 lpArgTypeDesc
= NULL
;
1796 /* parameter is the return value! */
1797 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1799 TYPEDESC
* lpArgTypeDesc
;
1801 (*pptfd
)->funcdesc
.elemdescFunc
=
1802 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1804 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1806 while ( lpArgTypeDesc
!= NULL
)
1808 switch ( lpArgTypeDesc
->vt
)
1811 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1815 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1819 case VT_USERDEFINED
:
1822 lpArgTypeDesc
->u
.hreftype
);
1824 lpArgTypeDesc
= NULL
;
1828 lpArgTypeDesc
= NULL
;
1833 /* second time around */
1834 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1837 (*pptfd
)->pParamDesc
[j
].Name
=
1838 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1841 if ( (PARAMFLAG_FHASDEFAULT
&
1842 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1843 ((pFuncRec
->FKCCIC
) & 0x1000) )
1845 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1847 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1849 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1851 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1852 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1854 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1858 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1861 pFuncRec
->OptAttr
[7+j
],
1862 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1867 /* scode is not used: archaic win16 stuff FIXME: right? */
1868 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1869 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1871 pptfd
= & ((*pptfd
)->next
);
1872 recoffset
+= reclength
;
1876 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1877 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1879 int infolen
, nameoffset
, reclength
;
1881 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1885 TRACE_(typelib
)("\n");
1887 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1888 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1889 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1890 recoffset
+= offset
+sizeof(INT
);
1891 for(i
=0;i
<cVars
;i
++){
1892 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1893 /* name, eventually add to a hash table */
1894 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1895 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1896 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1897 /* read the variable information record */
1898 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1900 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1902 if(reclength
>(6*sizeof(INT
)) )
1903 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1904 if(reclength
>(7*sizeof(INT
)) )
1905 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1906 if(reclength
>(8*sizeof(INT
)) )
1907 if(reclength
>(9*sizeof(INT
)) )
1908 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1909 /* fill the VarDesc Structure */
1910 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1911 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1912 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1913 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1914 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1915 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1916 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1917 if(pVarRec
->VarKind
== VAR_CONST
){
1918 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1919 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1920 pVarRec
->OffsValue
, pcx
);
1922 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1923 pptvd
=&((*pptvd
)->next
);
1924 recoffset
+= reclength
;
1927 /* fill in data for a hreftype (offset). When the refernced type is contained
1928 * in the typelib, it's just an (file) offset in the type info base dir.
1929 * If comes from import, it's an offset+1 in the ImpInfo table
1931 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1935 TLBRefType
**ppRefType
= &pTI
->reflist
;
1937 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1940 if((*ppRefType
)->reference
== offset
)
1942 ppRefType
= &(*ppRefType
)->next
;
1945 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1946 sizeof(**ppRefType
));
1948 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1949 /* external typelib */
1950 MSFT_ImpInfo impinfo
;
1951 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1953 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1955 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1956 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1957 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1958 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1959 pImpLib
=pImpLib
->next
;
1962 (*ppRefType
)->reference
=offset
;
1963 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1964 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1965 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1967 ERR("Cannot find a reference\n");
1968 (*ppRefType
)->reference
=-1;
1969 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1972 /* in this typelib */
1973 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1974 (*ppRefType
)->reference
=offset
;
1975 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1979 /* process Implemented Interfaces of a com class */
1980 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1984 MSFT_RefRecord refrec
;
1985 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1987 TRACE_(typelib
)("\n");
1989 for(i
=0;i
<count
;i
++){
1990 if(offset
<0) break; /* paranoia */
1991 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1992 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1993 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1994 (*ppImpl
)->hRef
= refrec
.reftype
;
1995 (*ppImpl
)->implflags
=refrec
.flags
;
1996 (*ppImpl
)->ctCustData
=
1997 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1998 offset
=refrec
.onext
;
1999 ppImpl
=&((*ppImpl
)->next
);
2003 * process a typeinfo record
2005 ITypeInfoImpl
* MSFT_DoTypeInfo(
2008 ITypeLibImpl
* pLibInfo
)
2010 MSFT_TypeInfoBase tiBase
;
2011 ITypeInfoImpl
*ptiRet
;
2013 TRACE_(typelib
)("count=%u\n", count
);
2015 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2016 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2017 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2018 /* this is where we are coming from */
2019 ptiRet
->pTypeLib
= pLibInfo
;
2020 ptiRet
->index
=count
;
2021 /* fill in the typeattr fields */
2022 WARN("Assign constructor/destructor memid\n");
2024 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2025 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2026 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
2027 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
2028 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2029 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2030 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2031 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2032 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2033 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2034 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2035 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2036 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2037 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2038 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2039 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2040 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2041 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2044 /* IDLDESC idldescType; *//* never saw this one != zero */
2046 /* name, eventually add to a hash table */
2047 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2048 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2050 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2051 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2052 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2053 /* note: InfoType's Help file and HelpStringDll come from the containing
2054 * library. Further HelpString and Docstring appear to be the same thing :(
2057 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2058 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2059 ptiRet
->TypeAttr
.cVars
,
2060 tiBase
.memoffset
, & ptiRet
->funclist
);
2062 if(ptiRet
->TypeAttr
.cVars
>0 )
2063 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2064 ptiRet
->TypeAttr
.cVars
,
2065 tiBase
.memoffset
, & ptiRet
->varlist
);
2066 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2067 switch(ptiRet
->TypeAttr
.typekind
)
2070 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2073 case TKIND_DISPATCH
:
2074 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2076 if (tiBase
.datatype1
!= -1)
2078 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2079 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2082 { /* FIXME: This is a really bad hack to add IDispatch */
2083 const char* szStdOle
= "stdole2.tlb\0";
2084 int nStdOleLen
= strlen(szStdOle
);
2085 TLBRefType
**ppRef
= &ptiRet
->reflist
;
2088 if((*ppRef
)->reference
== -1)
2090 ppRef
= &(*ppRef
)->next
;
2093 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
2094 (*ppRef
)->guid
= IID_IDispatch
;
2095 (*ppRef
)->reference
= -1;
2096 (*ppRef
)->index
= TLB_REF_USE_GUID
;
2097 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
2098 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
2099 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
2102 MultiByteToWideChar(CP_ACP
,
2106 (*ppRef
)->pImpTLInfo
->name
,
2107 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
2109 (*ppRef
)->pImpTLInfo
->lcid
= 0;
2110 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
2111 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
2116 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2117 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2118 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2123 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2125 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2126 debugstr_w(ptiRet
->Name
),
2127 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2128 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2133 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2134 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2135 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2138 static ITypeLibImpl
*tlb_cache_first
;
2139 static CRITICAL_SECTION cache_section
;
2140 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2142 0, 0, &cache_section
,
2143 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2144 0, 0, { 0, (DWORD
)(__FILE__
": typelib loader cache") }
2146 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2149 /****************************************************************************
2152 * find the type of the typelib file and map the typelib resource into
2155 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2156 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2157 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2159 ITypeLibImpl
*entry
;
2160 int ret
= TYPE_E_CANTLOADLIBRARY
;
2161 DWORD dwSignature
= 0;
2164 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2168 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2169 EnterCriticalSection(&cache_section
);
2170 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2172 if (!strcmpiW(entry
->path
, pszFileName
))
2174 TRACE("cache hit\n");
2175 *ppTypeLib
= (ITypeLib2
*)entry
;
2176 ITypeLib_AddRef(*ppTypeLib
);
2177 LeaveCriticalSection(&cache_section
);
2181 LeaveCriticalSection(&cache_section
);
2183 /* check the signature of the file */
2184 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2185 if (INVALID_HANDLE_VALUE
!= hFile
)
2187 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2190 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2193 /* retrieve file size */
2194 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2196 /* first try to load as *.tlb */
2197 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2198 if ( dwSignature
== MSFT_SIGNATURE
)
2200 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2202 else if ( dwSignature
== SLTG_SIGNATURE
)
2204 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2206 UnmapViewOfFile(pBase
);
2208 CloseHandle(hMapping
);
2213 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
2215 /* find the typelibrary resource*/
2216 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2217 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2220 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2221 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2224 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2227 LPVOID pBase
= LockResource(hGlobal
);
2228 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2232 /* try to load as incore resource */
2233 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2234 if ( dwSignature
== MSFT_SIGNATURE
)
2236 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2238 else if ( dwSignature
== SLTG_SIGNATURE
)
2240 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2244 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2247 FreeResource( hGlobal
);
2250 FreeLibrary(hinstDLL
);
2255 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2257 TRACE("adding to cache\n");
2258 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2259 lstrcpyW(impl
->path
, pszFileName
);
2260 /* We should really canonicalise the path here. */
2262 /* FIXME: check if it has added already in the meantime */
2263 EnterCriticalSection(&cache_section
);
2264 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2266 tlb_cache_first
= impl
;
2267 LeaveCriticalSection(&cache_section
);
2270 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2275 /*================== ITypeLib(2) Methods ===================================*/
2277 /****************************************************************************
2278 * ITypeLib2_Constructor_MSFT
2280 * loading an MSFT typelib from an in-memory image
2282 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2286 MSFT_Header tlbHeader
;
2287 MSFT_SegDir tlbSegDir
;
2288 ITypeLibImpl
* pTypeLibImpl
;
2290 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2292 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2293 if (!pTypeLibImpl
) return NULL
;
2295 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2296 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2297 pTypeLibImpl
->ref
= 1;
2299 /* get pointer to beginning of typelib data */
2303 cx
.pLibInfo
= pTypeLibImpl
;
2304 cx
.length
= dwTLBLength
;
2307 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2309 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2310 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2311 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2314 /* there is a small amount of information here until the next important
2316 * the segment directory . Try to calculate the amount of data */
2317 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2319 /* now read the segment directory */
2320 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2321 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2322 cx
.pTblDir
= &tlbSegDir
;
2324 /* just check two entries */
2325 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2327 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2328 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2332 /* now fill our internal data */
2333 /* TLIBATTR fields */
2334 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2336 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2337 /* Windows seems to have zero here, is this correct? */
2338 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2339 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2341 pTypeLibImpl
->LibAttr
.lcid
= 0;
2343 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2344 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2345 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2346 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2348 /* name, eventually add to a hash table */
2349 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2352 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2353 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2355 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2358 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2359 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2362 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2365 if(tlbHeader
.CustomDataOffset
>= 0)
2367 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2370 /* fill in typedescriptions */
2371 if(tlbSegDir
.pTypdescTab
.length
> 0)
2373 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2375 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2376 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2379 /* FIXME: add several sanity checks here */
2380 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2381 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2383 /* FIXME: check safearray */
2385 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2387 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2389 else if(td
[0] == VT_CARRAY
)
2391 /* array descr table here */
2392 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2394 else if(td
[0] == VT_USERDEFINED
)
2396 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2398 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2401 /* second time around to fill the array subscript info */
2404 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2405 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2407 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2408 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2411 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2413 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2415 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2417 for(j
= 0; j
<td
[2]; j
++)
2419 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2420 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2421 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2422 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2427 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2428 ERR("didn't find array description data\n");
2433 /* imported type libs */
2434 if(tlbSegDir
.pImpFiles
.offset
>0)
2436 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2437 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2440 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2445 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2446 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2447 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2449 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2450 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2451 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2452 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2455 name
= TLB_Alloc(size
+1);
2456 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2457 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2458 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2459 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2462 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2463 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2465 ppImpLib
= &(*ppImpLib
)->next
;
2470 if(tlbHeader
.nrtypeinfos
>= 0 )
2472 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2473 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2476 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2478 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2480 ppTI
= &((*ppTI
)->next
);
2481 (pTypeLibImpl
->TypeInfoCount
)++;
2485 TRACE("(%p)\n", pTypeLibImpl
);
2486 return (ITypeLib2
*) pTypeLibImpl
;
2490 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2496 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2497 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2498 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2499 ret
= SysAllocString(nameW
);
2500 HeapFree(GetProcessHeap(), 0, nameW
);
2504 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2510 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2511 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2515 guid
->Data4
[0] = s
>> 8;
2516 guid
->Data4
[1] = s
& 0xff;
2519 for(i
= 0; i
< 6; i
++) {
2520 memcpy(b
, str
+ 24 + 2 * i
, 2);
2521 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2526 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2533 bytelen
= *(WORD
*)ptr
;
2534 if(bytelen
== 0xffff) return 2;
2535 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2536 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2537 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2538 *pBstr
= SysAllocStringLen(nameW
, len
);
2539 HeapFree(GetProcessHeap(), 0, nameW
);
2543 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2548 bytelen
= *(WORD
*)ptr
;
2549 if(bytelen
== 0xffff) return 2;
2550 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2551 memcpy(*str
, ptr
+ 2, bytelen
);
2552 (*str
)[bytelen
] = '\0';
2556 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2558 char *ptr
= pLibBlk
;
2561 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2562 FIXME("libblk magic = %04x\n", w
);
2567 if((w
= *(WORD
*)ptr
) != 0xffff) {
2568 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2573 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2575 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2577 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2580 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2583 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2584 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2586 pTypeLibImpl
->LibAttr
.lcid
= 0;
2589 ptr
+= 4; /* skip res12 */
2591 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2594 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2597 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2600 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2601 ptr
+= sizeof(GUID
);
2603 return ptr
- (char*)pLibBlk
;
2606 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2609 TYPEDESC
*pTD
= &pElem
->tdesc
;
2611 /* Handle [in/out] first */
2612 if((*pType
& 0xc000) == 0xc000)
2613 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2614 else if(*pType
& 0x8000)
2615 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2616 else if(*pType
& 0x4000)
2617 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2619 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2622 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2625 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2628 if((*pType
& 0xe00) == 0xe00) {
2630 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2632 pTD
= pTD
->u
.lptdesc
;
2634 switch(*pType
& 0x7f) {
2637 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2639 pTD
= pTD
->u
.lptdesc
;
2642 case VT_USERDEFINED
:
2643 pTD
->vt
= VT_USERDEFINED
;
2644 pTD
->u
.hreftype
= *(++pType
) / 4;
2650 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2653 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2655 pTD
->vt
= VT_CARRAY
;
2656 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2658 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2659 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2660 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2661 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2663 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2669 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2673 pTD
->vt
= VT_SAFEARRAY
;
2674 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2676 pTD
= pTD
->u
.lptdesc
;
2680 pTD
->vt
= *pType
& 0x7f;
2690 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2695 TLBRefType
**ppRefType
;
2697 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2698 FIXME("Ref magic = %x\n", pRef
->magic
);
2701 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2703 ppRefType
= &pTI
->reflist
;
2704 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2706 unsigned int lib_offs
, type_num
;
2708 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2709 sizeof(**ppRefType
));
2711 name
+= SLTG_ReadStringA(name
, &refname
);
2712 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2713 FIXME("Can't sscanf ref\n");
2714 if(lib_offs
!= 0xffff) {
2715 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2718 if((*import
)->offset
== lib_offs
)
2720 import
= &(*import
)->next
;
2723 char fname
[MAX_PATH
+1];
2726 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2728 (*import
)->offset
= lib_offs
;
2729 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2731 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2732 &(*import
)->wVersionMajor
,
2733 &(*import
)->wVersionMinor
,
2734 &(*import
)->lcid
, fname
) != 4) {
2735 FIXME("can't sscanf ref %s\n",
2736 pNameTable
+ lib_offs
+ 40);
2738 len
= strlen(fname
);
2739 if(fname
[len
-1] != '#')
2740 FIXME("fname = %s\n", fname
);
2741 fname
[len
-1] = '\0';
2742 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2744 (*ppRefType
)->pImpTLInfo
= *import
;
2745 } else { /* internal ref */
2746 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2748 (*ppRefType
)->reference
= ref
;
2749 (*ppRefType
)->index
= type_num
;
2751 HeapFree(GetProcessHeap(), 0, refname
);
2752 ppRefType
= &(*ppRefType
)->next
;
2754 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2755 FIXME("End of ref block magic = %x\n", *name
);
2756 dump_TLBRefType(pTI
->reflist
);
2759 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2762 SLTG_ImplInfo
*info
;
2763 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2764 /* I don't really get this structure, usually it's 0x16 bytes
2765 long, but iuser.tlb contains some that are 0x18 bytes long.
2766 That's ok because we can use the next ptr to jump to the next
2767 one. But how do we know the length of the last one? The WORD
2768 at offs 0x8 might be the clue. For now I'm just assuming that
2769 the last one is the regular 0x16 bytes. */
2771 info
= (SLTG_ImplInfo
*)pBlk
;
2773 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2774 sizeof(**ppImplType
));
2775 (*ppImplType
)->hRef
= info
->ref
;
2776 (*ppImplType
)->implflags
= info
->impltypeflags
;
2777 pTI
->TypeAttr
.cImplTypes
++;
2778 ppImplType
= &(*ppImplType
)->next
;
2780 if(info
->next
== 0xffff)
2783 FIXME("Interface inheriting more than one interface\n");
2784 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2786 info
++; /* see comment at top of function */
2790 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2793 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2794 SLTG_MemberHeader
*pMemHeader
;
2795 char *pFirstItem
, *pNextItem
;
2797 if(pTIHeader
->href_table
!= 0xffffffff) {
2798 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2803 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2805 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2807 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2808 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2811 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2815 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2818 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2819 SLTG_MemberHeader
*pMemHeader
;
2820 SLTG_Function
*pFunc
;
2821 char *pFirstItem
, *pNextItem
;
2822 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2825 if(pTIHeader
->href_table
!= 0xffffffff) {
2826 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2830 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2832 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2834 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2835 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2838 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2839 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2844 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2845 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2846 FIXME("func magic = %02x\n", pFunc
->magic
);
2849 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2850 sizeof(**ppFuncDesc
));
2851 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2853 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2854 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2855 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2856 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2857 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2858 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2860 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2861 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2863 if(pFunc
->retnextopt
& 0x80)
2864 pType
= &pFunc
->rettype
;
2866 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2869 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2871 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2872 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2873 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2874 (*ppFuncDesc
)->pParamDesc
=
2875 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2876 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2878 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2880 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2881 char *paramName
= pNameTable
+ *pArg
;
2883 /* If arg type follows then paramName points to the 2nd
2884 letter of the name, else the next WORD is an offset to
2885 the arg type and paramName points to the first letter.
2886 So let's take one char off paramName and see if we're
2887 pointing at an alpha-numeric char. However if *pArg is
2888 0xffff or 0xfffe then the param has no name, the former
2889 meaning that the next WORD is the type, the latter
2890 meaning the the next WORD is an offset to the type. */
2895 else if(*pArg
== 0xfffe) {
2899 else if(!isalnum(*(paramName
-1)))
2904 if(HaveOffs
) { /* the next word is an offset to type */
2905 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2906 SLTG_DoType(pType
, pFirstItem
,
2907 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2912 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2913 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2916 /* Are we an optional param ? */
2917 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2918 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2919 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2922 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2923 TLB_MultiByteToBSTR(paramName
);
2927 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2928 if(pFunc
->next
== 0xffff) break;
2930 pTI
->TypeAttr
.cFuncs
= num
;
2931 dump_TLBFuncDesc(pTI
->funclist
);
2932 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2935 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2938 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2939 SLTG_MemberHeader
*pMemHeader
;
2940 SLTG_RecordItem
*pItem
;
2942 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2947 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2949 pFirstItem
= (char*)(pMemHeader
+ 1);
2950 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2951 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2952 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2953 FIXME("record magic = %02x\n", pItem
->magic
);
2956 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2957 sizeof(**ppVarDesc
));
2958 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2959 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2960 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2961 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2963 if(pItem
->typepos
== 0x02)
2964 pType
= &pItem
->type
;
2965 else if(pItem
->typepos
== 0x00)
2966 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2968 FIXME("typepos = %02x\n", pItem
->typepos
);
2972 SLTG_DoType(pType
, pFirstItem
,
2973 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2975 /* FIXME("helpcontext, helpstring\n"); */
2977 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2979 ppVarDesc
= &((*ppVarDesc
)->next
);
2980 if(pItem
->next
== 0xffff) break;
2982 pTI
->TypeAttr
.cVars
= num
;
2983 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2986 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
2989 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2990 SLTG_MemberHeader
*pMemHeader
;
2991 SLTG_AliasItem
*pItem
;
2994 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2995 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
2998 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2999 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
3000 if (pItem
->vt
== 0xffff) {
3001 if (i
<(pMemHeader
->cbExtra
/4-1))
3002 FIXME("Endmarker too early in process alias data!\n");
3006 FIXME("Chain extends over last entry?\n");
3009 if (pItem
->vt
== VT_USERDEFINED
) {
3010 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
3011 /* guessing here ... */
3012 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
3013 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
3016 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
3017 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
3021 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3024 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3027 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3028 SLTG_MemberHeader
*pMemHeader
;
3029 SLTG_AliasItem
*pItem
;
3031 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3032 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3033 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
3034 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
3035 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3038 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3041 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3042 SLTG_MemberHeader
*pMemHeader
;
3043 SLTG_EnumItem
*pItem
;
3045 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3048 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3050 pFirstItem
= (char*)(pMemHeader
+ 1);
3051 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
3052 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
3053 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
3054 FIXME("enumitem magic = %04x\n", pItem
->magic
);
3057 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3058 sizeof(**ppVarDesc
));
3059 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3060 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3061 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3063 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3064 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
3065 *(INT
*)(pItem
->value
+ pFirstItem
);
3066 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
3067 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3068 /* FIXME("helpcontext, helpstring\n"); */
3070 ppVarDesc
= &((*ppVarDesc
)->next
);
3071 if(pItem
->next
== 0xffff) break;
3073 pTI
->TypeAttr
.cVars
= num
;
3074 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3077 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3078 managable copy of it into this */
3091 } SLTG_InternalOtherTypeInfo
;
3093 /****************************************************************************
3094 * ITypeLib2_Constructor_SLTG
3096 * loading a SLTG typelib from an in-memory image
3098 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3100 ITypeLibImpl
*pTypeLibImpl
;
3101 SLTG_Header
*pHeader
;
3102 SLTG_BlkEntry
*pBlkEntry
;
3106 LPVOID pBlk
, pFirstBlk
;
3107 SLTG_LibBlk
*pLibBlk
;
3108 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3109 char *pAfterOTIBlks
= NULL
;
3110 char *pNameTable
, *ptr
;
3113 ITypeInfoImpl
**ppTypeInfoImpl
;
3115 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3117 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
3118 if (!pTypeLibImpl
) return NULL
;
3120 pTypeLibImpl
->lpVtbl
= &tlbvt
;
3121 pTypeLibImpl
->ref
= 1;
3126 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
3127 pHeader
->nrOfFileBlks
);
3128 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3129 FIXME("Header type magic 0x%08lx not supported.\n",
3130 pHeader
->SLTG_magic
);
3134 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3135 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3137 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3138 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3140 /* Next we have a magic block */
3141 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3143 /* Let's see if we're still in sync */
3144 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3145 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3146 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3149 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3150 sizeof(SLTG_DIR_MAGIC
))) {
3151 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3155 pIndex
= (SLTG_Index
*)(pMagic
+1);
3157 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3159 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3161 /* We'll set up a ptr to the main library block, which is the last one. */
3163 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3164 pBlkEntry
[order
].next
!= 0;
3165 order
= pBlkEntry
[order
].next
- 1, i
++) {
3166 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3170 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3172 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3177 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3179 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3180 sizeof(*pOtherTypeInfoBlks
) *
3181 pTypeLibImpl
->TypeInfoCount
);
3184 ptr
= (char*)pLibBlk
+ len
;
3186 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3190 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3192 w
= *(WORD
*)(ptr
+ 2);
3195 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3197 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3198 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3200 w
= *(WORD
*)(ptr
+ 4 + len
);
3202 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3204 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3206 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3207 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3209 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3210 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3211 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3213 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3215 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3218 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3219 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3220 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3221 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3222 len
+= sizeof(SLTG_OtherTypeInfo
);
3226 pAfterOTIBlks
= ptr
;
3228 /* Skip this WORD and get the next DWORD */
3229 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3231 /* Now add this to pLibBLk look at what we're pointing at and
3232 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3233 dust and we should be pointing at the beginning of the name
3236 pNameTable
= (char*)pLibBlk
+ len
;
3238 switch(*(WORD
*)pNameTable
) {
3245 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3249 pNameTable
+= 0x216;
3253 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3255 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3258 /* Hopefully we now have enough ptrs set up to actually read in
3259 some TypeInfos. It's not clear which order to do them in, so
3260 I'll just follow the links along the BlkEntry chain and read
3261 them in in the order in which they're in the file */
3263 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3265 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3266 pBlkEntry
[order
].next
!= 0;
3267 order
= pBlkEntry
[order
].next
- 1, i
++) {
3269 SLTG_TypeInfoHeader
*pTIHeader
;
3270 SLTG_TypeInfoTail
*pTITail
;
3272 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3273 pOtherTypeInfoBlks
[i
].index_name
)) {
3274 FIXME("Index strings don't match\n");
3279 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3280 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3283 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3284 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3285 (*ppTypeInfoImpl
)->index
= i
;
3286 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3287 pOtherTypeInfoBlks
[i
].name_offs
+
3289 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3290 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3292 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3293 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3294 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3295 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3296 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3298 if((pTIHeader
->typeflags1
& 7) != 2)
3299 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3300 if(pTIHeader
->typeflags3
!= 2)
3301 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3303 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3304 debugstr_w((*ppTypeInfoImpl
)->Name
),
3305 typekind_desc
[pTIHeader
->typekind
],
3306 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3307 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3309 switch(pTIHeader
->typekind
) {
3311 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3315 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3318 case TKIND_INTERFACE
:
3319 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3323 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3327 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3328 if (pTITail
->tdescalias_vt
)
3329 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3332 case TKIND_DISPATCH
:
3333 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3337 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3343 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3344 but we've already set those */
3345 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3346 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3347 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3349 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3371 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3372 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3375 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3376 FIXME("Somehow processed %d TypeInfos\n", i
);
3380 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3381 return (ITypeLib2
*)pTypeLibImpl
;
3384 /* ITypeLib::QueryInterface
3386 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3391 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3393 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3396 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3397 IsEqualIID(riid
,&IID_ITypeLib
)||
3398 IsEqualIID(riid
,&IID_ITypeLib2
))
3405 ITypeLib2_AddRef(iface
);
3406 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3409 TRACE("-- Interface: E_NOINTERFACE\n");
3410 return E_NOINTERFACE
;
3415 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3417 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3418 ULONG ref
= InterlockedIncrement(&This
->ref
);
3420 TRACE("(%p)->ref was %lu\n",This
, ref
- 1);
3425 /* ITypeLib::Release
3427 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3429 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3430 ULONG ref
= InterlockedDecrement(&This
->ref
);
3432 TRACE("(%p)->(%lu)\n",This
, ref
);
3436 /* remove cache entry */
3437 TRACE("removing from cache list\n");
3438 EnterCriticalSection(&cache_section
);
3439 if (This
->next
) This
->next
->prev
= This
->prev
;
3440 if (This
->prev
) This
->prev
->next
= This
->next
;
3441 else tlb_cache_first
= This
->next
;
3442 LeaveCriticalSection(&cache_section
);
3444 /* FIXME destroy child objects */
3445 TRACE(" destroying ITypeLib(%p)\n",This
);
3449 SysFreeString(This
->Name
);
3453 if (This
->DocString
)
3455 SysFreeString(This
->DocString
);
3456 This
->DocString
= NULL
;
3461 SysFreeString(This
->HelpFile
);
3462 This
->HelpFile
= NULL
;
3465 if (This
->HelpStringDll
)
3467 SysFreeString(This
->HelpStringDll
);
3468 This
->HelpStringDll
= NULL
;
3471 if (This
->pTypeInfo
) /* can be NULL */
3472 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3473 HeapFree(GetProcessHeap(),0,This
);
3480 /* ITypeLib::GetTypeInfoCount
3482 * Returns the number of type descriptions in the type library
3484 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3486 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3487 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3488 return This
->TypeInfoCount
;
3491 /* ITypeLib::GetTypeInfo
3493 * retrieves the specified type description in the library.
3495 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3498 ITypeInfo
**ppTInfo
)
3502 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3503 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3505 TRACE("(%p)->(index=%d) \n", This
, index
);
3507 if (!ppTInfo
) return E_INVALIDARG
;
3509 /* search element n in list */
3510 for(i
=0; i
< index
; i
++)
3512 pTypeInfo
= pTypeInfo
->next
;
3515 TRACE("-- element not found\n");
3516 return TYPE_E_ELEMENTNOTFOUND
;
3520 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3522 ITypeInfo_AddRef(*ppTInfo
);
3523 TRACE("-- found (%p)\n",*ppTInfo
);
3528 /* ITypeLibs::GetTypeInfoType
3530 * Retrieves the type of a type description.
3532 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3537 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3539 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3541 TRACE("(%p) index %d \n",This
, index
);
3543 if(!pTKind
) return E_INVALIDARG
;
3545 /* search element n in list */
3546 for(i
=0; i
< index
; i
++)
3550 TRACE("-- element not found\n");
3551 return TYPE_E_ELEMENTNOTFOUND
;
3553 pTInfo
= pTInfo
->next
;
3556 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3557 TRACE("-- found Type (%d)\n", *pTKind
);
3561 /* ITypeLib::GetTypeInfoOfGuid
3563 * Retrieves the type description that corresponds to the specified GUID.
3566 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3569 ITypeInfo
**ppTInfo
)
3571 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3572 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3574 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3576 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3578 /* search linked list for guid */
3579 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3581 pTypeInfo
= pTypeInfo
->next
;
3585 /* end of list reached */
3586 TRACE("-- element not found\n");
3587 return TYPE_E_ELEMENTNOTFOUND
;
3591 TRACE("-- found (%p, %s)\n",
3593 debugstr_w(pTypeInfo
->Name
));
3595 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3596 ITypeInfo_AddRef(*ppTInfo
);
3600 /* ITypeLib::GetLibAttr
3602 * Retrieves the structure that contains the library's attributes.
3605 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3607 LPTLIBATTR
*ppTLibAttr
)
3609 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3610 TRACE("(%p)\n",This
);
3611 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3612 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3616 /* ITypeLib::GetTypeComp
3618 * Enables a client compiler to bind to a library's types, variables,
3619 * constants, and global functions.
3622 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3624 ITypeComp
**ppTComp
)
3626 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3628 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3629 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3630 ITypeComp_AddRef(*ppTComp
);
3635 /* ITypeLib::GetDocumentation
3637 * Retrieves the library's documentation string, the complete Help file name
3638 * and path, and the context identifier for the library Help topic in the Help
3641 * On a successful return all non-null BSTR pointers will have been set,
3644 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3648 BSTR
*pBstrDocString
,
3649 DWORD
*pdwHelpContext
,
3650 BSTR
*pBstrHelpFile
)
3652 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3654 HRESULT result
= E_INVALIDARG
;
3659 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3661 pBstrName
, pBstrDocString
,
3662 pdwHelpContext
, pBstrHelpFile
);
3666 /* documentation for the typelib */
3670 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3676 if (This
->DocString
)
3677 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3678 else if (This
->Name
)
3679 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3681 *pBstrDocString
= NULL
;
3685 *pdwHelpContext
= This
->dwHelpContext
;
3690 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3692 *pBstrHelpFile
= NULL
;
3699 /* for a typeinfo */
3700 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3702 if(SUCCEEDED(result
))
3704 result
= ITypeInfo_GetDocumentation(pTInfo
,
3708 pdwHelpContext
, pBstrHelpFile
);
3710 ITypeInfo_Release(pTInfo
);
3715 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3717 if (pBstrName
) SysFreeString (*pBstrName
);
3719 return STG_E_INSUFFICIENTMEMORY
;
3724 * Indicates whether a passed-in string contains the name of a type or member
3725 * described in the library.
3728 static HRESULT WINAPI
ITypeLib2_fnIsName(
3734 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3735 ITypeInfoImpl
*pTInfo
;
3736 TLBFuncDesc
*pFInfo
;
3739 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3741 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3745 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3746 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3747 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3748 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3749 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3750 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3751 goto ITypeLib2_fnIsName_exit
;
3753 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3754 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3759 ITypeLib2_fnIsName_exit
:
3760 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3761 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3766 /* ITypeLib::FindName
3768 * Finds occurrences of a type description in a type library. This may be used
3769 * to quickly verify that a name exists in a type library.
3772 static HRESULT WINAPI
ITypeLib2_fnFindName(
3776 ITypeInfo
**ppTInfo
,
3780 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3781 ITypeInfoImpl
*pTInfo
;
3782 TLBFuncDesc
*pFInfo
;
3786 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3788 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3789 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3790 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3791 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3792 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3793 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3794 goto ITypeLib2_fnFindName_exit
;
3796 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3797 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3799 ITypeLib2_fnFindName_exit
:
3800 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3801 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3804 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3805 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3812 /* ITypeLib::ReleaseTLibAttr
3814 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3817 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3819 TLIBATTR
*pTLibAttr
)
3821 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3822 TRACE("freeing (%p)\n",This
);
3823 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3827 /* ITypeLib2::GetCustData
3829 * gets the custom data
3831 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3836 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3837 TLBCustData
*pCData
;
3839 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3841 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3844 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3848 VariantInit( pVarVal
);
3849 VariantCopy( pVarVal
, &pCData
->data
);
3852 return E_INVALIDARG
; /* FIXME: correct? */
3855 /* ITypeLib2::GetLibStatistics
3857 * Returns statistics about a type library that are required for efficient
3858 * sizing of hash tables.
3861 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3863 ULONG
*pcUniqueNames
,
3864 ULONG
*pcchUniqueNames
)
3866 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3868 FIXME("(%p): stub!\n", This
);
3870 if(pcUniqueNames
) *pcUniqueNames
=1;
3871 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3875 /* ITypeLib2::GetDocumentation2
3877 * Retrieves the library's documentation string, the complete Help file name
3878 * and path, the localization context to use, and the context ID for the
3879 * library Help topic in the Help file.
3882 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3886 BSTR
*pbstrHelpString
,
3887 DWORD
*pdwHelpStringContext
,
3888 BSTR
*pbstrHelpStringDll
)
3890 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3894 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3896 /* the help string should be obtained from the helpstringdll,
3897 * using the _DLLGetDocumentation function, based on the supplied
3898 * lcid. Nice to do sometime...
3902 /* documentation for the typelib */
3904 *pbstrHelpString
=SysAllocString(This
->DocString
);
3905 if(pdwHelpStringContext
)
3906 *pdwHelpStringContext
=This
->dwHelpContext
;
3907 if(pbstrHelpStringDll
)
3908 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3914 /* for a typeinfo */
3915 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3917 if(SUCCEEDED(result
))
3919 ITypeInfo2
* pTInfo2
;
3920 result
= ITypeInfo_QueryInterface(pTInfo
,
3922 (LPVOID
*) &pTInfo2
);
3924 if(SUCCEEDED(result
))
3926 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3930 pdwHelpStringContext
,
3931 pbstrHelpStringDll
);
3933 ITypeInfo2_Release(pTInfo2
);
3936 ITypeInfo_Release(pTInfo
);
3942 /* ITypeLib2::GetAllCustData
3944 * Gets all custom data items for the library.
3947 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3949 CUSTDATA
*pCustData
)
3951 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3952 TLBCustData
*pCData
;
3954 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3955 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3956 if(pCustData
->prgCustData
){
3957 pCustData
->cCustData
=This
->ctCustData
;
3958 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3959 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3960 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3963 ERR(" OUT OF MEMORY! \n");
3964 return E_OUTOFMEMORY
;
3969 static ITypeLib2Vtbl tlbvt
= {
3970 ITypeLib2_fnQueryInterface
,
3972 ITypeLib2_fnRelease
,
3973 ITypeLib2_fnGetTypeInfoCount
,
3974 ITypeLib2_fnGetTypeInfo
,
3975 ITypeLib2_fnGetTypeInfoType
,
3976 ITypeLib2_fnGetTypeInfoOfGuid
,
3977 ITypeLib2_fnGetLibAttr
,
3978 ITypeLib2_fnGetTypeComp
,
3979 ITypeLib2_fnGetDocumentation
,
3981 ITypeLib2_fnFindName
,
3982 ITypeLib2_fnReleaseTLibAttr
,
3984 ITypeLib2_fnGetCustData
,
3985 ITypeLib2_fnGetLibStatistics
,
3986 ITypeLib2_fnGetDocumentation2
,
3987 ITypeLib2_fnGetAllCustData
3991 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
3993 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3995 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
3998 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4000 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4002 return ITypeInfo_AddRef((ITypeInfo
*)This
);
4005 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4007 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4009 return ITypeInfo_Release((ITypeInfo
*)This
);
4012 static HRESULT WINAPI
ITypeLibComp_fnBind(
4017 ITypeInfo
** ppTInfo
,
4018 DESCKIND
* pDescKind
,
4021 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4025 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4029 ITypeInfo
** ppTInfo
,
4030 ITypeComp
** ppTComp
)
4032 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4036 static ITypeCompVtbl tlbtcvt
=
4039 ITypeLibComp_fnQueryInterface
,
4040 ITypeLibComp_fnAddRef
,
4041 ITypeLibComp_fnRelease
,
4043 ITypeLibComp_fnBind
,
4044 ITypeLibComp_fnBindType
4047 /*================== ITypeInfo(2) Methods ===================================*/
4048 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4050 ITypeInfoImpl
* pTypeInfoImpl
;
4052 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4055 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4056 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4057 pTypeInfoImpl
->ref
=1;
4059 TRACE("(%p)\n", pTypeInfoImpl
);
4060 return (ITypeInfo2
*) pTypeInfoImpl
;
4063 /* ITypeInfo::QueryInterface
4065 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4070 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4072 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4075 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4076 IsEqualIID(riid
,&IID_ITypeInfo
)||
4077 IsEqualIID(riid
,&IID_ITypeInfo2
))
4081 ITypeInfo_AddRef(iface
);
4082 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4085 TRACE("-- Interface: E_NOINTERFACE\n");
4086 return E_NOINTERFACE
;
4089 /* ITypeInfo::AddRef
4091 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4093 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4094 ULONG ref
= InterlockedIncrement(&This
->ref
);
4096 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4098 TRACE("(%p)->ref is %lu\n",This
, ref
);
4102 /* ITypeInfo::Release
4104 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4106 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4107 ULONG ref
= InterlockedDecrement(&This
->ref
);
4109 TRACE("(%p)->(%lu)\n",This
, ref
);
4112 /* We don't release ITypeLib when ref=0 becouse
4113 it means that funtion is called by ITypeLi2_Release */
4114 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4116 FIXME("destroy child objects\n");
4118 TRACE("destroying ITypeInfo(%p)\n",This
);
4121 SysFreeString(This
->Name
);
4125 if (This
->DocString
)
4127 SysFreeString(This
->DocString
);
4128 This
->DocString
= 0;
4133 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4136 HeapFree(GetProcessHeap(),0,This
);
4142 /* ITypeInfo::GetTypeAttr
4144 * Retrieves a TYPEATTR structure that contains the attributes of the type
4148 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4149 LPTYPEATTR
*ppTypeAttr
)
4151 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4152 TRACE("(%p)\n",This
);
4153 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr
));
4154 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4156 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
) /* need to deep copy typedesc */
4157 copy_typedesc(&(*ppTypeAttr
)->tdescAlias
, &This
->TypeAttr
.tdescAlias
);
4159 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
&& (*ppTypeAttr
)->wTypeFlags
& TYPEFLAG_FDUAL
) {
4160 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4162 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4163 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4168 /* ITypeInfo::GetTypeComp
4170 * Retrieves the ITypeComp interface for the type description, which enables a
4171 * client compiler to bind to the type description's members.
4174 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4175 ITypeComp
* *ppTComp
)
4177 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4179 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4181 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4182 ITypeComp_AddRef(*ppTComp
);
4186 /* ITypeInfo::GetFuncDesc
4188 * Retrieves the FUNCDESC structure that contains information about a
4189 * specified function.
4192 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4193 LPFUNCDESC
*ppFuncDesc
)
4195 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4197 TLBFuncDesc
* pFDesc
;
4198 TRACE("(%p) index %d\n", This
, index
);
4199 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4202 /* FIXME: must do a copy here */
4203 *ppFuncDesc
=&pFDesc
->funcdesc
;
4206 return E_INVALIDARG
;
4209 /* ITypeInfo::GetVarDesc
4211 * Retrieves a VARDESC structure that describes the specified variable.
4214 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4215 LPVARDESC
*ppVarDesc
)
4217 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4219 TLBVarDesc
* pVDesc
;
4220 TRACE("(%p) index %d\n", This
, index
);
4221 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4224 /* FIXME: must do a copy here */
4225 *ppVarDesc
=&pVDesc
->vardesc
;
4228 return E_INVALIDARG
;
4231 /* ITypeInfo_GetNames
4233 * Retrieves the variable with the specified member ID (or the name of the
4234 * property or method and its parameters) that correspond to the specified
4237 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4238 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4240 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4241 TLBFuncDesc
* pFDesc
;
4242 TLBVarDesc
* pVDesc
;
4244 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4245 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4248 /* function found, now return function and parameter names */
4249 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4252 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4254 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4260 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4263 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4268 if(This
->TypeAttr
.cImplTypes
&&
4269 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4270 /* recursive search */
4273 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4275 if(SUCCEEDED(result
))
4277 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4278 ITypeInfo_Release(pTInfo
);
4281 WARN("Could not search inherited interface!\n");
4285 WARN("no names found\n");
4288 return TYPE_E_ELEMENTNOTFOUND
;
4295 /* ITypeInfo::GetRefTypeOfImplType
4297 * If a type description describes a COM class, it retrieves the type
4298 * description of the implemented interface types. For an interface,
4299 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4303 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4308 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4310 TLBImplType
*pImpl
= This
->impltypelist
;
4312 TRACE("(%p) index %d\n", This
, index
);
4313 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4317 /* only valid on dual interfaces;
4318 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4320 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4322 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4323 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4329 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4330 *pRefType
= pImpl
->hRef
;
4335 /* get element n from linked list */
4336 for(i
=0; pImpl
&& i
<index
; i
++)
4338 pImpl
= pImpl
->next
;
4341 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4343 *pRefType
= pImpl
->hRef
;
4345 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4352 /* ITypeInfo::GetImplTypeFlags
4354 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4355 * or base interface in a type description.
4357 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4358 UINT index
, INT
*pImplTypeFlags
)
4360 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4364 TRACE("(%p) index %d\n", This
, index
);
4365 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4366 i
++, pImpl
=pImpl
->next
)
4368 if(i
==index
&& pImpl
){
4369 *pImplTypeFlags
=pImpl
->implflags
;
4373 return TYPE_E_ELEMENTNOTFOUND
;
4377 * Maps between member names and member IDs, and parameter names and
4380 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4381 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4383 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4384 TLBFuncDesc
* pFDesc
;
4385 TLBVarDesc
* pVDesc
;
4388 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4390 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4392 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4393 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4394 for(i
=1; i
< cNames
; i
++){
4395 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4396 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4398 if( j
<pFDesc
->funcdesc
.cParams
)
4401 ret
=DISP_E_UNKNOWNNAME
;
4406 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4407 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4408 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4412 /* not found, see if this is and interface with an inheritance */
4413 if(This
->TypeAttr
.cImplTypes
&&
4414 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4415 /* recursive search */
4417 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4418 This
->impltypelist
->hRef
, &pTInfo
);
4420 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4421 ITypeInfo_Release(pTInfo
);
4424 WARN("Could not search inherited interface!\n");
4426 WARN("no names found\n");
4427 return DISP_E_UNKNOWNNAME
;
4430 /* ITypeInfo::Invoke
4432 * Invokes a method, or accesses a property of an object, that implements the
4433 * interface described by the type description.
4436 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4439 if (TRACE_ON(ole
)) {
4441 TRACE("Calling %p(",func
);
4442 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4454 res
= func(args
[0]);
4457 res
= func(args
[0],args
[1]);
4460 res
= func(args
[0],args
[1],args
[2]);
4463 res
= func(args
[0],args
[1],args
[2],args
[3]);
4466 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4469 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4472 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4475 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4478 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4481 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
4484 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
4487 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4493 FIXME("unsupported calling convention %d\n",callconv
);
4497 TRACE("returns %08lx\n",res
);
4501 extern int _argsize(DWORD vt
);
4503 /****************************************************************************
4504 * Helper functions for Dispcall / Invoke, which copies one variant
4505 * with target type onto the argument stack.
4508 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4509 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4511 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4515 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4516 memcpy(argpos
,&arg
,sizeof(void*));
4520 if (V_VT(arg
) == vt
) {
4521 memcpy(argpos
, &V_UNION(arg
,lVal
), arglen
);
4525 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4526 memcpy(argpos
, &V_UNION(arg
,parray
), sizeof(SAFEARRAY
*));
4530 if (vt
== VT_VARIANT
) {
4531 memcpy(argpos
, arg
, arglen
);
4534 /* Deref BYREF vars if there is need */
4535 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4536 memcpy(argpos
,(void*)V_UNION(arg
,lVal
), arglen
);
4539 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4540 /* in this context, if the type lib specifies IUnknown*, giving an
4541 IDispatch* is correct; so, don't invoke VariantChangeType */
4542 memcpy(argpos
,&V_UNION(arg
,lVal
), arglen
);
4545 if ((vt
== VT_PTR
) && tdesc
)
4546 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4548 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4549 ITypeInfo
*tinfo2
= NULL
;
4550 TYPEATTR
*tattr
= NULL
;
4553 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4555 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4556 "while coercing from vt 0x%x. Copying 4 byte.\n",
4557 tdesc
->u
.hreftype
,V_VT(arg
));
4558 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4561 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4564 ERR("GetTypeAttr failed\n");
4565 ITypeInfo_Release(tinfo2
);
4568 switch (tattr
->typekind
) {
4570 switch ( V_VT( arg
) ) {
4572 *argpos
= V_UNION(arg
,iVal
);
4576 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4580 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4587 tdesc
= &(tattr
->tdescAlias
);
4588 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4591 case TKIND_INTERFACE
:
4592 if (V_VT(arg
) == VT_DISPATCH
) {
4594 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4595 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4599 hres
=IUnknown_QueryInterface(V_UNION(arg
,pdispVal
),
4600 &IID_IDispatch
,(LPVOID
*)&disp
);
4601 if (SUCCEEDED(hres
)) {
4602 memcpy(argpos
,&disp
,4);
4603 IUnknown_Release(V_UNION(arg
,pdispVal
));
4607 FIXME("Failed to query IDispatch interface from %s while "
4608 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4612 if (V_VT(arg
) == VT_UNKNOWN
) {
4613 memcpy(argpos
, &V_UNION(arg
,punkVal
), 4);
4617 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4618 V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4622 case TKIND_DISPATCH
:
4623 if (V_VT(arg
) == VT_DISPATCH
) {
4624 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4629 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4633 FIXME("TKIND_RECORD unhandled.\n");
4637 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4641 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4642 ITypeInfo_Release(tinfo2
);
4648 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4649 memcpy(argpos
,&V_UNION(&va
,lVal
), arglen
);
4650 FIXME("Should not use VariantChangeType here."
4651 " (conversion from 0x%x -> 0x%x) %08lx\n",
4652 V_VT(arg
), vt
, *argpos
4656 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4660 /***********************************************************************
4661 * DispCallFunc (OLEAUT32.@)
4665 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4666 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4668 int i
, argsize
, argspos
;
4672 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4673 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4675 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4676 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4678 for (i
=0;i
<cActuals
;i
++) {
4679 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4680 dump_Variant(prgpvarg
[i
]);
4681 argsize
+= _argsize(prgvt
[i
]);
4683 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4684 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4686 for (i
=0;i
<cActuals
;i
++) {
4687 VARIANT
*arg
= prgpvarg
[i
];
4688 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4689 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4690 argspos
+= _argsize(prgvt
[i
]);
4693 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4695 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4700 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4701 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4702 FIXME("Method returned %lx\n",hres
);
4704 HeapFree(GetProcessHeap(),0,args
);
4708 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4713 DISPPARAMS
*pDispParams
,
4714 VARIANT
*pVarResult
,
4715 EXCEPINFO
*pExcepInfo
,
4718 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4720 unsigned int func_index
, var_index
;
4724 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4725 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4727 dump_DispParms(pDispParams
);
4729 hres
= ITypeInfo2_GetFuncIndexOfMemId(iface
, memid
, dwFlags
, &func_index
);
4730 if (SUCCEEDED(hres
)) {
4731 FUNCDESC
*func_desc
;
4733 hres
= ITypeInfo2_GetFuncDesc(iface
, func_index
, &func_desc
);
4734 if(FAILED(hres
)) return hres
;
4736 switch (func_desc
->funckind
) {
4737 case FUNC_PUREVIRTUAL
:
4738 case FUNC_VIRTUAL
: {
4740 int numargs
, numargs2
, argspos
, args2pos
;
4741 DWORD
*args
, *args2
;
4742 VARIANT
*rgvarg
= HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT
) * func_desc
->cParams
);
4743 memcpy(rgvarg
,pDispParams
->rgvarg
,sizeof(VARIANT
)*pDispParams
->cArgs
);
4746 numargs
= 1; numargs2
= 0;
4747 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4748 if (i
<pDispParams
->cArgs
)
4749 numargs
+= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4751 numargs
+= 1; /* sizeof(lpvoid) */
4752 numargs2
+= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4756 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4757 args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4759 args
[0] = (DWORD
)pIUnk
;
4760 argspos
= 1; args2pos
= 0;
4761 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4762 int arglen
= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4763 if (i
<pDispParams
->cArgs
) {
4764 VARIANT
*arg
= &rgvarg
[pDispParams
->cArgs
-i
-1];
4765 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4766 USHORT paramFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
4767 if (paramFlags
& PARAMFLAG_FOPT
) {
4768 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4769 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4770 if(V_VT(arg
) == VT_EMPTY
4771 || ((V_VT(arg
) & VT_BYREF
) && !V_BYREF(arg
))) {
4772 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4773 How to determine it? */
4775 if(paramFlags
& PARAMFLAG_FHASDEFAULT
)
4776 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4777 V_VT(arg
) = VT_ERROR
;
4778 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4779 arglen
= _argsize(VT_ERROR
);
4782 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4783 if (FAILED(hres
)) goto func_fail
;
4785 } else if(func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FOPT
) {
4786 VARIANT
*arg
= &rgvarg
[i
];
4787 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4788 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4789 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4790 if(func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4791 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4792 V_VT(arg
) = VT_ERROR
;
4793 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4794 arglen
= _argsize(VT_ERROR
);
4795 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4796 if (FAILED(hres
)) goto func_fail
;
4799 TYPEDESC
*tdesc
= &(func_desc
->lprgelemdescParam
[i
].tdesc
);
4800 if (tdesc
->vt
!= VT_PTR
)
4801 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4802 /*FIXME: give pointers for the rest, so propertyget works*/
4803 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4805 /* If pointer to variant, pass reference it. */
4806 if ((tdesc
->vt
== VT_PTR
) &&
4807 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4810 args
[argspos
]= (DWORD
)pVarResult
;
4815 if (func_desc
->cParamsOpt
< 0)
4816 FIXME("Does not support optional parameters (%d)\n", func_desc
->cParamsOpt
);
4818 res
= _invoke((*(FARPROC
**)pIUnk
)[func_desc
->oVft
/4],
4819 func_desc
->callconv
,
4824 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4826 for (i
= 0; i
< func_desc
->cParams
- pDispParams
->cArgs
; i
++) {
4827 int arglen
= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4828 TYPEDESC
*tdesc
= &(func_desc
->lprgelemdescParam
[i
+ pDispParams
->cArgs
].tdesc
);
4830 i4_tdesc
.vt
= VT_I4
;
4832 /* If we are a pointer to a variant, we are done already */
4833 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4836 VariantInit(pVarResult
);
4837 memcpy(&V_UNION(pVarResult
,intVal
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4839 if (tdesc
->vt
== VT_PTR
)
4840 tdesc
= tdesc
->u
.lptdesc
;
4841 if (tdesc
->vt
== VT_USERDEFINED
) {
4845 hres
= ITypeInfo_GetRefTypeInfo(iface
,tdesc
->u
.hreftype
,&tinfo2
);
4847 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc
->u
.hreftype
);
4850 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4851 switch (tattr
->typekind
) {
4853 /* force the return type to be VT_I4 */
4857 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr
->tdescAlias
.vt
);
4858 tdesc
= &(tattr
->tdescAlias
);
4861 case TKIND_INTERFACE
:
4862 FIXME("TKIND_INTERFACE unhandled.\n");
4864 case TKIND_DISPATCH
:
4865 FIXME("TKIND_DISPATCH unhandled.\n");
4868 FIXME("TKIND_RECORD unhandled.\n");
4871 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4874 ITypeInfo_Release(tinfo2
);
4876 V_VT(pVarResult
) = tdesc
->vt
;
4878 /* HACK: VB5 likes this.
4879 * I do not know why. There is 1 example in MSDN which uses
4880 * this which appears broken (mixes int vals and
4883 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4884 V_VT(pVarResult
) = VT_DISPATCH
;
4885 TRACE("storing into variant:\n");
4886 dump_Variant(pVarResult
);
4891 HeapFree(GetProcessHeap(), 0, rgvarg
);
4892 HeapFree(GetProcessHeap(),0,args2
);
4893 HeapFree(GetProcessHeap(),0,args
);
4896 case FUNC_DISPATCH
: {
4899 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4900 if (SUCCEEDED(hres
)) {
4901 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4902 hres
= IDispatch_Invoke(
4903 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4904 pVarResult
,pExcepInfo
,pArgErr
4907 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres
);
4908 IDispatch_Release(disp
);
4910 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4914 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
4919 ITypeInfo2_ReleaseFuncDesc(iface
, func_desc
);
4922 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
4925 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
4926 if(FAILED(hres
)) return hres
;
4928 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4929 dump_VARDESC(var_desc
);
4930 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
4934 /* not found, look for it in inherited interfaces */
4935 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
4936 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
4938 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface
, 0, &ref_type
))) {
4939 /* recursive search */
4941 hres
= ITypeInfo_GetRefTypeInfo(iface
, ref_type
, &pTInfo
);
4942 if(SUCCEEDED(hres
)){
4943 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4944 ITypeInfo_Release(pTInfo
);
4947 WARN("Could not search inherited interface!\n");
4950 ERR("did not find member id %08lx, flags %d!\n", memid
, dwFlags
);
4951 return DISP_E_MEMBERNOTFOUND
;
4954 /* ITypeInfo::GetDocumentation
4956 * Retrieves the documentation string, the complete Help file name and path,
4957 * and the context ID for the Help topic for a specified type description.
4959 * (Can be tested by the Visual Basic Editor in Word for instance.)
4961 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4962 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4963 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4965 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4966 TLBFuncDesc
* pFDesc
;
4967 TLBVarDesc
* pVDesc
;
4968 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4969 " HelpContext(%p) HelpFile(%p)\n",
4970 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4971 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4973 *pBstrName
=SysAllocString(This
->Name
);
4975 *pBstrDocString
=SysAllocString(This
->DocString
);
4977 *pdwHelpContext
=This
->dwHelpContext
;
4979 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4981 }else {/* for a member */
4982 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4983 if(pFDesc
->funcdesc
.memid
==memid
){
4985 *pBstrName
= SysAllocString(pFDesc
->Name
);
4987 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4989 *pdwHelpContext
=pFDesc
->helpcontext
;
4992 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4993 if(pVDesc
->vardesc
.memid
==memid
){
4995 *pBstrName
= SysAllocString(pVDesc
->Name
);
4997 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
4999 *pdwHelpContext
=pVDesc
->HelpContext
;
5003 return TYPE_E_ELEMENTNOTFOUND
;
5006 /* ITypeInfo::GetDllEntry
5008 * Retrieves a description or specification of an entry point for a function
5011 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5012 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5015 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5016 TLBFuncDesc
*pFDesc
;
5018 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5020 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5021 if(pFDesc
->funcdesc
.memid
==memid
){
5022 dump_TypeInfo(This
);
5023 dump_TLBFuncDescOne(pFDesc
);
5025 /* FIXME: This is wrong, but how do you find that out? */
5027 static const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5028 *pBstrDllName
= SysAllocString(oleaut32W
);
5031 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5033 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5041 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5047 /* ITypeInfo::GetRefTypeInfo
5049 * If a type description references other type descriptions, it retrieves
5050 * the referenced type descriptions.
5052 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5055 ITypeInfo
**ppTInfo
)
5057 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5058 HRESULT result
= E_FAIL
;
5061 if (hRefType
== -1 &&
5062 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5063 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5065 /* when we meet a DUAL dispinterface, we must create the interface
5068 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5071 /* the interface version contains the same information as the dispinterface
5072 * copy the contents of the structs.
5074 *pTypeInfoImpl
= *This
;
5075 pTypeInfoImpl
->ref
= 1;
5077 /* change the type to interface */
5078 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5080 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5082 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
5087 TLBRefType
*pRefType
;
5088 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5089 if(pRefType
->reference
== hRefType
)
5093 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
5094 if(pRefType
&& hRefType
!= -1) {
5095 ITypeLib
*pTLib
= NULL
;
5097 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5099 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5101 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5102 TRACE("typeinfo in imported typelib that is already loaded\n");
5103 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5104 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5107 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5108 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5109 pRefType
->pImpTLInfo
->wVersionMajor
,
5110 pRefType
->pImpTLInfo
->wVersionMinor
,
5111 pRefType
->pImpTLInfo
->lcid
,
5114 if(!SUCCEEDED(result
)) {
5115 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5116 result
=LoadTypeLib(libnam
, &pTLib
);
5117 SysFreeString(libnam
);
5119 if(SUCCEEDED(result
)) {
5120 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5121 ITypeLib2_AddRef(pTLib
);
5125 if(SUCCEEDED(result
)) {
5126 if(pRefType
->index
== TLB_REF_USE_GUID
)
5127 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5131 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5135 ITypeLib2_Release(pTLib
);
5139 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
5140 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5144 /* ITypeInfo::AddressOfMember
5146 * Retrieves the addresses of static functions or variables, such as those
5149 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5150 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5152 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5153 FIXME("(%p) stub!\n", This
);
5157 /* ITypeInfo::CreateInstance
5159 * Creates a new instance of a type that describes a component object class
5162 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
5163 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
5165 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5166 FIXME("(%p) stub!\n", This
);
5170 /* ITypeInfo::GetMops
5172 * Retrieves marshalling information.
5174 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
5177 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5178 FIXME("(%p) stub!\n", This
);
5182 /* ITypeInfo::GetContainingTypeLib
5184 * Retrieves the containing type library and the index of the type description
5185 * within that type library.
5187 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
5188 ITypeLib
* *ppTLib
, UINT
*pIndex
)
5190 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5192 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5194 *pIndex
=This
->index
;
5195 TRACE("returning pIndex=%d\n", *pIndex
);
5199 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
5200 ITypeLib2_AddRef(*ppTLib
);
5201 TRACE("returning ppTLib=%p\n", *ppTLib
);
5207 /* ITypeInfo::ReleaseTypeAttr
5209 * Releases a TYPEATTR previously returned by GetTypeAttr.
5212 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
5213 TYPEATTR
* pTypeAttr
)
5215 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5216 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
5217 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5218 free_deep_typedesc(&pTypeAttr
->tdescAlias
);
5219 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
5222 /* ITypeInfo::ReleaseFuncDesc
5224 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5226 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
5228 FUNCDESC
*pFuncDesc
)
5230 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5231 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
5234 /* ITypeInfo::ReleaseVarDesc
5236 * Releases a VARDESC previously returned by GetVarDesc.
5238 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5241 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5242 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5245 /* ITypeInfo2::GetTypeKind
5247 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5250 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5251 TYPEKIND
*pTypeKind
)
5253 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5254 *pTypeKind
=This
->TypeAttr
.typekind
;
5255 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5259 /* ITypeInfo2::GetTypeFlags
5261 * Returns the type flags without any allocations. This returns a DWORD type
5262 * flag, which expands the type flags without growing the TYPEATTR (type
5266 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5268 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5269 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5270 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5274 /* ITypeInfo2::GetFuncIndexOfMemId
5275 * Binds to a specific member based on a known DISPID, where the member name
5276 * is not known (for example, when binding to a default member).
5279 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5280 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5282 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5283 TLBFuncDesc
*pFuncInfo
;
5287 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
5288 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
5294 result
= TYPE_E_ELEMENTNOTFOUND
;
5296 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5297 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5301 /* TypeInfo2::GetVarIndexOfMemId
5303 * Binds to a specific member based on a known DISPID, where the member name
5304 * is not known (for example, when binding to a default member).
5307 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5308 MEMBERID memid
, UINT
*pVarIndex
)
5310 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5311 TLBVarDesc
*pVarInfo
;
5314 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5315 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5321 result
= TYPE_E_ELEMENTNOTFOUND
;
5323 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5324 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5328 /* ITypeInfo2::GetCustData
5330 * Gets the custom data
5332 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5337 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5338 TLBCustData
*pCData
;
5340 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5341 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5343 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5347 VariantInit( pVarVal
);
5348 VariantCopy( pVarVal
, &pCData
->data
);
5351 return E_INVALIDARG
; /* FIXME: correct? */
5354 /* ITypeInfo2::GetFuncCustData
5356 * Gets the custom data
5358 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5364 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5365 TLBCustData
*pCData
=NULL
;
5366 TLBFuncDesc
* pFDesc
;
5368 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5369 pFDesc
=pFDesc
->next
);
5372 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5373 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5375 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5378 VariantInit( pVarVal
);
5379 VariantCopy( pVarVal
, &pCData
->data
);
5382 return E_INVALIDARG
; /* FIXME: correct? */
5385 /* ITypeInfo2::GetParamCustData
5387 * Gets the custom data
5389 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5396 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5397 TLBCustData
*pCData
=NULL
;
5398 TLBFuncDesc
* pFDesc
;
5401 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5403 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5404 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5405 pCData
= pCData
->next
)
5406 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5408 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5412 VariantInit( pVarVal
);
5413 VariantCopy( pVarVal
, &pCData
->data
);
5416 return E_INVALIDARG
; /* FIXME: correct? */
5419 /* ITypeInfo2::GetVarCustData
5421 * Gets the custom data
5423 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5429 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5430 TLBCustData
*pCData
=NULL
;
5431 TLBVarDesc
* pVDesc
;
5434 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5438 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5440 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5444 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5448 VariantInit( pVarVal
);
5449 VariantCopy( pVarVal
, &pCData
->data
);
5452 return E_INVALIDARG
; /* FIXME: correct? */
5455 /* ITypeInfo2::GetImplCustData
5457 * Gets the custom data
5459 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5465 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5466 TLBCustData
*pCData
=NULL
;
5467 TLBImplType
* pRDesc
;
5470 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5474 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5476 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::GetDocumentation2
5493 * Retrieves the documentation string, the complete Help file name and path,
5494 * the localization context to use, and the context ID for the library Help
5495 * topic in the Help file.
5498 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5502 BSTR
*pbstrHelpString
,
5503 DWORD
*pdwHelpStringContext
,
5504 BSTR
*pbstrHelpStringDll
)
5506 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5507 TLBFuncDesc
* pFDesc
;
5508 TLBVarDesc
* pVDesc
;
5509 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5510 "HelpStringContext(%p) HelpStringDll(%p)\n",
5511 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5512 pbstrHelpStringDll
);
5513 /* the help string should be obtained from the helpstringdll,
5514 * using the _DLLGetDocumentation function, based on the supplied
5515 * lcid. Nice to do sometime...
5517 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5519 *pbstrHelpString
=SysAllocString(This
->Name
);
5520 if(pdwHelpStringContext
)
5521 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5522 if(pbstrHelpStringDll
)
5523 *pbstrHelpStringDll
=
5524 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5526 }else {/* for a member */
5527 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5528 if(pFDesc
->funcdesc
.memid
==memid
){
5530 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5531 if(pdwHelpStringContext
)
5532 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5533 if(pbstrHelpStringDll
)
5534 *pbstrHelpStringDll
=
5535 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5538 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5539 if(pVDesc
->vardesc
.memid
==memid
){
5541 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5542 if(pdwHelpStringContext
)
5543 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5544 if(pbstrHelpStringDll
)
5545 *pbstrHelpStringDll
=
5546 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5550 return TYPE_E_ELEMENTNOTFOUND
;
5553 /* ITypeInfo2::GetAllCustData
5555 * Gets all custom data items for the Type info.
5558 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5560 CUSTDATA
*pCustData
)
5562 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5563 TLBCustData
*pCData
;
5566 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5568 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5569 if(pCustData
->prgCustData
){
5570 pCustData
->cCustData
=This
->ctCustData
;
5571 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5572 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5573 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5576 ERR(" OUT OF MEMORY! \n");
5577 return E_OUTOFMEMORY
;
5582 /* ITypeInfo2::GetAllFuncCustData
5584 * Gets all custom data items for the specified Function
5587 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5590 CUSTDATA
*pCustData
)
5592 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5593 TLBCustData
*pCData
;
5594 TLBFuncDesc
* pFDesc
;
5596 TRACE("(%p) index %d\n", This
, index
);
5597 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5598 pFDesc
=pFDesc
->next
)
5601 pCustData
->prgCustData
=
5602 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5603 if(pCustData
->prgCustData
){
5604 pCustData
->cCustData
=pFDesc
->ctCustData
;
5605 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5606 pCData
= pCData
->next
){
5607 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5608 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5612 ERR(" OUT OF MEMORY! \n");
5613 return E_OUTOFMEMORY
;
5617 return TYPE_E_ELEMENTNOTFOUND
;
5620 /* ITypeInfo2::GetAllParamCustData
5622 * Gets all custom data items for the Functions
5625 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5626 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5628 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5629 TLBCustData
*pCData
=NULL
;
5630 TLBFuncDesc
* pFDesc
;
5632 TRACE("(%p) index %d\n", This
, indexFunc
);
5633 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5634 pFDesc
=pFDesc
->next
)
5636 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5637 pCustData
->prgCustData
=
5638 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5639 sizeof(CUSTDATAITEM
));
5640 if(pCustData
->prgCustData
){
5641 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5642 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5643 pCData
; i
++, pCData
= pCData
->next
){
5644 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5645 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5649 ERR(" OUT OF MEMORY! \n");
5650 return E_OUTOFMEMORY
;
5654 return TYPE_E_ELEMENTNOTFOUND
;
5657 /* ITypeInfo2::GetAllVarCustData
5659 * Gets all custom data items for the specified Variable
5662 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5663 UINT index
, CUSTDATA
*pCustData
)
5665 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5666 TLBCustData
*pCData
;
5667 TLBVarDesc
* pVDesc
;
5669 TRACE("(%p) index %d\n", This
, index
);
5670 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5671 pVDesc
=pVDesc
->next
)
5674 pCustData
->prgCustData
=
5675 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5676 if(pCustData
->prgCustData
){
5677 pCustData
->cCustData
=pVDesc
->ctCustData
;
5678 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5679 pCData
= pCData
->next
){
5680 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5681 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5685 ERR(" OUT OF MEMORY! \n");
5686 return E_OUTOFMEMORY
;
5690 return TYPE_E_ELEMENTNOTFOUND
;
5693 /* ITypeInfo2::GetAllImplCustData
5695 * Gets all custom data items for the specified implementation type
5698 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5701 CUSTDATA
*pCustData
)
5703 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5704 TLBCustData
*pCData
;
5705 TLBImplType
* pRDesc
;
5707 TRACE("(%p) index %d\n", This
, index
);
5708 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5709 pRDesc
=pRDesc
->next
)
5712 pCustData
->prgCustData
=
5713 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5714 if(pCustData
->prgCustData
){
5715 pCustData
->cCustData
=pRDesc
->ctCustData
;
5716 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5717 pCData
= pCData
->next
){
5718 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5719 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5723 ERR(" OUT OF MEMORY! \n");
5724 return E_OUTOFMEMORY
;
5728 return TYPE_E_ELEMENTNOTFOUND
;
5731 static ITypeInfo2Vtbl tinfvt
=
5734 ITypeInfo_fnQueryInterface
,
5736 ITypeInfo_fnRelease
,
5738 ITypeInfo_fnGetTypeAttr
,
5739 ITypeInfo_fnGetTypeComp
,
5740 ITypeInfo_fnGetFuncDesc
,
5741 ITypeInfo_fnGetVarDesc
,
5742 ITypeInfo_fnGetNames
,
5743 ITypeInfo_fnGetRefTypeOfImplType
,
5744 ITypeInfo_fnGetImplTypeFlags
,
5745 ITypeInfo_fnGetIDsOfNames
,
5747 ITypeInfo_fnGetDocumentation
,
5748 ITypeInfo_fnGetDllEntry
,
5749 ITypeInfo_fnGetRefTypeInfo
,
5750 ITypeInfo_fnAddressOfMember
,
5751 ITypeInfo_fnCreateInstance
,
5752 ITypeInfo_fnGetMops
,
5753 ITypeInfo_fnGetContainingTypeLib
,
5754 ITypeInfo_fnReleaseTypeAttr
,
5755 ITypeInfo_fnReleaseFuncDesc
,
5756 ITypeInfo_fnReleaseVarDesc
,
5758 ITypeInfo2_fnGetTypeKind
,
5759 ITypeInfo2_fnGetTypeFlags
,
5760 ITypeInfo2_fnGetFuncIndexOfMemId
,
5761 ITypeInfo2_fnGetVarIndexOfMemId
,
5762 ITypeInfo2_fnGetCustData
,
5763 ITypeInfo2_fnGetFuncCustData
,
5764 ITypeInfo2_fnGetParamCustData
,
5765 ITypeInfo2_fnGetVarCustData
,
5766 ITypeInfo2_fnGetImplTypeCustData
,
5767 ITypeInfo2_fnGetDocumentation2
,
5768 ITypeInfo2_fnGetAllCustData
,
5769 ITypeInfo2_fnGetAllFuncCustData
,
5770 ITypeInfo2_fnGetAllParamCustData
,
5771 ITypeInfo2_fnGetAllVarCustData
,
5772 ITypeInfo2_fnGetAllImplTypeCustData
,
5775 /******************************************************************************
5776 * CreateDispTypeInfo [OLEAUT32.31]
5778 * Build type information for an object so it can be called through an
5779 * IDispatch interface.
5782 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5783 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5786 * This call allows an objects methods to be accessed through IDispatch, by
5787 * building an ITypeInfo object that IDispatch can use to call through.
5789 HRESULT WINAPI
CreateDispTypeInfo(
5790 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
5791 LCID lcid
, /* [I] Locale Id */
5792 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
5794 ITypeInfoImpl
*pTIImpl
;
5796 TLBFuncDesc
**ppFuncDesc
;
5798 pTIImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
5799 pTIImpl
->pTypeLib
= NULL
;
5801 pTIImpl
->Name
= NULL
;
5802 pTIImpl
->dwHelpContext
= -1;
5803 memset(&pTIImpl
->TypeAttr
.guid
, 0, sizeof(GUID
));
5804 pTIImpl
->TypeAttr
.lcid
= lcid
;
5805 pTIImpl
->TypeAttr
.typekind
= TKIND_COCLASS
;
5806 pTIImpl
->TypeAttr
.wMajorVerNum
= 0;
5807 pTIImpl
->TypeAttr
.wMinorVerNum
= 0;
5808 pTIImpl
->TypeAttr
.cbAlignment
= 2;
5809 pTIImpl
->TypeAttr
.cbSizeInstance
= -1;
5810 pTIImpl
->TypeAttr
.cbSizeVft
= -1;
5811 pTIImpl
->TypeAttr
.cFuncs
= 0;
5812 pTIImpl
->TypeAttr
.cImplTypes
= 1;
5813 pTIImpl
->TypeAttr
.cVars
= 0;
5814 pTIImpl
->TypeAttr
.wTypeFlags
= 0;
5816 ppFuncDesc
= &pTIImpl
->funclist
;
5817 for(func
= 0; func
< pidata
->cMembers
; func
++) {
5818 METHODDATA
*md
= pidata
->pmethdata
+ func
;
5819 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
5820 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
5821 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
5822 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
5823 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
5824 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
5825 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
5826 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
;
5827 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0; /*??*/
5828 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
5829 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5830 md
->cArgs
* sizeof(ELEMDESC
));
5831 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5832 md
->cArgs
* sizeof(TLBParDesc
));
5833 for(param
= 0; param
< md
->cArgs
; param
++) {
5834 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
5835 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
5837 ppFuncDesc
= &(*ppFuncDesc
)->next
;
5839 *pptinfo
= (ITypeInfo
*)pTIImpl
;
5844 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5846 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5848 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
5851 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
5853 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5855 return ITypeInfo_AddRef((ITypeInfo
*)This
);
5858 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
5860 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5862 return ITypeInfo_Release((ITypeInfo
*)This
);
5865 static HRESULT WINAPI
ITypeComp_fnBind(
5870 ITypeInfo
** ppTInfo
,
5871 DESCKIND
* pDescKind
,
5874 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5875 TLBFuncDesc
* pFDesc
;
5876 TLBVarDesc
* pVDesc
;
5878 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5880 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
5881 if (pFDesc
->funcdesc
.invkind
& wFlags
)
5882 if (!strcmpW(pFDesc
->Name
, szName
)) {
5888 *pDescKind
= DESCKIND_FUNCDESC
;
5889 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
5890 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5893 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
5895 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
5896 if (!strcmpW(pVDesc
->Name
, szName
)) {
5897 *pDescKind
= DESCKIND_VARDESC
;
5898 pBindPtr
->lpvardesc
= &pVDesc
->vardesc
;
5899 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5905 /* not found, look for it in inherited interfaces */
5906 if (This
->TypeAttr
.cImplTypes
&&
5907 (This
->TypeAttr
.typekind
== TKIND_INTERFACE
|| This
->TypeAttr
.typekind
== TKIND_DISPATCH
)) {
5908 /* recursive search */
5912 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
5915 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
5916 ITypeInfo_Release(pTInfo
);
5920 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5921 ITypeComp_Release(pTComp
);
5924 WARN("Could not search inherited interface!\n");
5926 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
5927 *pDescKind
= DESCKIND_NONE
;
5928 pBindPtr
->lpfuncdesc
= NULL
;
5930 return DISP_E_MEMBERNOTFOUND
;
5933 static HRESULT WINAPI
ITypeComp_fnBindType(
5937 ITypeInfo
** ppTInfo
,
5938 ITypeComp
** ppTComp
)
5940 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5942 /* strange behaviour (does nothing) but like the
5945 if (!ppTInfo
|| !ppTComp
)
5954 static ITypeCompVtbl tcompvt
=
5957 ITypeComp_fnQueryInterface
,
5959 ITypeComp_fnRelease
,
5962 ITypeComp_fnBindType