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
);
318 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
319 memcpy(szPath
, szFile
, (strlenW(szFile
)+1)*sizeof(WCHAR
));
322 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
325 /* Look for a trailing '\\' followed by an index */
326 pIndexStr
= strrchrW(szFile
, '\\');
327 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
328 index
= atoiW(pIndexStr
);
329 memcpy(szFileCopy
, szFile
,
330 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
331 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
332 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
334 return TYPE_E_CANTLOADLIBRARY
;
335 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
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 and index, so store the linked list info within them */
852 struct tagITypeLibImpl
*next
, *prev
;
857 static struct ITypeLib2Vtbl tlbvt
;
858 static struct ITypeCompVtbl tlbtcvt
;
860 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
861 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
863 /* ITypeLib methods */
864 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
865 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
867 /*======================= ITypeInfo implementation =======================*/
869 /* data for referenced types */
870 typedef struct tagTLBRefType
872 INT index
; /* Type index for internal ref or for external ref
873 it the format is SLTG. -2 indicates to
876 GUID guid
; /* guid of the referenced type */
877 /* if index == TLB_REF_USE_GUID */
879 HREFTYPE reference
; /* The href of this ref */
880 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
881 TLB_REF_INTERNAL for internal refs
882 TLB_REF_NOT_FOUND for broken refs */
884 struct tagTLBRefType
* next
;
887 #define TLB_REF_USE_GUID -2
889 #define TLB_REF_INTERNAL (void*)-2
890 #define TLB_REF_NOT_FOUND (void*)-1
892 /* internal Parameter data */
893 typedef struct tagTLBParDesc
897 TLBCustData
* pCustData
; /* linked list to cust data */
900 /* internal Function data */
901 typedef struct tagTLBFuncDesc
903 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
904 BSTR Name
; /* the name of this function */
905 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
907 int HelpStringContext
;
909 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
911 TLBCustData
* pCustData
; /* linked list to cust data; */
912 struct tagTLBFuncDesc
* next
;
915 /* internal Variable data */
916 typedef struct tagTLBVarDesc
918 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
919 BSTR Name
; /* the name of this variable */
921 int HelpStringContext
; /* FIXME: where? */
924 TLBCustData
* pCustData
;/* linked list to cust data; */
925 struct tagTLBVarDesc
* next
;
928 /* internal implemented interface data */
929 typedef struct tagTLBImplType
931 HREFTYPE hRef
; /* hRef of interface */
932 int implflags
; /* IMPLFLAG_*s */
934 TLBCustData
* pCustData
;/* linked list to custom data; */
935 struct tagTLBImplType
*next
;
938 /* internal TypeInfo data */
939 typedef struct tagITypeInfoImpl
941 ITypeInfo2Vtbl
*lpVtbl
;
942 ITypeCompVtbl
*lpVtblTypeComp
;
944 TYPEATTR TypeAttr
; /* _lots_ of type information. */
945 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
946 int index
; /* index in this typelib; */
947 /* type libs seem to store the doc strings in ascii
948 * so why should we do it in unicode?
952 unsigned long dwHelpContext
;
953 unsigned long dwHelpStringContext
;
956 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
959 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
961 /* Implemented Interfaces */
962 TLBImplType
* impltypelist
;
964 TLBRefType
* reflist
;
966 TLBCustData
* pCustData
; /* linked list to cust data; */
967 struct tagITypeInfoImpl
* next
;
970 static struct ITypeInfo2Vtbl tinfvt
;
971 static struct ITypeCompVtbl tcompvt
;
973 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
975 typedef struct tagTLBContext
977 unsigned int oStart
; /* start of TLB in file */
978 unsigned int pos
; /* current pos */
979 unsigned int length
; /* total length */
980 void *mapping
; /* memory mapping */
981 MSFT_SegDir
* pTblDir
;
982 ITypeLibImpl
* pLibInfo
;
986 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
991 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
992 if (pTD
->vt
& VT_RESERVED
)
993 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
994 if (pTD
->vt
& VT_BYREF
)
995 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
996 if (pTD
->vt
& VT_ARRAY
)
997 szVarType
+= strlen(strcpy(szVarType
, "array of "));
998 if (pTD
->vt
& VT_VECTOR
)
999 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1000 switch(pTD
->vt
& VT_TYPEMASK
) {
1001 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1002 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1003 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1004 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1005 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1006 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1007 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1008 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1009 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1010 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1011 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1012 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1013 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1014 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1015 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1016 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1017 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1018 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1019 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1020 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1021 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
1022 pTD
->u
.hreftype
); break;
1023 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1024 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1026 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1027 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1029 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1030 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1031 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1034 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1038 void dump_ELEMDESC(ELEMDESC
*edesc
) {
1040 dump_TypeDesc(&edesc
->tdesc
,buf
);
1041 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1042 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
1043 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1045 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
1047 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
1048 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1049 MESSAGE("Param %d:\n",i
);
1050 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1052 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1053 switch (funcdesc
->funckind
) {
1054 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1055 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1056 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1057 case FUNC_STATIC
: MESSAGE("static");break;
1058 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1059 default: MESSAGE("unknown");break;
1061 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1062 switch (funcdesc
->invkind
) {
1063 case INVOKE_FUNC
: MESSAGE("func");break;
1064 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1065 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1066 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1068 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1069 switch (funcdesc
->callconv
) {
1070 case CC_CDECL
: MESSAGE("cdecl");break;
1071 case CC_PASCAL
: MESSAGE("pascal");break;
1072 case CC_STDCALL
: MESSAGE("stdcall");break;
1073 case CC_SYSCALL
: MESSAGE("syscall");break;
1076 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1077 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1078 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1080 MESSAGE("\telemdescFunc (return value type):\n");
1081 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1084 void dump_IDLDESC(IDLDESC
*idl
) {
1085 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
1088 static const char * typekind_desc
[] =
1101 void dump_TYPEATTR(TYPEATTR
*tattr
) {
1103 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
1104 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
1105 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
1106 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
1107 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
1108 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
1109 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
1110 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
1111 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
1112 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
1113 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
1114 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
1115 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
1116 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
1117 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
1118 MESSAGE("\ttypedesc: %s\n", buf
);
1119 dump_IDLDESC(&tattr
->idldescType
);
1122 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
1125 if (!TRACE_ON(typelib
))
1127 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1128 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1129 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1132 dump_FUNCDESC(&(pfd
->funcdesc
));
1134 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1135 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1137 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
1141 dump_TLBFuncDescOne(pfd
);
1145 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
1149 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1154 static void dump_TLBImpLib(TLBImpLib
*import
)
1156 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1157 debugstr_w(import
->name
));
1158 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1159 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1162 static void dump_TLBRefType(TLBRefType
* prt
)
1166 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1167 if(prt
->index
== -1)
1168 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1170 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1172 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1173 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1174 TRACE_(typelib
)("in lib\n");
1175 dump_TLBImpLib(prt
->pImpTLInfo
);
1181 static void dump_TLBImplType(TLBImplType
* impl
)
1185 "implementing/inheriting interface hRef = %lx implflags %x\n",
1186 impl
->hRef
, impl
->implflags
);
1191 void dump_Variant(VARIANT
* pvar
)
1195 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1199 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1200 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1202 TRACE(",%p", V_BYREF(pvar
));
1204 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1208 else switch (V_TYPE(pvar
))
1210 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1211 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1212 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1213 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1215 case VT_I4
: TRACE(",%ld", V_I4(pvar
)); break;
1217 case VT_UI4
: TRACE(",%ld", V_UI4(pvar
)); break;
1218 case VT_I8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_I8(pvar
) >> 32),
1219 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1220 case VT_UI8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_UI8(pvar
) >> 32),
1221 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1222 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1223 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1224 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1225 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1226 case VT_CY
: TRACE(",0x%08lx,0x%08lx", V_CY(pvar
).s
.Hi
,
1227 V_CY(pvar
).s
.Lo
); break;
1229 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1230 TRACE(",<invalid>");
1232 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1233 st
.wHour
, st
.wMinute
, st
.wSecond
);
1237 case VT_USERDEFINED
:
1239 case VT_NULL
: break;
1240 default: TRACE(",?"); break;
1246 static void dump_DispParms(DISPPARAMS
* pdp
)
1250 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1252 while (index
< pdp
->cArgs
)
1254 dump_Variant( &pdp
->rgvarg
[index
] );
1259 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1261 TRACE("%p ref=%lu\n", pty
, pty
->ref
);
1262 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1263 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1264 TRACE("fct:%u var:%u impl:%u\n",
1265 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1266 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1267 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1268 dump_TLBFuncDesc(pty
->funclist
);
1269 dump_TLBVarDesc(pty
->varlist
);
1270 dump_TLBImplType(pty
->impltypelist
);
1273 void dump_VARDESC(VARDESC
*v
)
1275 MESSAGE("memid %ld\n",v
->memid
);
1276 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1277 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1278 dump_ELEMDESC(&(v
->elemdescVar
));
1279 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1280 MESSAGE("varkind %d\n",v
->varkind
);
1283 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1285 /* VT_LPWSTR is largest type that */
1286 /* may appear in type description*/
1287 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1288 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1289 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1290 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1291 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1292 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1296 static void TLB_abort()
1300 static void * TLB_Alloc(unsigned size
)
1303 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1305 ERR("cannot allocate memory\n");
1310 static void TLB_Free(void * ptr
)
1312 HeapFree(GetProcessHeap(), 0, ptr
);
1315 /* deep copy a typedesc */
1316 static void copy_typedesc(TYPEDESC
*out
, const TYPEDESC
*in
)
1321 out
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC
));
1322 copy_typedesc(out
->u
.lptdesc
, in
->u
.lptdesc
);
1324 case VT_USERDEFINED
:
1325 out
->u
.hreftype
= in
->u
.hreftype
;
1328 out
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC
) +
1329 (in
->u
.lpadesc
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
1330 copy_typedesc(&out
->u
.lpadesc
->tdescElem
, &in
->u
.lpadesc
->tdescElem
);
1331 out
->u
.lpadesc
->cDims
= in
->u
.lpadesc
->cDims
;
1332 memcpy(out
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->cDims
* sizeof(SAFEARRAYBOUND
));
1339 /* free()s any allocated memory pointed to by the tdesc. NB does not
1340 free the tdesc itself - this is because the tdesc is typically part
1341 of a larger structure */
1342 static void free_deep_typedesc(TYPEDESC
*tdesc
)
1346 free_deep_typedesc(tdesc
->u
.lptdesc
);
1347 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lptdesc
);
1348 tdesc
->u
.lptdesc
= NULL
;
1351 free_deep_typedesc(&tdesc
->u
.lpadesc
->tdescElem
);
1352 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lpadesc
);
1353 tdesc
->u
.lpadesc
= NULL
;
1360 /**********************************************************************
1362 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1365 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1367 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1368 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1370 if (where
!= DO_NOT_SEEK
)
1372 where
+= pcx
->oStart
;
1373 if (where
> pcx
->length
)
1376 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1381 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1382 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1387 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1392 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1393 FromLEDWords(buffer
, ret
);
1398 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1403 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1404 FromLEWords(buffer
, ret
);
1409 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1411 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1412 memset(pGuid
,0, sizeof(GUID
));
1415 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1416 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1417 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1418 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1419 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1422 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1425 MSFT_NameIntro niName
;
1427 WCHAR
* pwstring
= NULL
;
1428 BSTR bstrName
= NULL
;
1430 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1431 pcx
->pTblDir
->pNametab
.offset
+offset
);
1432 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1433 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1434 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1435 name
[niName
.namelen
& 0xff]='\0';
1437 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1440 /* no invalid characters in string */
1443 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1445 /* don't check for invalid character since this has been done previously */
1446 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1448 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1449 lengthInChars
= SysStringLen(bstrName
);
1450 HeapFree(GetProcessHeap(), 0, pwstring
);
1453 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1457 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1464 if(offset
<0) return NULL
;
1465 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1466 if(length
<= 0) return 0;
1467 string
=TLB_Alloc(length
+1);
1468 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1469 string
[length
]='\0';
1471 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1472 string
, -1, NULL
, 0);
1474 /* no invalid characters in string */
1477 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1479 /* don't check for invalid character since this has been done previously */
1480 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1482 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1483 lengthInChars
= SysStringLen(bstr
);
1484 HeapFree(GetProcessHeap(), 0, pwstring
);
1487 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1491 * read a value and fill a VARIANT structure
1493 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1497 TRACE_(typelib
)("\n");
1499 if(offset
<0) { /* data are packed in here */
1500 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1501 V_I2(pVar
) = offset
& 0x3ffffff;
1504 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1505 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1506 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1507 switch (V_VT(pVar
)){
1508 case VT_EMPTY
: /* FIXME: is this right? */
1509 case VT_NULL
: /* FIXME: is this right? */
1510 case VT_I2
: /* this should not happen */
1521 case VT_VOID
: /* FIXME: is this right? */
1529 case VT_DECIMAL
: /* FIXME: is this right? */
1532 /* pointer types with known behaviour */
1535 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1537 FIXME("BSTR length = %d?\n", size
);
1539 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1540 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1541 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1542 /* FIXME: do we need a AtoW conversion here? */
1543 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1544 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1549 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1556 case VT_USERDEFINED
:
1562 case VT_STREAMED_OBJECT
:
1563 case VT_STORED_OBJECT
:
1564 case VT_BLOB_OBJECT
:
1569 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1573 if(size
>0) /* (big|small) endian correct? */
1574 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1578 * create a linked list with custom data
1580 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1586 TRACE_(typelib
)("\n");
1590 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1591 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1592 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1593 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1594 /* add new custom data at head of the list */
1595 pNew
->next
=*ppCustData
;
1597 offset
= entry
.next
;
1602 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1606 pTd
->vt
=type
& VT_TYPEMASK
;
1608 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1610 if(pTd
->vt
== VT_USERDEFINED
)
1611 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1613 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1617 MSFT_DoFuncs(TLBContext
* pcx
,
1622 TLBFuncDesc
** pptfd
)
1625 * member information is stored in a data structure at offset
1626 * indicated by the memoffset field of the typeinfo structure
1627 * There are several distinctive parts.
1628 * the first part starts with a field that holds the total length
1629 * of this (first) part excluding this field. Then follow the records,
1630 * for each member there is one record.
1632 * First entry is always the length of the record (including this
1634 * Rest of the record depends on the type of the member. If there is
1635 * a field indicating the member type (function variable intereface etc)
1636 * I have not found it yet. At this time we depend on the information
1637 * in the type info and the usual order how things are stored.
1639 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1642 * Third is a equal sized array with file offsets to the name entry
1645 * Forth and last (?) part is an array with offsets to the records in the
1646 * first part of this file segment.
1649 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1650 int recoffset
= offset
+ sizeof(INT
);
1653 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1655 TRACE_(typelib
)("\n");
1657 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1659 for ( i
= 0; i
< cFuncs
; i
++ )
1661 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1663 /* name, eventually add to a hash table */
1664 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1665 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1667 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1669 /* read the function information record */
1670 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1674 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1676 /* do the attributes */
1677 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1680 if ( nrattributes
> 0 )
1682 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1684 if ( nrattributes
> 1 )
1686 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1687 pFuncRec
->OptAttr
[1]) ;
1689 if ( nrattributes
> 2 )
1691 if ( pFuncRec
->FKCCIC
& 0x2000 )
1693 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1697 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1698 pFuncRec
->OptAttr
[2]);
1700 if( nrattributes
> 5 )
1702 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1704 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1707 pFuncRec
->OptAttr
[6],
1708 &(*pptfd
)->pCustData
);
1715 /* fill the FuncDesc Structure */
1716 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1717 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1719 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1720 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1721 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1722 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1723 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1724 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1725 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1729 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1732 /* do the parameters/arguments */
1733 if(pFuncRec
->nrargs
)
1736 MSFT_ParameterInfo paraminfo
;
1738 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1739 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1741 (*pptfd
)->pParamDesc
=
1742 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1744 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1745 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1747 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1749 TYPEDESC
* lpArgTypeDesc
= 0;
1753 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1756 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1758 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1760 /* SEEK value = jump to offset,
1761 * from there jump to the end of record,
1762 * go back by (j-1) arguments
1764 MSFT_ReadLEDWords( ¶minfo
,
1765 sizeof(MSFT_ParameterInfo
), pcx
,
1766 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1767 * sizeof(MSFT_ParameterInfo
)));
1769 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1771 while ( lpArgTypeDesc
!= NULL
)
1773 switch ( lpArgTypeDesc
->vt
)
1776 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1780 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1783 case VT_USERDEFINED
:
1784 MSFT_DoRefType(pcx
, pTI
,
1785 lpArgTypeDesc
->u
.hreftype
);
1787 lpArgTypeDesc
= NULL
;
1791 lpArgTypeDesc
= NULL
;
1797 /* parameter is the return value! */
1798 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1800 TYPEDESC
* lpArgTypeDesc
;
1802 (*pptfd
)->funcdesc
.elemdescFunc
=
1803 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1805 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1807 while ( lpArgTypeDesc
!= NULL
)
1809 switch ( lpArgTypeDesc
->vt
)
1812 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1816 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1820 case VT_USERDEFINED
:
1823 lpArgTypeDesc
->u
.hreftype
);
1825 lpArgTypeDesc
= NULL
;
1829 lpArgTypeDesc
= NULL
;
1834 /* second time around */
1835 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1838 (*pptfd
)->pParamDesc
[j
].Name
=
1839 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1842 if ( (PARAMFLAG_FHASDEFAULT
&
1843 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1844 ((pFuncRec
->FKCCIC
) & 0x1000) )
1846 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1848 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1850 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1852 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1853 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1855 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1859 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1862 pFuncRec
->OptAttr
[7+j
],
1863 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1868 /* scode is not used: archaic win16 stuff FIXME: right? */
1869 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1870 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1872 pptfd
= & ((*pptfd
)->next
);
1873 recoffset
+= reclength
;
1877 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1878 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1880 int infolen
, nameoffset
, reclength
;
1882 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1886 TRACE_(typelib
)("\n");
1888 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1889 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1890 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1891 recoffset
+= offset
+sizeof(INT
);
1892 for(i
=0;i
<cVars
;i
++){
1893 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1894 /* name, eventually add to a hash table */
1895 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1896 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1897 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1898 /* read the variable information record */
1899 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1901 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1903 if(reclength
>(6*sizeof(INT
)) )
1904 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1905 if(reclength
>(7*sizeof(INT
)) )
1906 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1907 if(reclength
>(8*sizeof(INT
)) )
1908 if(reclength
>(9*sizeof(INT
)) )
1909 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1910 /* fill the VarDesc Structure */
1911 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1912 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1913 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1914 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1915 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1916 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1917 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1918 if(pVarRec
->VarKind
== VAR_CONST
){
1919 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1920 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1921 pVarRec
->OffsValue
, pcx
);
1923 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1924 pptvd
=&((*pptvd
)->next
);
1925 recoffset
+= reclength
;
1928 /* fill in data for a hreftype (offset). When the referenced type is contained
1929 * in the typelib, it's just an (file) offset in the type info base dir.
1930 * If comes from import, it's an offset+1 in the ImpInfo table
1932 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1936 TLBRefType
**ppRefType
= &pTI
->reflist
;
1938 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1941 if((*ppRefType
)->reference
== offset
)
1943 ppRefType
= &(*ppRefType
)->next
;
1946 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1947 sizeof(**ppRefType
));
1949 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1950 /* external typelib */
1951 MSFT_ImpInfo impinfo
;
1952 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1954 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1956 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1957 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1958 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1959 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1960 pImpLib
=pImpLib
->next
;
1963 (*ppRefType
)->reference
=offset
;
1964 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1965 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1966 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1968 ERR("Cannot find a reference\n");
1969 (*ppRefType
)->reference
=-1;
1970 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1973 /* in this typelib */
1974 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1975 (*ppRefType
)->reference
=offset
;
1976 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1980 /* process Implemented Interfaces of a com class */
1981 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1985 MSFT_RefRecord refrec
;
1986 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1988 TRACE_(typelib
)("\n");
1990 for(i
=0;i
<count
;i
++){
1991 if(offset
<0) break; /* paranoia */
1992 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1993 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1994 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1995 (*ppImpl
)->hRef
= refrec
.reftype
;
1996 (*ppImpl
)->implflags
=refrec
.flags
;
1997 (*ppImpl
)->ctCustData
=
1998 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1999 offset
=refrec
.onext
;
2000 ppImpl
=&((*ppImpl
)->next
);
2004 * process a typeinfo record
2006 ITypeInfoImpl
* MSFT_DoTypeInfo(
2009 ITypeLibImpl
* pLibInfo
)
2011 MSFT_TypeInfoBase tiBase
;
2012 ITypeInfoImpl
*ptiRet
;
2014 TRACE_(typelib
)("count=%u\n", count
);
2016 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2017 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2018 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2019 /* this is where we are coming from */
2020 ptiRet
->pTypeLib
= pLibInfo
;
2021 ptiRet
->index
=count
;
2022 /* fill in the typeattr fields */
2023 WARN("Assign constructor/destructor memid\n");
2025 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2026 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2027 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
2028 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
2029 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2030 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2031 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2032 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2033 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2034 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2035 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2036 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2037 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2038 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2039 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2040 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2041 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2042 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2045 /* IDLDESC idldescType; *//* never saw this one != zero */
2047 /* name, eventually add to a hash table */
2048 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2049 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2051 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2052 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2053 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2054 /* note: InfoType's Help file and HelpStringDll come from the containing
2055 * library. Further HelpString and Docstring appear to be the same thing :(
2058 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2059 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2060 ptiRet
->TypeAttr
.cVars
,
2061 tiBase
.memoffset
, & ptiRet
->funclist
);
2063 if(ptiRet
->TypeAttr
.cVars
>0 )
2064 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2065 ptiRet
->TypeAttr
.cVars
,
2066 tiBase
.memoffset
, & ptiRet
->varlist
);
2067 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2068 switch(ptiRet
->TypeAttr
.typekind
)
2071 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2074 case TKIND_DISPATCH
:
2075 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2077 if (tiBase
.datatype1
!= -1)
2079 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2080 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2083 { /* FIXME: This is a really bad hack to add IDispatch */
2084 const char* szStdOle
= "stdole2.tlb\0";
2085 int nStdOleLen
= strlen(szStdOle
);
2086 TLBRefType
**ppRef
= &ptiRet
->reflist
;
2089 if((*ppRef
)->reference
== -1)
2091 ppRef
= &(*ppRef
)->next
;
2094 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
2095 (*ppRef
)->guid
= IID_IDispatch
;
2096 (*ppRef
)->reference
= -1;
2097 (*ppRef
)->index
= TLB_REF_USE_GUID
;
2098 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
2099 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
2100 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
2103 MultiByteToWideChar(CP_ACP
,
2107 (*ppRef
)->pImpTLInfo
->name
,
2108 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
2110 (*ppRef
)->pImpTLInfo
->lcid
= 0;
2111 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
2112 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
2117 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2118 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2119 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2124 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2126 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2127 debugstr_w(ptiRet
->Name
),
2128 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2129 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2134 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2135 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2136 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2139 static ITypeLibImpl
*tlb_cache_first
;
2140 static CRITICAL_SECTION cache_section
;
2141 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2143 0, 0, &cache_section
,
2144 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2145 0, 0, { 0, (DWORD
)(__FILE__
": typelib loader cache") }
2147 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2150 /****************************************************************************
2153 * find the type of the typelib file and map the typelib resource into
2156 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2157 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2158 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2160 ITypeLibImpl
*entry
;
2161 int ret
= TYPE_E_CANTLOADLIBRARY
;
2162 DWORD dwSignature
= 0;
2165 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2169 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2170 EnterCriticalSection(&cache_section
);
2171 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2173 if (!strcmpiW(entry
->path
, pszFileName
) && entry
->index
== index
)
2175 TRACE("cache hit\n");
2176 *ppTypeLib
= (ITypeLib2
*)entry
;
2177 ITypeLib_AddRef(*ppTypeLib
);
2178 LeaveCriticalSection(&cache_section
);
2182 LeaveCriticalSection(&cache_section
);
2184 /* check the signature of the file */
2185 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2186 if (INVALID_HANDLE_VALUE
!= hFile
)
2188 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2191 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2194 /* retrieve file size */
2195 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2197 /* first try to load as *.tlb */
2198 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2199 if ( dwSignature
== MSFT_SIGNATURE
)
2201 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2203 else if ( dwSignature
== SLTG_SIGNATURE
)
2205 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2207 UnmapViewOfFile(pBase
);
2209 CloseHandle(hMapping
);
2215 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName
));
2218 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2219 if (((WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
) || (dwSignature
== 0))
2221 /* find the typelibrary resource*/
2222 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2223 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2226 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2227 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2230 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2233 LPVOID pBase
= LockResource(hGlobal
);
2234 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2238 /* try to load as incore resource */
2239 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2240 if ( dwSignature
== MSFT_SIGNATURE
)
2242 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2244 else if ( dwSignature
== SLTG_SIGNATURE
)
2246 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2250 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2253 FreeResource( hGlobal
);
2256 FreeLibrary(hinstDLL
);
2261 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2263 TRACE("adding to cache\n");
2264 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2265 lstrcpyW(impl
->path
, pszFileName
);
2266 /* We should really canonicalise the path here. */
2267 impl
->index
= index
;
2269 /* FIXME: check if it has added already in the meantime */
2270 EnterCriticalSection(&cache_section
);
2271 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2273 tlb_cache_first
= impl
;
2274 LeaveCriticalSection(&cache_section
);
2277 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2282 /*================== ITypeLib(2) Methods ===================================*/
2284 /****************************************************************************
2285 * ITypeLib2_Constructor_MSFT
2287 * loading an MSFT typelib from an in-memory image
2289 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2293 MSFT_Header tlbHeader
;
2294 MSFT_SegDir tlbSegDir
;
2295 ITypeLibImpl
* pTypeLibImpl
;
2297 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2299 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2300 if (!pTypeLibImpl
) return NULL
;
2302 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2303 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2304 pTypeLibImpl
->ref
= 1;
2306 /* get pointer to beginning of typelib data */
2310 cx
.pLibInfo
= pTypeLibImpl
;
2311 cx
.length
= dwTLBLength
;
2314 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2316 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2317 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2318 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2321 /* there is a small amount of information here until the next important
2323 * the segment directory . Try to calculate the amount of data */
2324 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2326 /* now read the segment directory */
2327 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2328 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2329 cx
.pTblDir
= &tlbSegDir
;
2331 /* just check two entries */
2332 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2334 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2335 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2339 /* now fill our internal data */
2340 /* TLIBATTR fields */
2341 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2343 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2344 /* Windows seems to have zero here, is this correct? */
2345 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2346 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2348 pTypeLibImpl
->LibAttr
.lcid
= 0;
2350 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2351 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2352 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2353 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2355 /* name, eventually add to a hash table */
2356 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2359 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2360 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2362 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2365 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2366 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2369 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2372 if(tlbHeader
.CustomDataOffset
>= 0)
2374 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2377 /* fill in typedescriptions */
2378 if(tlbSegDir
.pTypdescTab
.length
> 0)
2380 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2382 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2383 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2386 /* FIXME: add several sanity checks here */
2387 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2388 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2390 /* FIXME: check safearray */
2392 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2394 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2396 else if(td
[0] == VT_CARRAY
)
2398 /* array descr table here */
2399 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2401 else if(td
[0] == VT_USERDEFINED
)
2403 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2405 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2408 /* second time around to fill the array subscript info */
2411 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2412 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2414 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2415 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2418 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2420 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2422 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2424 for(j
= 0; j
<td
[2]; j
++)
2426 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2427 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2428 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2429 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2434 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2435 ERR("didn't find array description data\n");
2440 /* imported type libs */
2441 if(tlbSegDir
.pImpFiles
.offset
>0)
2443 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2444 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2447 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2452 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2453 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2454 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2456 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2457 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2458 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2459 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2462 name
= TLB_Alloc(size
+1);
2463 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2464 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2465 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2466 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2469 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2470 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2472 ppImpLib
= &(*ppImpLib
)->next
;
2477 if(tlbHeader
.nrtypeinfos
>= 0 )
2479 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2480 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2483 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2485 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2487 ppTI
= &((*ppTI
)->next
);
2488 (pTypeLibImpl
->TypeInfoCount
)++;
2492 TRACE("(%p)\n", pTypeLibImpl
);
2493 return (ITypeLib2
*) pTypeLibImpl
;
2497 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2503 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2504 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2505 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2506 ret
= SysAllocString(nameW
);
2507 HeapFree(GetProcessHeap(), 0, nameW
);
2511 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2517 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2518 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2522 guid
->Data4
[0] = s
>> 8;
2523 guid
->Data4
[1] = s
& 0xff;
2526 for(i
= 0; i
< 6; i
++) {
2527 memcpy(b
, str
+ 24 + 2 * i
, 2);
2528 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2533 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2540 bytelen
= *(WORD
*)ptr
;
2541 if(bytelen
== 0xffff) return 2;
2542 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2543 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2544 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2545 *pBstr
= SysAllocStringLen(nameW
, len
);
2546 HeapFree(GetProcessHeap(), 0, nameW
);
2550 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2555 bytelen
= *(WORD
*)ptr
;
2556 if(bytelen
== 0xffff) return 2;
2557 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2558 memcpy(*str
, ptr
+ 2, bytelen
);
2559 (*str
)[bytelen
] = '\0';
2563 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2565 char *ptr
= pLibBlk
;
2568 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2569 FIXME("libblk magic = %04x\n", w
);
2574 if((w
= *(WORD
*)ptr
) != 0xffff) {
2575 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2580 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2582 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2584 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2587 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2590 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2591 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2593 pTypeLibImpl
->LibAttr
.lcid
= 0;
2596 ptr
+= 4; /* skip res12 */
2598 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2601 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2604 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2607 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2608 ptr
+= sizeof(GUID
);
2610 return ptr
- (char*)pLibBlk
;
2613 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2616 TYPEDESC
*pTD
= &pElem
->tdesc
;
2618 /* Handle [in/out] first */
2619 if((*pType
& 0xc000) == 0xc000)
2620 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2621 else if(*pType
& 0x8000)
2622 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2623 else if(*pType
& 0x4000)
2624 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2626 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2629 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2632 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2635 if((*pType
& 0xe00) == 0xe00) {
2637 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2639 pTD
= pTD
->u
.lptdesc
;
2641 switch(*pType
& 0x7f) {
2644 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2646 pTD
= pTD
->u
.lptdesc
;
2649 case VT_USERDEFINED
:
2650 pTD
->vt
= VT_USERDEFINED
;
2651 pTD
->u
.hreftype
= *(++pType
) / 4;
2657 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2660 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2662 pTD
->vt
= VT_CARRAY
;
2663 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2665 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2666 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2667 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2668 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2670 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2676 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2680 pTD
->vt
= VT_SAFEARRAY
;
2681 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2683 pTD
= pTD
->u
.lptdesc
;
2687 pTD
->vt
= *pType
& 0x7f;
2697 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2702 TLBRefType
**ppRefType
;
2704 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2705 FIXME("Ref magic = %x\n", pRef
->magic
);
2708 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2710 ppRefType
= &pTI
->reflist
;
2711 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2713 unsigned int lib_offs
, type_num
;
2715 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2716 sizeof(**ppRefType
));
2718 name
+= SLTG_ReadStringA(name
, &refname
);
2719 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2720 FIXME("Can't sscanf ref\n");
2721 if(lib_offs
!= 0xffff) {
2722 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2725 if((*import
)->offset
== lib_offs
)
2727 import
= &(*import
)->next
;
2730 char fname
[MAX_PATH
+1];
2733 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2735 (*import
)->offset
= lib_offs
;
2736 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2738 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2739 &(*import
)->wVersionMajor
,
2740 &(*import
)->wVersionMinor
,
2741 &(*import
)->lcid
, fname
) != 4) {
2742 FIXME("can't sscanf ref %s\n",
2743 pNameTable
+ lib_offs
+ 40);
2745 len
= strlen(fname
);
2746 if(fname
[len
-1] != '#')
2747 FIXME("fname = %s\n", fname
);
2748 fname
[len
-1] = '\0';
2749 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2751 (*ppRefType
)->pImpTLInfo
= *import
;
2752 } else { /* internal ref */
2753 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2755 (*ppRefType
)->reference
= ref
;
2756 (*ppRefType
)->index
= type_num
;
2758 HeapFree(GetProcessHeap(), 0, refname
);
2759 ppRefType
= &(*ppRefType
)->next
;
2761 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2762 FIXME("End of ref block magic = %x\n", *name
);
2763 dump_TLBRefType(pTI
->reflist
);
2766 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2769 SLTG_ImplInfo
*info
;
2770 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2771 /* I don't really get this structure, usually it's 0x16 bytes
2772 long, but iuser.tlb contains some that are 0x18 bytes long.
2773 That's ok because we can use the next ptr to jump to the next
2774 one. But how do we know the length of the last one? The WORD
2775 at offs 0x8 might be the clue. For now I'm just assuming that
2776 the last one is the regular 0x16 bytes. */
2778 info
= (SLTG_ImplInfo
*)pBlk
;
2780 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2781 sizeof(**ppImplType
));
2782 (*ppImplType
)->hRef
= info
->ref
;
2783 (*ppImplType
)->implflags
= info
->impltypeflags
;
2784 pTI
->TypeAttr
.cImplTypes
++;
2785 ppImplType
= &(*ppImplType
)->next
;
2787 if(info
->next
== 0xffff)
2790 FIXME("Interface inheriting more than one interface\n");
2791 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2793 info
++; /* see comment at top of function */
2797 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2800 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2801 SLTG_MemberHeader
*pMemHeader
;
2802 char *pFirstItem
, *pNextItem
;
2804 if(pTIHeader
->href_table
!= 0xffffffff) {
2805 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2810 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2812 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2814 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2815 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2818 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2822 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2825 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2826 SLTG_MemberHeader
*pMemHeader
;
2827 SLTG_Function
*pFunc
;
2828 char *pFirstItem
, *pNextItem
;
2829 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2832 if(pTIHeader
->href_table
!= 0xffffffff) {
2833 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2837 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2839 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2841 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2842 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2845 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2846 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2851 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2852 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2853 FIXME("func magic = %02x\n", pFunc
->magic
);
2856 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2857 sizeof(**ppFuncDesc
));
2858 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2860 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2861 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2862 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2863 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2864 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2865 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2867 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2868 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2870 if(pFunc
->retnextopt
& 0x80)
2871 pType
= &pFunc
->rettype
;
2873 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2876 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2878 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2879 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2880 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2881 (*ppFuncDesc
)->pParamDesc
=
2882 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2883 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2885 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2887 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2888 char *paramName
= pNameTable
+ *pArg
;
2890 /* If arg type follows then paramName points to the 2nd
2891 letter of the name, else the next WORD is an offset to
2892 the arg type and paramName points to the first letter.
2893 So let's take one char off paramName and see if we're
2894 pointing at an alpha-numeric char. However if *pArg is
2895 0xffff or 0xfffe then the param has no name, the former
2896 meaning that the next WORD is the type, the latter
2897 meaning the the next WORD is an offset to the type. */
2902 else if(*pArg
== 0xfffe) {
2906 else if(!isalnum(*(paramName
-1)))
2911 if(HaveOffs
) { /* the next word is an offset to type */
2912 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2913 SLTG_DoType(pType
, pFirstItem
,
2914 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2919 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2920 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2923 /* Are we an optional param ? */
2924 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2925 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2926 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2929 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2930 TLB_MultiByteToBSTR(paramName
);
2934 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2935 if(pFunc
->next
== 0xffff) break;
2937 pTI
->TypeAttr
.cFuncs
= num
;
2938 dump_TLBFuncDesc(pTI
->funclist
);
2939 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2942 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2945 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2946 SLTG_MemberHeader
*pMemHeader
;
2947 SLTG_RecordItem
*pItem
;
2949 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2954 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2956 pFirstItem
= (char*)(pMemHeader
+ 1);
2957 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2958 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2959 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2960 FIXME("record magic = %02x\n", pItem
->magic
);
2963 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2964 sizeof(**ppVarDesc
));
2965 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2966 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2967 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2968 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2970 if(pItem
->typepos
== 0x02)
2971 pType
= &pItem
->type
;
2972 else if(pItem
->typepos
== 0x00)
2973 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2975 FIXME("typepos = %02x\n", pItem
->typepos
);
2979 SLTG_DoType(pType
, pFirstItem
,
2980 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2982 /* FIXME("helpcontext, helpstring\n"); */
2984 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2986 ppVarDesc
= &((*ppVarDesc
)->next
);
2987 if(pItem
->next
== 0xffff) break;
2989 pTI
->TypeAttr
.cVars
= num
;
2990 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2993 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
2996 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2997 SLTG_MemberHeader
*pMemHeader
;
2998 SLTG_AliasItem
*pItem
;
3001 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3002 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3005 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3006 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
3007 if (pItem
->vt
== 0xffff) {
3008 if (i
<(pMemHeader
->cbExtra
/4-1))
3009 FIXME("Endmarker too early in process alias data!\n");
3013 FIXME("Chain extends over last entry?\n");
3016 if (pItem
->vt
== VT_USERDEFINED
) {
3017 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
3018 /* guessing here ... */
3019 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
3020 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
3023 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
3024 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
3028 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3031 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3034 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3035 SLTG_MemberHeader
*pMemHeader
;
3036 SLTG_AliasItem
*pItem
;
3038 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3039 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3040 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
3041 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
3042 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3045 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3048 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3049 SLTG_MemberHeader
*pMemHeader
;
3050 SLTG_EnumItem
*pItem
;
3052 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3055 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3057 pFirstItem
= (char*)(pMemHeader
+ 1);
3058 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
3059 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
3060 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
3061 FIXME("enumitem magic = %04x\n", pItem
->magic
);
3064 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3065 sizeof(**ppVarDesc
));
3066 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3067 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3068 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3070 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3071 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
3072 *(INT
*)(pItem
->value
+ pFirstItem
);
3073 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
3074 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3075 /* FIXME("helpcontext, helpstring\n"); */
3077 ppVarDesc
= &((*ppVarDesc
)->next
);
3078 if(pItem
->next
== 0xffff) break;
3080 pTI
->TypeAttr
.cVars
= num
;
3081 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3084 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3085 managable copy of it into this */
3098 } SLTG_InternalOtherTypeInfo
;
3100 /****************************************************************************
3101 * ITypeLib2_Constructor_SLTG
3103 * loading a SLTG typelib from an in-memory image
3105 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3107 ITypeLibImpl
*pTypeLibImpl
;
3108 SLTG_Header
*pHeader
;
3109 SLTG_BlkEntry
*pBlkEntry
;
3113 LPVOID pBlk
, pFirstBlk
;
3114 SLTG_LibBlk
*pLibBlk
;
3115 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3116 char *pAfterOTIBlks
= NULL
;
3117 char *pNameTable
, *ptr
;
3120 ITypeInfoImpl
**ppTypeInfoImpl
;
3122 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3124 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
3125 if (!pTypeLibImpl
) return NULL
;
3127 pTypeLibImpl
->lpVtbl
= &tlbvt
;
3128 pTypeLibImpl
->ref
= 1;
3133 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
3134 pHeader
->nrOfFileBlks
);
3135 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3136 FIXME("Header type magic 0x%08lx not supported.\n",
3137 pHeader
->SLTG_magic
);
3141 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3142 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3144 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3145 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3147 /* Next we have a magic block */
3148 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3150 /* Let's see if we're still in sync */
3151 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3152 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3153 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3156 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3157 sizeof(SLTG_DIR_MAGIC
))) {
3158 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3162 pIndex
= (SLTG_Index
*)(pMagic
+1);
3164 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3166 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3168 /* We'll set up a ptr to the main library block, which is the last one. */
3170 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3171 pBlkEntry
[order
].next
!= 0;
3172 order
= pBlkEntry
[order
].next
- 1, i
++) {
3173 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3177 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3179 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3184 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3186 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3187 sizeof(*pOtherTypeInfoBlks
) *
3188 pTypeLibImpl
->TypeInfoCount
);
3191 ptr
= (char*)pLibBlk
+ len
;
3193 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3197 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3199 w
= *(WORD
*)(ptr
+ 2);
3202 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3204 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3205 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3207 w
= *(WORD
*)(ptr
+ 4 + len
);
3209 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3211 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3213 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3214 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3216 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3217 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3218 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3220 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3222 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3225 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3226 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3227 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3228 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3229 len
+= sizeof(SLTG_OtherTypeInfo
);
3233 pAfterOTIBlks
= ptr
;
3235 /* Skip this WORD and get the next DWORD */
3236 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3238 /* Now add this to pLibBLk look at what we're pointing at and
3239 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3240 dust and we should be pointing at the beginning of the name
3243 pNameTable
= (char*)pLibBlk
+ len
;
3245 switch(*(WORD
*)pNameTable
) {
3252 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3256 pNameTable
+= 0x216;
3260 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3262 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3265 /* Hopefully we now have enough ptrs set up to actually read in
3266 some TypeInfos. It's not clear which order to do them in, so
3267 I'll just follow the links along the BlkEntry chain and read
3268 them in in the order in which they're in the file */
3270 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3272 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3273 pBlkEntry
[order
].next
!= 0;
3274 order
= pBlkEntry
[order
].next
- 1, i
++) {
3276 SLTG_TypeInfoHeader
*pTIHeader
;
3277 SLTG_TypeInfoTail
*pTITail
;
3279 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3280 pOtherTypeInfoBlks
[i
].index_name
)) {
3281 FIXME("Index strings don't match\n");
3286 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3287 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3290 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3291 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3292 (*ppTypeInfoImpl
)->index
= i
;
3293 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3294 pOtherTypeInfoBlks
[i
].name_offs
+
3296 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3297 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3299 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3300 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3301 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3302 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3303 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3305 if((pTIHeader
->typeflags1
& 7) != 2)
3306 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3307 if(pTIHeader
->typeflags3
!= 2)
3308 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3310 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3311 debugstr_w((*ppTypeInfoImpl
)->Name
),
3312 typekind_desc
[pTIHeader
->typekind
],
3313 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3314 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3316 switch(pTIHeader
->typekind
) {
3318 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3322 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3325 case TKIND_INTERFACE
:
3326 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3330 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3334 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3335 if (pTITail
->tdescalias_vt
)
3336 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3339 case TKIND_DISPATCH
:
3340 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3344 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3350 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3351 but we've already set those */
3352 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3353 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3354 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3356 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3378 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3379 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3382 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3383 FIXME("Somehow processed %d TypeInfos\n", i
);
3387 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3388 return (ITypeLib2
*)pTypeLibImpl
;
3391 /* ITypeLib::QueryInterface
3393 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3398 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3400 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3403 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3404 IsEqualIID(riid
,&IID_ITypeLib
)||
3405 IsEqualIID(riid
,&IID_ITypeLib2
))
3412 ITypeLib2_AddRef(iface
);
3413 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3416 TRACE("-- Interface: E_NOINTERFACE\n");
3417 return E_NOINTERFACE
;
3422 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3424 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3425 ULONG ref
= InterlockedIncrement(&This
->ref
);
3427 TRACE("(%p)->ref was %lu\n",This
, ref
- 1);
3432 /* ITypeLib::Release
3434 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3436 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3437 ULONG ref
= InterlockedDecrement(&This
->ref
);
3439 TRACE("(%p)->(%lu)\n",This
, ref
);
3443 /* remove cache entry */
3444 TRACE("removing from cache list\n");
3445 EnterCriticalSection(&cache_section
);
3446 if (This
->next
) This
->next
->prev
= This
->prev
;
3447 if (This
->prev
) This
->prev
->next
= This
->next
;
3448 else tlb_cache_first
= This
->next
;
3449 LeaveCriticalSection(&cache_section
);
3451 /* FIXME destroy child objects */
3452 TRACE(" destroying ITypeLib(%p)\n",This
);
3456 SysFreeString(This
->Name
);
3460 if (This
->DocString
)
3462 SysFreeString(This
->DocString
);
3463 This
->DocString
= NULL
;
3468 SysFreeString(This
->HelpFile
);
3469 This
->HelpFile
= NULL
;
3472 if (This
->HelpStringDll
)
3474 SysFreeString(This
->HelpStringDll
);
3475 This
->HelpStringDll
= NULL
;
3478 if (This
->pTypeInfo
) /* can be NULL */
3479 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3480 HeapFree(GetProcessHeap(),0,This
);
3487 /* ITypeLib::GetTypeInfoCount
3489 * Returns the number of type descriptions in the type library
3491 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3493 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3494 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3495 return This
->TypeInfoCount
;
3498 /* ITypeLib::GetTypeInfo
3500 * retrieves the specified type description in the library.
3502 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3505 ITypeInfo
**ppTInfo
)
3509 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3510 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3512 TRACE("(%p)->(index=%d) \n", This
, index
);
3514 if (!ppTInfo
) return E_INVALIDARG
;
3516 /* search element n in list */
3517 for(i
=0; i
< index
; i
++)
3519 pTypeInfo
= pTypeInfo
->next
;
3522 TRACE("-- element not found\n");
3523 return TYPE_E_ELEMENTNOTFOUND
;
3527 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3529 ITypeInfo_AddRef(*ppTInfo
);
3530 TRACE("-- found (%p)\n",*ppTInfo
);
3535 /* ITypeLibs::GetTypeInfoType
3537 * Retrieves the type of a type description.
3539 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3544 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3546 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3548 TRACE("(%p) index %d \n",This
, index
);
3550 if(!pTKind
) return E_INVALIDARG
;
3552 /* search element n in list */
3553 for(i
=0; i
< index
; i
++)
3557 TRACE("-- element not found\n");
3558 return TYPE_E_ELEMENTNOTFOUND
;
3560 pTInfo
= pTInfo
->next
;
3563 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3564 TRACE("-- found Type (%d)\n", *pTKind
);
3568 /* ITypeLib::GetTypeInfoOfGuid
3570 * Retrieves the type description that corresponds to the specified GUID.
3573 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3576 ITypeInfo
**ppTInfo
)
3578 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3579 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3581 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3583 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3585 /* search linked list for guid */
3586 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3588 pTypeInfo
= pTypeInfo
->next
;
3592 /* end of list reached */
3593 TRACE("-- element not found\n");
3594 return TYPE_E_ELEMENTNOTFOUND
;
3598 TRACE("-- found (%p, %s)\n",
3600 debugstr_w(pTypeInfo
->Name
));
3602 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3603 ITypeInfo_AddRef(*ppTInfo
);
3607 /* ITypeLib::GetLibAttr
3609 * Retrieves the structure that contains the library's attributes.
3612 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3614 LPTLIBATTR
*ppTLibAttr
)
3616 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3617 TRACE("(%p)\n",This
);
3618 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3619 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3623 /* ITypeLib::GetTypeComp
3625 * Enables a client compiler to bind to a library's types, variables,
3626 * constants, and global functions.
3629 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3631 ITypeComp
**ppTComp
)
3633 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3635 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3636 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3637 ITypeComp_AddRef(*ppTComp
);
3642 /* ITypeLib::GetDocumentation
3644 * Retrieves the library's documentation string, the complete Help file name
3645 * and path, and the context identifier for the library Help topic in the Help
3648 * On a successful return all non-null BSTR pointers will have been set,
3651 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3655 BSTR
*pBstrDocString
,
3656 DWORD
*pdwHelpContext
,
3657 BSTR
*pBstrHelpFile
)
3659 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3661 HRESULT result
= E_INVALIDARG
;
3666 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3668 pBstrName
, pBstrDocString
,
3669 pdwHelpContext
, pBstrHelpFile
);
3673 /* documentation for the typelib */
3677 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3683 if (This
->DocString
)
3684 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3685 else if (This
->Name
)
3686 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3688 *pBstrDocString
= NULL
;
3692 *pdwHelpContext
= This
->dwHelpContext
;
3697 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3699 *pBstrHelpFile
= NULL
;
3706 /* for a typeinfo */
3707 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3709 if(SUCCEEDED(result
))
3711 result
= ITypeInfo_GetDocumentation(pTInfo
,
3715 pdwHelpContext
, pBstrHelpFile
);
3717 ITypeInfo_Release(pTInfo
);
3722 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3724 if (pBstrName
) SysFreeString (*pBstrName
);
3726 return STG_E_INSUFFICIENTMEMORY
;
3731 * Indicates whether a passed-in string contains the name of a type or member
3732 * described in the library.
3735 static HRESULT WINAPI
ITypeLib2_fnIsName(
3741 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3742 ITypeInfoImpl
*pTInfo
;
3743 TLBFuncDesc
*pFInfo
;
3746 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3748 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3752 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3753 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3754 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3755 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3756 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3757 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3758 goto ITypeLib2_fnIsName_exit
;
3760 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3761 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3766 ITypeLib2_fnIsName_exit
:
3767 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3768 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3773 /* ITypeLib::FindName
3775 * Finds occurrences of a type description in a type library. This may be used
3776 * to quickly verify that a name exists in a type library.
3779 static HRESULT WINAPI
ITypeLib2_fnFindName(
3783 ITypeInfo
**ppTInfo
,
3787 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3788 ITypeInfoImpl
*pTInfo
;
3789 TLBFuncDesc
*pFInfo
;
3793 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3795 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3796 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3797 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3798 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3799 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3800 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3801 goto ITypeLib2_fnFindName_exit
;
3803 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3804 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3806 ITypeLib2_fnFindName_exit
:
3807 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3808 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3811 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3812 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3819 /* ITypeLib::ReleaseTLibAttr
3821 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3824 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3826 TLIBATTR
*pTLibAttr
)
3828 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3829 TRACE("freeing (%p)\n",This
);
3830 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3834 /* ITypeLib2::GetCustData
3836 * gets the custom data
3838 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3843 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3844 TLBCustData
*pCData
;
3846 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3848 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3851 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3855 VariantInit( pVarVal
);
3856 VariantCopy( pVarVal
, &pCData
->data
);
3859 return E_INVALIDARG
; /* FIXME: correct? */
3862 /* ITypeLib2::GetLibStatistics
3864 * Returns statistics about a type library that are required for efficient
3865 * sizing of hash tables.
3868 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3870 ULONG
*pcUniqueNames
,
3871 ULONG
*pcchUniqueNames
)
3873 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3875 FIXME("(%p): stub!\n", This
);
3877 if(pcUniqueNames
) *pcUniqueNames
=1;
3878 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3882 /* ITypeLib2::GetDocumentation2
3884 * Retrieves the library's documentation string, the complete Help file name
3885 * and path, the localization context to use, and the context ID for the
3886 * library Help topic in the Help file.
3889 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3893 BSTR
*pbstrHelpString
,
3894 DWORD
*pdwHelpStringContext
,
3895 BSTR
*pbstrHelpStringDll
)
3897 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3901 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3903 /* the help string should be obtained from the helpstringdll,
3904 * using the _DLLGetDocumentation function, based on the supplied
3905 * lcid. Nice to do sometime...
3909 /* documentation for the typelib */
3911 *pbstrHelpString
=SysAllocString(This
->DocString
);
3912 if(pdwHelpStringContext
)
3913 *pdwHelpStringContext
=This
->dwHelpContext
;
3914 if(pbstrHelpStringDll
)
3915 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3921 /* for a typeinfo */
3922 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3924 if(SUCCEEDED(result
))
3926 ITypeInfo2
* pTInfo2
;
3927 result
= ITypeInfo_QueryInterface(pTInfo
,
3929 (LPVOID
*) &pTInfo2
);
3931 if(SUCCEEDED(result
))
3933 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3937 pdwHelpStringContext
,
3938 pbstrHelpStringDll
);
3940 ITypeInfo2_Release(pTInfo2
);
3943 ITypeInfo_Release(pTInfo
);
3949 /* ITypeLib2::GetAllCustData
3951 * Gets all custom data items for the library.
3954 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3956 CUSTDATA
*pCustData
)
3958 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3959 TLBCustData
*pCData
;
3961 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3962 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3963 if(pCustData
->prgCustData
){
3964 pCustData
->cCustData
=This
->ctCustData
;
3965 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3966 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3967 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3970 ERR(" OUT OF MEMORY! \n");
3971 return E_OUTOFMEMORY
;
3976 static ITypeLib2Vtbl tlbvt
= {
3977 ITypeLib2_fnQueryInterface
,
3979 ITypeLib2_fnRelease
,
3980 ITypeLib2_fnGetTypeInfoCount
,
3981 ITypeLib2_fnGetTypeInfo
,
3982 ITypeLib2_fnGetTypeInfoType
,
3983 ITypeLib2_fnGetTypeInfoOfGuid
,
3984 ITypeLib2_fnGetLibAttr
,
3985 ITypeLib2_fnGetTypeComp
,
3986 ITypeLib2_fnGetDocumentation
,
3988 ITypeLib2_fnFindName
,
3989 ITypeLib2_fnReleaseTLibAttr
,
3991 ITypeLib2_fnGetCustData
,
3992 ITypeLib2_fnGetLibStatistics
,
3993 ITypeLib2_fnGetDocumentation2
,
3994 ITypeLib2_fnGetAllCustData
3998 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4000 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4002 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
4005 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4007 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4009 return ITypeInfo_AddRef((ITypeInfo
*)This
);
4012 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4014 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4016 return ITypeInfo_Release((ITypeInfo
*)This
);
4019 static HRESULT WINAPI
ITypeLibComp_fnBind(
4024 ITypeInfo
** ppTInfo
,
4025 DESCKIND
* pDescKind
,
4028 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4032 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4036 ITypeInfo
** ppTInfo
,
4037 ITypeComp
** ppTComp
)
4039 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4043 static ITypeCompVtbl tlbtcvt
=
4046 ITypeLibComp_fnQueryInterface
,
4047 ITypeLibComp_fnAddRef
,
4048 ITypeLibComp_fnRelease
,
4050 ITypeLibComp_fnBind
,
4051 ITypeLibComp_fnBindType
4054 /*================== ITypeInfo(2) Methods ===================================*/
4055 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4057 ITypeInfoImpl
* pTypeInfoImpl
;
4059 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4062 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4063 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4064 pTypeInfoImpl
->ref
=1;
4066 TRACE("(%p)\n", pTypeInfoImpl
);
4067 return (ITypeInfo2
*) pTypeInfoImpl
;
4070 /* ITypeInfo::QueryInterface
4072 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4077 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4079 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4082 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4083 IsEqualIID(riid
,&IID_ITypeInfo
)||
4084 IsEqualIID(riid
,&IID_ITypeInfo2
))
4088 ITypeInfo_AddRef(iface
);
4089 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4092 TRACE("-- Interface: E_NOINTERFACE\n");
4093 return E_NOINTERFACE
;
4096 /* ITypeInfo::AddRef
4098 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4100 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4101 ULONG ref
= InterlockedIncrement(&This
->ref
);
4103 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4105 TRACE("(%p)->ref is %lu\n",This
, ref
);
4109 /* ITypeInfo::Release
4111 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4113 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4114 ULONG ref
= InterlockedDecrement(&This
->ref
);
4116 TRACE("(%p)->(%lu)\n",This
, ref
);
4119 /* We don't release ITypeLib when ref=0 because
4120 it means that function is called by ITypeLib2_Release */
4121 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4123 FIXME("destroy child objects\n");
4125 TRACE("destroying ITypeInfo(%p)\n",This
);
4128 SysFreeString(This
->Name
);
4132 if (This
->DocString
)
4134 SysFreeString(This
->DocString
);
4135 This
->DocString
= 0;
4140 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4143 HeapFree(GetProcessHeap(),0,This
);
4149 /* ITypeInfo::GetTypeAttr
4151 * Retrieves a TYPEATTR structure that contains the attributes of the type
4155 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4156 LPTYPEATTR
*ppTypeAttr
)
4158 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4159 TRACE("(%p)\n",This
);
4160 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr
));
4161 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4163 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
) /* need to deep copy typedesc */
4164 copy_typedesc(&(*ppTypeAttr
)->tdescAlias
, &This
->TypeAttr
.tdescAlias
);
4166 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
&& (*ppTypeAttr
)->wTypeFlags
& TYPEFLAG_FDUAL
) {
4167 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4169 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4170 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4175 /* ITypeInfo::GetTypeComp
4177 * Retrieves the ITypeComp interface for the type description, which enables a
4178 * client compiler to bind to the type description's members.
4181 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4182 ITypeComp
* *ppTComp
)
4184 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4186 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4188 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4189 ITypeComp_AddRef(*ppTComp
);
4193 /* ITypeInfo::GetFuncDesc
4195 * Retrieves the FUNCDESC structure that contains information about a
4196 * specified function.
4199 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4200 LPFUNCDESC
*ppFuncDesc
)
4202 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4204 TLBFuncDesc
* pFDesc
;
4205 TRACE("(%p) index %d\n", This
, index
);
4206 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4209 /* FIXME: must do a copy here */
4210 *ppFuncDesc
=&pFDesc
->funcdesc
;
4213 return E_INVALIDARG
;
4216 /* ITypeInfo::GetVarDesc
4218 * Retrieves a VARDESC structure that describes the specified variable.
4221 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4222 LPVARDESC
*ppVarDesc
)
4224 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4226 TLBVarDesc
* pVDesc
;
4227 TRACE("(%p) index %d\n", This
, index
);
4228 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4231 /* FIXME: must do a copy here */
4232 *ppVarDesc
=&pVDesc
->vardesc
;
4235 return E_INVALIDARG
;
4238 /* ITypeInfo_GetNames
4240 * Retrieves the variable with the specified member ID (or the name of the
4241 * property or method and its parameters) that correspond to the specified
4244 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4245 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4247 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4248 TLBFuncDesc
* pFDesc
;
4249 TLBVarDesc
* pVDesc
;
4251 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4252 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4255 /* function found, now return function and parameter names */
4256 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4259 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4261 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4267 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4270 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4275 if(This
->TypeAttr
.cImplTypes
&&
4276 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4277 /* recursive search */
4280 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4282 if(SUCCEEDED(result
))
4284 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4285 ITypeInfo_Release(pTInfo
);
4288 WARN("Could not search inherited interface!\n");
4292 WARN("no names found\n");
4295 return TYPE_E_ELEMENTNOTFOUND
;
4302 /* ITypeInfo::GetRefTypeOfImplType
4304 * If a type description describes a COM class, it retrieves the type
4305 * description of the implemented interface types. For an interface,
4306 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4310 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4315 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4317 TLBImplType
*pImpl
= This
->impltypelist
;
4319 TRACE("(%p) index %d\n", This
, index
);
4320 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4324 /* only valid on dual interfaces;
4325 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4327 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4329 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4330 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4336 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4337 *pRefType
= pImpl
->hRef
;
4342 /* get element n from linked list */
4343 for(i
=0; pImpl
&& i
<index
; i
++)
4345 pImpl
= pImpl
->next
;
4348 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4350 *pRefType
= pImpl
->hRef
;
4352 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4359 /* ITypeInfo::GetImplTypeFlags
4361 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4362 * or base interface in a type description.
4364 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4365 UINT index
, INT
*pImplTypeFlags
)
4367 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4371 TRACE("(%p) index %d\n", This
, index
);
4372 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4373 i
++, pImpl
=pImpl
->next
)
4375 if(i
==index
&& pImpl
){
4376 *pImplTypeFlags
=pImpl
->implflags
;
4380 return TYPE_E_ELEMENTNOTFOUND
;
4384 * Maps between member names and member IDs, and parameter names and
4387 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4388 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4390 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4391 TLBFuncDesc
* pFDesc
;
4392 TLBVarDesc
* pVDesc
;
4395 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4397 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4399 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4400 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4401 for(i
=1; i
< cNames
; i
++){
4402 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4403 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4405 if( j
<pFDesc
->funcdesc
.cParams
)
4408 ret
=DISP_E_UNKNOWNNAME
;
4413 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4414 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4415 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4419 /* not found, see if this is and interface with an inheritance */
4420 if(This
->TypeAttr
.cImplTypes
&&
4421 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4422 /* recursive search */
4424 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4425 This
->impltypelist
->hRef
, &pTInfo
);
4427 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4428 ITypeInfo_Release(pTInfo
);
4431 WARN("Could not search inherited interface!\n");
4433 WARN("no names found\n");
4434 return DISP_E_UNKNOWNNAME
;
4437 /* ITypeInfo::Invoke
4439 * Invokes a method, or accesses a property of an object, that implements the
4440 * interface described by the type description.
4443 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4446 if (TRACE_ON(ole
)) {
4448 TRACE("Calling %p(",func
);
4449 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4461 res
= func(args
[0]);
4464 res
= func(args
[0],args
[1]);
4467 res
= func(args
[0],args
[1],args
[2]);
4470 res
= func(args
[0],args
[1],args
[2],args
[3]);
4473 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4476 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4479 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4482 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4485 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4488 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
4491 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
4494 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4500 FIXME("unsupported calling convention %d\n",callconv
);
4504 TRACE("returns %08lx\n",res
);
4508 extern int _argsize(DWORD vt
);
4510 /****************************************************************************
4511 * Helper functions for Dispcall / Invoke, which copies one variant
4512 * with target type onto the argument stack.
4515 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4516 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4518 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4522 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4523 memcpy(argpos
,&arg
,sizeof(void*));
4527 if (V_VT(arg
) == vt
) {
4528 memcpy(argpos
, &V_I4(arg
), arglen
);
4532 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4533 memcpy(argpos
, &V_ARRAY(arg
), sizeof(SAFEARRAY
*));
4537 if (vt
== VT_VARIANT
) {
4538 memcpy(argpos
, arg
, arglen
);
4541 /* Deref BYREF vars if there is need */
4542 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4543 memcpy(argpos
,(void*)V_I4(arg
), arglen
);
4546 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4547 /* in this context, if the type lib specifies IUnknown*, giving an
4548 IDispatch* is correct; so, don't invoke VariantChangeType */
4549 memcpy(argpos
,&V_I4(arg
), arglen
);
4552 if ((vt
== VT_PTR
) && tdesc
)
4553 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4555 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4556 ITypeInfo
*tinfo2
= NULL
;
4557 TYPEATTR
*tattr
= NULL
;
4560 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4562 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4563 "while coercing from vt 0x%x. Copying 4 byte.\n",
4564 tdesc
->u
.hreftype
,V_VT(arg
));
4565 memcpy(argpos
, &V_I4(arg
), 4);
4568 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4571 ERR("GetTypeAttr failed\n");
4572 ITypeInfo_Release(tinfo2
);
4575 switch (tattr
->typekind
) {
4577 switch ( V_VT( arg
) ) {
4579 *argpos
= V_I2(arg
);
4583 memcpy(argpos
, &V_I4(arg
), 4);
4587 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4594 tdesc
= &(tattr
->tdescAlias
);
4595 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4598 case TKIND_INTERFACE
:
4599 if (V_VT(arg
) == VT_DISPATCH
) {
4601 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4602 memcpy(argpos
, &V_DISPATCH(arg
), 4);
4606 hres
=IUnknown_QueryInterface(V_DISPATCH(arg
),
4607 &IID_IDispatch
,(LPVOID
*)&disp
);
4608 if (SUCCEEDED(hres
)) {
4609 memcpy(argpos
,&disp
,4);
4610 IUnknown_Release(V_DISPATCH(arg
));
4614 FIXME("Failed to query IDispatch interface from %s while "
4615 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4619 if (V_VT(arg
) == VT_UNKNOWN
) {
4620 memcpy(argpos
, &V_UNKNOWN(arg
), 4);
4624 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4625 V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4629 case TKIND_DISPATCH
:
4630 if (V_VT(arg
) == VT_DISPATCH
) {
4631 memcpy(argpos
, &V_DISPATCH(arg
), 4);
4636 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4640 FIXME("TKIND_RECORD unhandled.\n");
4644 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4648 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4649 ITypeInfo_Release(tinfo2
);
4655 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4656 memcpy(argpos
,&V_I4(&va
), arglen
);
4657 FIXME("Should not use VariantChangeType here."
4658 " (conversion from 0x%x -> 0x%x) %08lx\n",
4659 V_VT(arg
), vt
, *argpos
4663 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4667 /***********************************************************************
4668 * DispCallFunc (OLEAUT32.@)
4672 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4673 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4675 int i
, argsize
, argspos
;
4679 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4680 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4682 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4683 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4685 for (i
=0;i
<cActuals
;i
++) {
4686 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4687 dump_Variant(prgpvarg
[i
]);
4688 argsize
+= _argsize(prgvt
[i
]);
4690 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4691 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4693 for (i
=0;i
<cActuals
;i
++) {
4694 VARIANT
*arg
= prgpvarg
[i
];
4695 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4696 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4697 argspos
+= _argsize(prgvt
[i
]);
4700 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4702 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4707 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4708 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4709 FIXME("Method returned %lx\n",hres
);
4711 HeapFree(GetProcessHeap(),0,args
);
4715 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4720 DISPPARAMS
*pDispParams
,
4721 VARIANT
*pVarResult
,
4722 EXCEPINFO
*pExcepInfo
,
4725 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4727 unsigned int func_index
, var_index
;
4731 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4732 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4734 dump_DispParms(pDispParams
);
4736 hres
= ITypeInfo2_GetFuncIndexOfMemId(iface
, memid
, dwFlags
, &func_index
);
4737 if (SUCCEEDED(hres
)) {
4738 FUNCDESC
*func_desc
;
4740 hres
= ITypeInfo2_GetFuncDesc(iface
, func_index
, &func_desc
);
4741 if(FAILED(hres
)) return hres
;
4743 switch (func_desc
->funckind
) {
4744 case FUNC_PUREVIRTUAL
:
4745 case FUNC_VIRTUAL
: {
4747 int numargs
, numargs2
, argspos
, args2pos
;
4748 DWORD
*args
, *args2
;
4749 VARIANT
*rgvarg
= HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT
) * func_desc
->cParams
);
4750 memcpy(rgvarg
,pDispParams
->rgvarg
,sizeof(VARIANT
)*pDispParams
->cArgs
);
4753 numargs
= 1; numargs2
= 0;
4754 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4755 if (i
<pDispParams
->cArgs
)
4756 numargs
+= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4758 numargs
+= 1; /* sizeof(lpvoid) */
4759 numargs2
+= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4763 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4764 args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4766 args
[0] = (DWORD
)pIUnk
;
4767 argspos
= 1; args2pos
= 0;
4768 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4769 int arglen
= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4770 if (i
<pDispParams
->cArgs
) {
4771 VARIANT
*arg
= &rgvarg
[pDispParams
->cArgs
-i
-1];
4772 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4773 USHORT paramFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
4774 if (paramFlags
& PARAMFLAG_FOPT
) {
4775 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4776 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4777 if(V_VT(arg
) == VT_EMPTY
4778 || ((V_ISBYREF(arg
)) && !V_BYREF(arg
))) {
4779 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4780 How to determine it? */
4782 if(paramFlags
& PARAMFLAG_FHASDEFAULT
)
4783 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4784 V_VT(arg
) = VT_ERROR
;
4785 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4786 arglen
= _argsize(VT_ERROR
);
4789 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4790 if (FAILED(hres
)) goto func_fail
;
4792 } else if(func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FOPT
) {
4793 VARIANT
*arg
= &rgvarg
[i
];
4794 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4795 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4796 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4797 if(func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4798 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4799 V_VT(arg
) = VT_ERROR
;
4800 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4801 arglen
= _argsize(VT_ERROR
);
4802 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4803 if (FAILED(hres
)) goto func_fail
;
4806 TYPEDESC
*tdesc
= &(func_desc
->lprgelemdescParam
[i
].tdesc
);
4807 if (tdesc
->vt
!= VT_PTR
)
4808 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4809 /*FIXME: give pointers for the rest, so propertyget works*/
4810 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4812 /* If pointer to variant, pass reference it. */
4813 if ((tdesc
->vt
== VT_PTR
) &&
4814 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4817 args
[argspos
]= (DWORD
)pVarResult
;
4822 if (func_desc
->cParamsOpt
< 0)
4823 FIXME("Does not support optional parameters (%d)\n", func_desc
->cParamsOpt
);
4825 res
= _invoke((*(FARPROC
**)pIUnk
)[func_desc
->oVft
/4],
4826 func_desc
->callconv
,
4831 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4833 for (i
= 0; i
< func_desc
->cParams
- pDispParams
->cArgs
; i
++) {
4834 int arglen
= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4835 TYPEDESC
*tdesc
= &(func_desc
->lprgelemdescParam
[i
+ pDispParams
->cArgs
].tdesc
);
4837 i4_tdesc
.vt
= VT_I4
;
4839 /* If we are a pointer to a variant, we are done already */
4840 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4843 VariantInit(pVarResult
);
4844 memcpy(&V_INT(pVarResult
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4846 if (tdesc
->vt
== VT_PTR
)
4847 tdesc
= tdesc
->u
.lptdesc
;
4848 if (tdesc
->vt
== VT_USERDEFINED
) {
4852 hres
= ITypeInfo_GetRefTypeInfo(iface
,tdesc
->u
.hreftype
,&tinfo2
);
4854 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc
->u
.hreftype
);
4857 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4858 switch (tattr
->typekind
) {
4860 /* force the return type to be VT_I4 */
4864 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr
->tdescAlias
.vt
);
4865 tdesc
= &(tattr
->tdescAlias
);
4868 case TKIND_INTERFACE
:
4869 FIXME("TKIND_INTERFACE unhandled.\n");
4871 case TKIND_DISPATCH
:
4872 FIXME("TKIND_DISPATCH unhandled.\n");
4875 FIXME("TKIND_RECORD unhandled.\n");
4878 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4881 ITypeInfo_Release(tinfo2
);
4883 V_VT(pVarResult
) = tdesc
->vt
;
4885 /* HACK: VB5 likes this.
4886 * I do not know why. There is 1 example in MSDN which uses
4887 * this which appears broken (mixes int vals and
4890 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4891 V_VT(pVarResult
) = VT_DISPATCH
;
4892 TRACE("storing into variant:\n");
4893 dump_Variant(pVarResult
);
4898 HeapFree(GetProcessHeap(), 0, rgvarg
);
4899 HeapFree(GetProcessHeap(),0,args2
);
4900 HeapFree(GetProcessHeap(),0,args
);
4903 case FUNC_DISPATCH
: {
4906 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4907 if (SUCCEEDED(hres
)) {
4908 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4909 hres
= IDispatch_Invoke(
4910 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4911 pVarResult
,pExcepInfo
,pArgErr
4914 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres
);
4915 IDispatch_Release(disp
);
4917 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4921 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
4926 ITypeInfo2_ReleaseFuncDesc(iface
, func_desc
);
4929 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
4932 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
4933 if(FAILED(hres
)) return hres
;
4935 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4936 dump_VARDESC(var_desc
);
4937 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
4941 /* not found, look for it in inherited interfaces */
4942 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
4943 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
4945 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface
, 0, &ref_type
))) {
4946 /* recursive search */
4948 hres
= ITypeInfo_GetRefTypeInfo(iface
, ref_type
, &pTInfo
);
4949 if(SUCCEEDED(hres
)){
4950 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4951 ITypeInfo_Release(pTInfo
);
4954 WARN("Could not search inherited interface!\n");
4957 ERR("did not find member id %08lx, flags %d!\n", memid
, dwFlags
);
4958 return DISP_E_MEMBERNOTFOUND
;
4961 /* ITypeInfo::GetDocumentation
4963 * Retrieves the documentation string, the complete Help file name and path,
4964 * and the context ID for the Help topic for a specified type description.
4966 * (Can be tested by the Visual Basic Editor in Word for instance.)
4968 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4969 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4970 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4972 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4973 TLBFuncDesc
* pFDesc
;
4974 TLBVarDesc
* pVDesc
;
4975 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4976 " HelpContext(%p) HelpFile(%p)\n",
4977 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4978 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4980 *pBstrName
=SysAllocString(This
->Name
);
4982 *pBstrDocString
=SysAllocString(This
->DocString
);
4984 *pdwHelpContext
=This
->dwHelpContext
;
4986 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4988 }else {/* for a member */
4989 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4990 if(pFDesc
->funcdesc
.memid
==memid
){
4992 *pBstrName
= SysAllocString(pFDesc
->Name
);
4994 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4996 *pdwHelpContext
=pFDesc
->helpcontext
;
4999 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5000 if(pVDesc
->vardesc
.memid
==memid
){
5002 *pBstrName
= SysAllocString(pVDesc
->Name
);
5004 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
5006 *pdwHelpContext
=pVDesc
->HelpContext
;
5010 return TYPE_E_ELEMENTNOTFOUND
;
5013 /* ITypeInfo::GetDllEntry
5015 * Retrieves a description or specification of an entry point for a function
5018 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5019 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5022 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5023 TLBFuncDesc
*pFDesc
;
5025 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5027 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5028 if(pFDesc
->funcdesc
.memid
==memid
){
5029 dump_TypeInfo(This
);
5030 dump_TLBFuncDescOne(pFDesc
);
5032 /* FIXME: This is wrong, but how do you find that out? */
5034 static const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5035 *pBstrDllName
= SysAllocString(oleaut32W
);
5038 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5040 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5048 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5054 /* ITypeInfo::GetRefTypeInfo
5056 * If a type description references other type descriptions, it retrieves
5057 * the referenced type descriptions.
5059 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5062 ITypeInfo
**ppTInfo
)
5064 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5065 HRESULT result
= E_FAIL
;
5068 if (hRefType
== -1 &&
5069 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5070 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5072 /* when we meet a DUAL dispinterface, we must create the interface
5075 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5078 /* the interface version contains the same information as the dispinterface
5079 * copy the contents of the structs.
5081 *pTypeInfoImpl
= *This
;
5082 pTypeInfoImpl
->ref
= 1;
5084 /* change the type to interface */
5085 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5087 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5089 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
5094 TLBRefType
*pRefType
;
5095 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5096 if(pRefType
->reference
== hRefType
)
5100 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
5101 if(pRefType
&& hRefType
!= -1) {
5102 ITypeLib
*pTLib
= NULL
;
5104 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5106 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5108 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5109 TRACE("typeinfo in imported typelib that is already loaded\n");
5110 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5111 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5114 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5115 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5116 pRefType
->pImpTLInfo
->wVersionMajor
,
5117 pRefType
->pImpTLInfo
->wVersionMinor
,
5118 pRefType
->pImpTLInfo
->lcid
,
5121 if(!SUCCEEDED(result
)) {
5122 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5123 result
=LoadTypeLib(libnam
, &pTLib
);
5124 SysFreeString(libnam
);
5126 if(SUCCEEDED(result
)) {
5127 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5128 ITypeLib2_AddRef(pTLib
);
5132 if(SUCCEEDED(result
)) {
5133 if(pRefType
->index
== TLB_REF_USE_GUID
)
5134 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5138 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5142 ITypeLib2_Release(pTLib
);
5146 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
5147 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5151 /* ITypeInfo::AddressOfMember
5153 * Retrieves the addresses of static functions or variables, such as those
5156 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5157 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5159 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5160 FIXME("(%p) stub!\n", This
);
5164 /* ITypeInfo::CreateInstance
5166 * Creates a new instance of a type that describes a component object class
5169 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
5170 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
5172 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5173 FIXME("(%p) stub!\n", This
);
5177 /* ITypeInfo::GetMops
5179 * Retrieves marshalling information.
5181 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
5184 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5185 FIXME("(%p) stub!\n", This
);
5189 /* ITypeInfo::GetContainingTypeLib
5191 * Retrieves the containing type library and the index of the type description
5192 * within that type library.
5194 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
5195 ITypeLib
* *ppTLib
, UINT
*pIndex
)
5197 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5199 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5201 *pIndex
=This
->index
;
5202 TRACE("returning pIndex=%d\n", *pIndex
);
5206 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
5207 ITypeLib2_AddRef(*ppTLib
);
5208 TRACE("returning ppTLib=%p\n", *ppTLib
);
5214 /* ITypeInfo::ReleaseTypeAttr
5216 * Releases a TYPEATTR previously returned by GetTypeAttr.
5219 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
5220 TYPEATTR
* pTypeAttr
)
5222 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5223 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
5224 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5225 free_deep_typedesc(&pTypeAttr
->tdescAlias
);
5226 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
5229 /* ITypeInfo::ReleaseFuncDesc
5231 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5233 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
5235 FUNCDESC
*pFuncDesc
)
5237 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5238 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
5241 /* ITypeInfo::ReleaseVarDesc
5243 * Releases a VARDESC previously returned by GetVarDesc.
5245 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5248 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5249 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5252 /* ITypeInfo2::GetTypeKind
5254 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5257 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5258 TYPEKIND
*pTypeKind
)
5260 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5261 *pTypeKind
=This
->TypeAttr
.typekind
;
5262 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5266 /* ITypeInfo2::GetTypeFlags
5268 * Returns the type flags without any allocations. This returns a DWORD type
5269 * flag, which expands the type flags without growing the TYPEATTR (type
5273 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5275 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5276 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5277 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5281 /* ITypeInfo2::GetFuncIndexOfMemId
5282 * Binds to a specific member based on a known DISPID, where the member name
5283 * is not known (for example, when binding to a default member).
5286 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5287 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5289 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5290 TLBFuncDesc
*pFuncInfo
;
5294 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
5295 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
5301 result
= TYPE_E_ELEMENTNOTFOUND
;
5303 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5304 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5308 /* TypeInfo2::GetVarIndexOfMemId
5310 * Binds to a specific member based on a known DISPID, where the member name
5311 * is not known (for example, when binding to a default member).
5314 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5315 MEMBERID memid
, UINT
*pVarIndex
)
5317 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5318 TLBVarDesc
*pVarInfo
;
5321 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5322 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5328 result
= TYPE_E_ELEMENTNOTFOUND
;
5330 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5331 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5335 /* ITypeInfo2::GetCustData
5337 * Gets the custom data
5339 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5344 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5345 TLBCustData
*pCData
;
5347 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5348 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5350 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5354 VariantInit( pVarVal
);
5355 VariantCopy( pVarVal
, &pCData
->data
);
5358 return E_INVALIDARG
; /* FIXME: correct? */
5361 /* ITypeInfo2::GetFuncCustData
5363 * Gets the custom data
5365 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5371 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5372 TLBCustData
*pCData
=NULL
;
5373 TLBFuncDesc
* pFDesc
;
5375 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5376 pFDesc
=pFDesc
->next
);
5379 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5380 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5382 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5385 VariantInit( pVarVal
);
5386 VariantCopy( pVarVal
, &pCData
->data
);
5389 return E_INVALIDARG
; /* FIXME: correct? */
5392 /* ITypeInfo2::GetParamCustData
5394 * Gets the custom data
5396 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5403 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5404 TLBCustData
*pCData
=NULL
;
5405 TLBFuncDesc
* pFDesc
;
5408 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5410 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5411 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5412 pCData
= pCData
->next
)
5413 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5415 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5419 VariantInit( pVarVal
);
5420 VariantCopy( pVarVal
, &pCData
->data
);
5423 return E_INVALIDARG
; /* FIXME: correct? */
5426 /* ITypeInfo2::GetVarCustData
5428 * Gets the custom data
5430 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5436 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5437 TLBCustData
*pCData
=NULL
;
5438 TLBVarDesc
* pVDesc
;
5441 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5445 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5447 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5451 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5455 VariantInit( pVarVal
);
5456 VariantCopy( pVarVal
, &pCData
->data
);
5459 return E_INVALIDARG
; /* FIXME: correct? */
5462 /* ITypeInfo2::GetImplCustData
5464 * Gets the custom data
5466 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5472 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5473 TLBCustData
*pCData
=NULL
;
5474 TLBImplType
* pRDesc
;
5477 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5481 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5483 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5487 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5491 VariantInit( pVarVal
);
5492 VariantCopy( pVarVal
, &pCData
->data
);
5495 return E_INVALIDARG
; /* FIXME: correct? */
5498 /* ITypeInfo2::GetDocumentation2
5500 * Retrieves the documentation string, the complete Help file name and path,
5501 * the localization context to use, and the context ID for the library Help
5502 * topic in the Help file.
5505 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5509 BSTR
*pbstrHelpString
,
5510 DWORD
*pdwHelpStringContext
,
5511 BSTR
*pbstrHelpStringDll
)
5513 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5514 TLBFuncDesc
* pFDesc
;
5515 TLBVarDesc
* pVDesc
;
5516 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5517 "HelpStringContext(%p) HelpStringDll(%p)\n",
5518 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5519 pbstrHelpStringDll
);
5520 /* the help string should be obtained from the helpstringdll,
5521 * using the _DLLGetDocumentation function, based on the supplied
5522 * lcid. Nice to do sometime...
5524 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5526 *pbstrHelpString
=SysAllocString(This
->Name
);
5527 if(pdwHelpStringContext
)
5528 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5529 if(pbstrHelpStringDll
)
5530 *pbstrHelpStringDll
=
5531 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5533 }else {/* for a member */
5534 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5535 if(pFDesc
->funcdesc
.memid
==memid
){
5537 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5538 if(pdwHelpStringContext
)
5539 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5540 if(pbstrHelpStringDll
)
5541 *pbstrHelpStringDll
=
5542 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5545 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5546 if(pVDesc
->vardesc
.memid
==memid
){
5548 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5549 if(pdwHelpStringContext
)
5550 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5551 if(pbstrHelpStringDll
)
5552 *pbstrHelpStringDll
=
5553 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5557 return TYPE_E_ELEMENTNOTFOUND
;
5560 /* ITypeInfo2::GetAllCustData
5562 * Gets all custom data items for the Type info.
5565 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5567 CUSTDATA
*pCustData
)
5569 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5570 TLBCustData
*pCData
;
5573 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5575 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5576 if(pCustData
->prgCustData
){
5577 pCustData
->cCustData
=This
->ctCustData
;
5578 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5579 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5580 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5583 ERR(" OUT OF MEMORY! \n");
5584 return E_OUTOFMEMORY
;
5589 /* ITypeInfo2::GetAllFuncCustData
5591 * Gets all custom data items for the specified Function
5594 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5597 CUSTDATA
*pCustData
)
5599 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5600 TLBCustData
*pCData
;
5601 TLBFuncDesc
* pFDesc
;
5603 TRACE("(%p) index %d\n", This
, index
);
5604 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5605 pFDesc
=pFDesc
->next
)
5608 pCustData
->prgCustData
=
5609 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5610 if(pCustData
->prgCustData
){
5611 pCustData
->cCustData
=pFDesc
->ctCustData
;
5612 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5613 pCData
= pCData
->next
){
5614 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5615 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5619 ERR(" OUT OF MEMORY! \n");
5620 return E_OUTOFMEMORY
;
5624 return TYPE_E_ELEMENTNOTFOUND
;
5627 /* ITypeInfo2::GetAllParamCustData
5629 * Gets all custom data items for the Functions
5632 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5633 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5635 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5636 TLBCustData
*pCData
=NULL
;
5637 TLBFuncDesc
* pFDesc
;
5639 TRACE("(%p) index %d\n", This
, indexFunc
);
5640 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5641 pFDesc
=pFDesc
->next
)
5643 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5644 pCustData
->prgCustData
=
5645 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5646 sizeof(CUSTDATAITEM
));
5647 if(pCustData
->prgCustData
){
5648 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5649 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5650 pCData
; i
++, pCData
= pCData
->next
){
5651 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5652 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5656 ERR(" OUT OF MEMORY! \n");
5657 return E_OUTOFMEMORY
;
5661 return TYPE_E_ELEMENTNOTFOUND
;
5664 /* ITypeInfo2::GetAllVarCustData
5666 * Gets all custom data items for the specified Variable
5669 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5670 UINT index
, CUSTDATA
*pCustData
)
5672 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5673 TLBCustData
*pCData
;
5674 TLBVarDesc
* pVDesc
;
5676 TRACE("(%p) index %d\n", This
, index
);
5677 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5678 pVDesc
=pVDesc
->next
)
5681 pCustData
->prgCustData
=
5682 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5683 if(pCustData
->prgCustData
){
5684 pCustData
->cCustData
=pVDesc
->ctCustData
;
5685 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5686 pCData
= pCData
->next
){
5687 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5688 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5692 ERR(" OUT OF MEMORY! \n");
5693 return E_OUTOFMEMORY
;
5697 return TYPE_E_ELEMENTNOTFOUND
;
5700 /* ITypeInfo2::GetAllImplCustData
5702 * Gets all custom data items for the specified implementation type
5705 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5708 CUSTDATA
*pCustData
)
5710 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5711 TLBCustData
*pCData
;
5712 TLBImplType
* pRDesc
;
5714 TRACE("(%p) index %d\n", This
, index
);
5715 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5716 pRDesc
=pRDesc
->next
)
5719 pCustData
->prgCustData
=
5720 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5721 if(pCustData
->prgCustData
){
5722 pCustData
->cCustData
=pRDesc
->ctCustData
;
5723 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5724 pCData
= pCData
->next
){
5725 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5726 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5730 ERR(" OUT OF MEMORY! \n");
5731 return E_OUTOFMEMORY
;
5735 return TYPE_E_ELEMENTNOTFOUND
;
5738 static ITypeInfo2Vtbl tinfvt
=
5741 ITypeInfo_fnQueryInterface
,
5743 ITypeInfo_fnRelease
,
5745 ITypeInfo_fnGetTypeAttr
,
5746 ITypeInfo_fnGetTypeComp
,
5747 ITypeInfo_fnGetFuncDesc
,
5748 ITypeInfo_fnGetVarDesc
,
5749 ITypeInfo_fnGetNames
,
5750 ITypeInfo_fnGetRefTypeOfImplType
,
5751 ITypeInfo_fnGetImplTypeFlags
,
5752 ITypeInfo_fnGetIDsOfNames
,
5754 ITypeInfo_fnGetDocumentation
,
5755 ITypeInfo_fnGetDllEntry
,
5756 ITypeInfo_fnGetRefTypeInfo
,
5757 ITypeInfo_fnAddressOfMember
,
5758 ITypeInfo_fnCreateInstance
,
5759 ITypeInfo_fnGetMops
,
5760 ITypeInfo_fnGetContainingTypeLib
,
5761 ITypeInfo_fnReleaseTypeAttr
,
5762 ITypeInfo_fnReleaseFuncDesc
,
5763 ITypeInfo_fnReleaseVarDesc
,
5765 ITypeInfo2_fnGetTypeKind
,
5766 ITypeInfo2_fnGetTypeFlags
,
5767 ITypeInfo2_fnGetFuncIndexOfMemId
,
5768 ITypeInfo2_fnGetVarIndexOfMemId
,
5769 ITypeInfo2_fnGetCustData
,
5770 ITypeInfo2_fnGetFuncCustData
,
5771 ITypeInfo2_fnGetParamCustData
,
5772 ITypeInfo2_fnGetVarCustData
,
5773 ITypeInfo2_fnGetImplTypeCustData
,
5774 ITypeInfo2_fnGetDocumentation2
,
5775 ITypeInfo2_fnGetAllCustData
,
5776 ITypeInfo2_fnGetAllFuncCustData
,
5777 ITypeInfo2_fnGetAllParamCustData
,
5778 ITypeInfo2_fnGetAllVarCustData
,
5779 ITypeInfo2_fnGetAllImplTypeCustData
,
5782 /******************************************************************************
5783 * CreateDispTypeInfo [OLEAUT32.31]
5785 * Build type information for an object so it can be called through an
5786 * IDispatch interface.
5789 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5790 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5793 * This call allows an objects methods to be accessed through IDispatch, by
5794 * building an ITypeInfo object that IDispatch can use to call through.
5796 HRESULT WINAPI
CreateDispTypeInfo(
5797 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
5798 LCID lcid
, /* [I] Locale Id */
5799 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
5801 ITypeInfoImpl
*pTIImpl
;
5803 TLBFuncDesc
**ppFuncDesc
;
5805 pTIImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
5806 pTIImpl
->pTypeLib
= NULL
;
5808 pTIImpl
->Name
= NULL
;
5809 pTIImpl
->dwHelpContext
= -1;
5810 memset(&pTIImpl
->TypeAttr
.guid
, 0, sizeof(GUID
));
5811 pTIImpl
->TypeAttr
.lcid
= lcid
;
5812 pTIImpl
->TypeAttr
.typekind
= TKIND_COCLASS
;
5813 pTIImpl
->TypeAttr
.wMajorVerNum
= 0;
5814 pTIImpl
->TypeAttr
.wMinorVerNum
= 0;
5815 pTIImpl
->TypeAttr
.cbAlignment
= 2;
5816 pTIImpl
->TypeAttr
.cbSizeInstance
= -1;
5817 pTIImpl
->TypeAttr
.cbSizeVft
= -1;
5818 pTIImpl
->TypeAttr
.cFuncs
= 0;
5819 pTIImpl
->TypeAttr
.cImplTypes
= 1;
5820 pTIImpl
->TypeAttr
.cVars
= 0;
5821 pTIImpl
->TypeAttr
.wTypeFlags
= 0;
5823 ppFuncDesc
= &pTIImpl
->funclist
;
5824 for(func
= 0; func
< pidata
->cMembers
; func
++) {
5825 METHODDATA
*md
= pidata
->pmethdata
+ func
;
5826 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
5827 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
5828 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
5829 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
5830 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
5831 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
5832 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
5833 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
;
5834 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0; /*??*/
5835 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
5836 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5837 md
->cArgs
* sizeof(ELEMDESC
));
5838 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5839 md
->cArgs
* sizeof(TLBParDesc
));
5840 for(param
= 0; param
< md
->cArgs
; param
++) {
5841 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
5842 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
5844 ppFuncDesc
= &(*ppFuncDesc
)->next
;
5846 *pptinfo
= (ITypeInfo
*)pTIImpl
;
5851 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5853 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5855 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
5858 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
5860 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5862 return ITypeInfo_AddRef((ITypeInfo
*)This
);
5865 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
5867 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5869 return ITypeInfo_Release((ITypeInfo
*)This
);
5872 static HRESULT WINAPI
ITypeComp_fnBind(
5877 ITypeInfo
** ppTInfo
,
5878 DESCKIND
* pDescKind
,
5881 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5882 TLBFuncDesc
* pFDesc
;
5883 TLBVarDesc
* pVDesc
;
5885 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5887 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
5888 if (pFDesc
->funcdesc
.invkind
& wFlags
)
5889 if (!strcmpW(pFDesc
->Name
, szName
)) {
5895 *pDescKind
= DESCKIND_FUNCDESC
;
5896 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
5897 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5900 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
5902 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
5903 if (!strcmpW(pVDesc
->Name
, szName
)) {
5904 *pDescKind
= DESCKIND_VARDESC
;
5905 pBindPtr
->lpvardesc
= &pVDesc
->vardesc
;
5906 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5912 /* not found, look for it in inherited interfaces */
5913 if (This
->TypeAttr
.cImplTypes
&&
5914 (This
->TypeAttr
.typekind
== TKIND_INTERFACE
|| This
->TypeAttr
.typekind
== TKIND_DISPATCH
)) {
5915 /* recursive search */
5919 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
5922 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
5923 ITypeInfo_Release(pTInfo
);
5927 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5928 ITypeComp_Release(pTComp
);
5931 WARN("Could not search inherited interface!\n");
5933 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
5934 *pDescKind
= DESCKIND_NONE
;
5935 pBindPtr
->lpfuncdesc
= NULL
;
5937 return DISP_E_MEMBERNOTFOUND
;
5940 static HRESULT WINAPI
ITypeComp_fnBindType(
5944 ITypeInfo
** ppTInfo
,
5945 ITypeComp
** ppTComp
)
5947 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5949 /* strange behaviour (does nothing) but like the
5952 if (!ppTInfo
|| !ppTComp
)
5961 static ITypeCompVtbl tcompvt
=
5964 ITypeComp_fnQueryInterface
,
5966 ITypeComp_fnRelease
,
5969 ITypeComp_fnBindType