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 */
295 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
298 /******************************************************************************
299 * LoadTypeLibEx [OLEAUT32.183]
300 * Loads and optionally registers a type library
306 HRESULT WINAPI
LoadTypeLibEx(
307 LPCOLESTR szFile
, /* [in] Name of file to load from */
308 REGKIND regkind
, /* [in] Specify kind of registration */
309 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
311 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
316 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
319 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
322 /* Look for a trailing '\\' followed by an index */
323 pIndexStr
= strrchrW(szFile
, '\\');
324 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
325 index
= atoiW(pIndexStr
);
326 memcpy(szFileCopy
, szFile
,
327 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
328 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
329 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
331 return TYPE_E_CANTLOADLIBRARY
;
332 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
333 return TYPE_E_CANTLOADLIBRARY
;
336 static const WCHAR stdole32tlb
[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
339 lstrcpyW(tstpath
,szFile
);
341 for (i
=0;i
<strlenW(tstpath
);i
++) {
342 if (tstpath
[i
] == 's') {
343 if (!strcmpW(tstpath
+i
,stdole32tlb
)) {
345 MESSAGE("**************************************************************************\n");
346 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
347 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
348 MESSAGE("on the Microsoft Download Pages.\n");
349 MESSAGE("**************************************************************************\n");
354 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile
));
355 return TYPE_E_CANTLOADLIBRARY
;
359 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
361 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
366 case REGKIND_DEFAULT
:
367 /* don't register typelibs supplied with full path. Experimentation confirms the following */
369 ((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
370 (szFile
[0] && (szFile
[1] == ':'))) break;
371 /* else fall-through */
373 case REGKIND_REGISTER
:
374 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
376 IUnknown_Release(*pptLib
);
384 TRACE(" returns %08lx\n",res
);
388 /******************************************************************************
389 * LoadRegTypeLib [OLEAUT32.162]
391 HRESULT WINAPI
LoadRegTypeLib(
392 REFGUID rguid
, /* [in] referenced guid */
393 WORD wVerMajor
, /* [in] major version */
394 WORD wVerMinor
, /* [in] minor version */
395 LCID lcid
, /* [in] locale id */
396 ITypeLib
**ppTLib
) /* [out] path of typelib */
399 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
403 res
= LoadTypeLib(bstr
, ppTLib
);
407 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
413 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
414 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
415 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
416 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
417 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
418 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
420 /******************************************************************************
421 * RegisterTypeLib [OLEAUT32.163]
422 * Adds information about a type library to the System Registry
424 * Docs: ITypeLib FAR * ptlib
425 * Docs: OLECHAR FAR* szFullPath
426 * Docs: OLECHAR FAR* szHelpDir
432 HRESULT WINAPI
RegisterTypeLib(
433 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
434 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
435 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
438 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
439 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
440 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
450 if (ptlib
== NULL
|| szFullPath
== NULL
)
453 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
456 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
459 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
460 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
464 /* Set the human-readable name of the typelib */
465 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
467 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
468 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
476 /* Make up the name of the typelib path subkey */
477 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
479 /* Create the typelib path subkey */
480 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
481 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
483 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
484 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
492 /* Create the flags subkey */
493 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
494 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
496 /* FIXME: is %u correct? */
497 static const WCHAR formatW
[] = {'%','u',0};
499 sprintfW(buf
, formatW
, attr
->wLibFlags
);
500 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
501 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
509 /* create the helpdir subkey */
510 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
511 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
513 BOOL freeHelpDir
= FALSE
;
516 /* if we created a new key, and helpDir was null, set the helpdir
517 to the directory which contains the typelib. However,
518 if we just opened an existing key, we leave the helpdir alone */
519 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
520 szHelpDir
= SysAllocString(szFullPath
);
521 pIndexStr
= strrchrW(szHelpDir
, '\\');
528 /* if we have an szHelpDir, set it! */
529 if (szHelpDir
!= NULL
) {
530 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
531 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
537 if (freeHelpDir
) SysFreeString(szHelpDir
);
549 /* register OLE Automation-compatible interfaces for this typelib */
550 types
= ITypeLib_GetTypeInfoCount(ptlib
);
551 for (tidx
=0; tidx
<types
; tidx
++) {
552 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
553 LPOLESTR name
= NULL
;
554 ITypeInfo
*tinfo
= NULL
;
556 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
559 case TKIND_INTERFACE
:
560 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
561 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
565 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
566 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
570 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
575 TYPEATTR
*tattr
= NULL
;
576 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
579 TRACE_(typelib
)("guid=%s, flags=%04x (",
580 debugstr_guid(&tattr
->guid
),
583 if (TRACE_ON(typelib
)) {
584 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
605 * FIXME: The 1 is just here until we implement rpcrt4
606 * stub/proxy handling. Until then it helps IShield
609 if (1 || (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
))
611 if (!(tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) {
612 FIXME("Registering non-oleautomation interface!\n");
615 /* register interface<->typelib coupling */
616 get_interface_key( &tattr
->guid
, keyName
);
617 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
618 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
621 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
622 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
624 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
625 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
626 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
627 (BYTE
*)PSOA
, sizeof PSOA
);
631 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
632 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
633 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
634 (BYTE
*)PSOA
, sizeof PSOA
);
638 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
639 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
642 static const WCHAR fmtver
[] = {'%','u','.','%','u',0 };
643 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
645 StringFromGUID2(&attr
->guid
, buffer
, 40);
646 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
647 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
648 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
649 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
650 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
658 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
661 ITypeInfo_Release(tinfo
);
668 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
674 /******************************************************************************
675 * UnRegisterTypeLib [OLEAUT32.186]
676 * Removes information about a type library from the System Registry
683 HRESULT WINAPI
UnRegisterTypeLib(
684 REFGUID libid
, /* [in] Guid of the library */
685 WORD wVerMajor
, /* [in] major version */
686 WORD wVerMinor
, /* [in] minor version */
687 LCID lcid
, /* [in] locale id */
690 BSTR tlibPath
= NULL
;
693 WCHAR subKeyName
[50];
696 BOOL deleteOtherStuff
;
699 TYPEATTR
* typeAttr
= NULL
;
701 ITypeInfo
* typeInfo
= NULL
;
702 ITypeLib
* typeLib
= NULL
;
705 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
707 /* Create the path to the key */
708 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
710 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
712 TRACE("Unsupported syskind %i\n", syskind
);
713 result
= E_INVALIDARG
;
717 /* get the path to the typelib on disk */
718 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
719 result
= E_INVALIDARG
;
723 /* Try and open the key to the type library. */
724 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != S_OK
) {
725 result
= E_INVALIDARG
;
729 /* Try and load the type library */
730 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
731 result
= TYPE_E_INVALIDSTATE
;
735 /* remove any types registered with this typelib */
736 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
737 for (i
=0; i
<numTypes
; i
++) {
738 /* get the kind of type */
739 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
743 /* skip non-interfaces, and get type info for the type */
744 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
747 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
750 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
754 /* the path to the type */
755 get_interface_key( &typeAttr
->guid
, subKeyName
);
757 /* Delete its bits */
758 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != S_OK
) {
761 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
762 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
763 RegDeleteKeyW(subKey
, TypeLibW
);
766 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
769 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
771 if (typeInfo
) ITypeInfo_Release(typeInfo
);
775 /* Now, delete the type library path subkey */
776 get_lcid_subkey( lcid
, syskind
, subKeyName
);
777 RegDeleteKeyW(key
, subKeyName
);
778 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
779 RegDeleteKeyW(key
, subKeyName
);
781 /* check if there is anything besides the FLAGS/HELPDIR keys.
782 If there is, we don't delete them */
783 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
784 deleteOtherStuff
= TRUE
;
786 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == S_OK
) {
787 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
789 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
790 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
791 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
792 deleteOtherStuff
= FALSE
;
796 /* only delete the other parts of the key if we're absolutely sure */
797 if (deleteOtherStuff
) {
798 RegDeleteKeyW(key
, FLAGSW
);
799 RegDeleteKeyW(key
, HELPDIRW
);
803 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
804 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
805 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
809 if (tlibPath
) SysFreeString(tlibPath
);
810 if (typeLib
) ITypeLib_Release(typeLib
);
811 if (subKey
) RegCloseKey(subKey
);
812 if (key
) RegCloseKey(key
);
816 /*======================= ITypeLib implementation =======================*/
818 typedef struct tagTLBCustData
822 struct tagTLBCustData
* next
;
825 /* data structure for import typelibs */
826 typedef struct tagTLBImpLib
828 int offset
; /* offset in the file (MSFT)
829 offset in nametable (SLTG)
830 just used to identify library while reading
832 GUID guid
; /* libid */
833 BSTR name
; /* name */
835 LCID lcid
; /* lcid of imported typelib */
837 WORD wVersionMajor
; /* major version number */
838 WORD wVersionMinor
; /* minor version number */
840 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
841 NULL if not yet loaded */
842 struct tagTLBImpLib
* next
;
845 /* internal ITypeLib data */
846 typedef struct tagITypeLibImpl
848 ITypeLib2Vtbl
*lpVtbl
;
849 ITypeCompVtbl
*lpVtblTypeComp
;
851 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
853 /* strings can be stored in tlb as multibyte strings BUT they are *always*
854 * exported to the application as a UNICODE string.
860 unsigned long dwHelpContext
;
861 int TypeInfoCount
; /* nr of typeinfo's in librarry */
862 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
863 int ctCustData
; /* number of items in cust data list */
864 TLBCustData
* pCustData
; /* linked list to cust data */
865 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
866 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
867 libary. Only used while read MSFT
870 /* typelibs are cached, keyed by path, so store the linked list info within them */
871 struct tagITypeLibImpl
*next
, *prev
;
875 static struct ITypeLib2Vtbl tlbvt
;
876 static struct ITypeCompVtbl tlbtcvt
;
878 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
879 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
881 /* ITypeLib methods */
882 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
883 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
885 /*======================= ITypeInfo implementation =======================*/
887 /* data for refernced types */
888 typedef struct tagTLBRefType
890 INT index
; /* Type index for internal ref or for external ref
891 it the format is SLTG. -2 indicates to
894 GUID guid
; /* guid of the referenced type */
895 /* if index == TLB_REF_USE_GUID */
897 HREFTYPE reference
; /* The href of this ref */
898 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
899 TLB_REF_INTERNAL for internal refs
900 TLB_REF_NOT_FOUND for broken refs */
902 struct tagTLBRefType
* next
;
905 #define TLB_REF_USE_GUID -2
907 #define TLB_REF_INTERNAL (void*)-2
908 #define TLB_REF_NOT_FOUND (void*)-1
910 /* internal Parameter data */
911 typedef struct tagTLBParDesc
915 TLBCustData
* pCustData
; /* linked list to cust data */
918 /* internal Function data */
919 typedef struct tagTLBFuncDesc
921 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
922 BSTR Name
; /* the name of this function */
923 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
925 int HelpStringContext
;
927 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
929 TLBCustData
* pCustData
; /* linked list to cust data; */
930 struct tagTLBFuncDesc
* next
;
933 /* internal Variable data */
934 typedef struct tagTLBVarDesc
936 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
937 BSTR Name
; /* the name of this variable */
939 int HelpStringContext
; /* FIXME: where? */
942 TLBCustData
* pCustData
;/* linked list to cust data; */
943 struct tagTLBVarDesc
* next
;
946 /* internal implemented interface data */
947 typedef struct tagTLBImplType
949 HREFTYPE hRef
; /* hRef of interface */
950 int implflags
; /* IMPLFLAG_*s */
952 TLBCustData
* pCustData
;/* linked list to custom data; */
953 struct tagTLBImplType
*next
;
956 /* internal TypeInfo data */
957 typedef struct tagITypeInfoImpl
959 ITypeInfo2Vtbl
*lpVtbl
;
960 ITypeCompVtbl
*lpVtblTypeComp
;
962 TYPEATTR TypeAttr
; /* _lots_ of type information. */
963 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
964 int index
; /* index in this typelib; */
965 /* type libs seem to store the doc strings in ascii
966 * so why should we do it in unicode?
970 unsigned long dwHelpContext
;
971 unsigned long dwHelpStringContext
;
974 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
977 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
979 /* Implemented Interfaces */
980 TLBImplType
* impltypelist
;
982 TLBRefType
* reflist
;
984 TLBCustData
* pCustData
; /* linked list to cust data; */
985 struct tagITypeInfoImpl
* next
;
988 static struct ITypeInfo2Vtbl tinfvt
;
989 static struct ITypeCompVtbl tcompvt
;
991 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
993 typedef struct tagTLBContext
995 unsigned int oStart
; /* start of TLB in file */
996 unsigned int pos
; /* current pos */
997 unsigned int length
; /* total length */
998 void *mapping
; /* memory mapping */
999 MSFT_SegDir
* pTblDir
;
1000 ITypeLibImpl
* pLibInfo
;
1004 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
1009 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
1010 if (pTD
->vt
& VT_RESERVED
)
1011 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1012 if (pTD
->vt
& VT_BYREF
)
1013 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1014 if (pTD
->vt
& VT_ARRAY
)
1015 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1016 if (pTD
->vt
& VT_VECTOR
)
1017 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1018 switch(pTD
->vt
& VT_TYPEMASK
) {
1019 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1020 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1021 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1022 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1023 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1024 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1025 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1026 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1027 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1028 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1029 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1030 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1031 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1032 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1033 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1034 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1035 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1036 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1037 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1038 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1039 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
1040 pTD
->u
.hreftype
); break;
1041 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1042 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1044 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1045 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1047 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1048 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1049 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1052 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1056 void dump_ELEMDESC(ELEMDESC
*edesc
) {
1058 dump_TypeDesc(&edesc
->tdesc
,buf
);
1059 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1060 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
1061 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1063 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
1065 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
1066 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1067 MESSAGE("Param %d:\n",i
);
1068 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1070 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1071 switch (funcdesc
->funckind
) {
1072 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1073 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1074 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1075 case FUNC_STATIC
: MESSAGE("static");break;
1076 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1077 default: MESSAGE("unknown");break;
1079 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1080 switch (funcdesc
->invkind
) {
1081 case INVOKE_FUNC
: MESSAGE("func");break;
1082 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1083 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1084 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1086 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1087 switch (funcdesc
->callconv
) {
1088 case CC_CDECL
: MESSAGE("cdecl");break;
1089 case CC_PASCAL
: MESSAGE("pascal");break;
1090 case CC_STDCALL
: MESSAGE("stdcall");break;
1091 case CC_SYSCALL
: MESSAGE("syscall");break;
1094 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1095 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1096 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1098 MESSAGE("\telemdescFunc (return value type):\n");
1099 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1102 void dump_IDLDESC(IDLDESC
*idl
) {
1103 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
1106 static const char * typekind_desc
[] =
1119 void dump_TYPEATTR(TYPEATTR
*tattr
) {
1121 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
1122 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
1123 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
1124 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
1125 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
1126 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
1127 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
1128 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
1129 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
1130 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
1131 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
1132 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
1133 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
1134 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
1135 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
1136 MESSAGE("\ttypedesc: %s\n", buf
);
1137 dump_IDLDESC(&tattr
->idldescType
);
1140 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
1143 if (!TRACE_ON(typelib
))
1145 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1146 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1147 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1150 dump_FUNCDESC(&(pfd
->funcdesc
));
1152 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1153 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1155 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
1159 dump_TLBFuncDescOne(pfd
);
1163 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
1167 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1172 static void dump_TLBImpLib(TLBImpLib
*import
)
1174 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1175 debugstr_w(import
->name
));
1176 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1177 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1180 static void dump_TLBRefType(TLBRefType
* prt
)
1184 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1185 if(prt
->index
== -1)
1186 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1188 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1190 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1191 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1192 TRACE_(typelib
)("in lib\n");
1193 dump_TLBImpLib(prt
->pImpTLInfo
);
1199 static void dump_TLBImplType(TLBImplType
* impl
)
1203 "implementing/inheriting interface hRef = %lx implflags %x\n",
1204 impl
->hRef
, impl
->implflags
);
1209 void dump_Variant(VARIANT
* pvar
)
1213 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1217 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1218 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1220 TRACE(",%p", V_BYREF(pvar
));
1222 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1226 else switch (V_TYPE(pvar
))
1228 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1229 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1230 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1231 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1233 case VT_I4
: TRACE(",%ld", V_I4(pvar
)); break;
1235 case VT_UI4
: TRACE(",%ld", V_UI4(pvar
)); break;
1236 case VT_I8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_I8(pvar
) >> 32),
1237 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1238 case VT_UI8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_UI8(pvar
) >> 32),
1239 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1240 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1241 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1242 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1243 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1244 case VT_CY
: TRACE(",0x%08lx,0x%08lx", V_CY(pvar
).s
.Hi
,
1245 V_CY(pvar
).s
.Lo
); break;
1247 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1248 TRACE(",<invalid>");
1250 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1251 st
.wHour
, st
.wMinute
, st
.wSecond
);
1255 case VT_USERDEFINED
:
1257 case VT_NULL
: break;
1258 default: TRACE(",?"); break;
1264 static void dump_DispParms(DISPPARAMS
* pdp
)
1268 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1270 while (index
< pdp
->cArgs
)
1272 dump_Variant( &pdp
->rgvarg
[index
] );
1277 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1279 TRACE("%p ref=%lu\n", pty
, pty
->ref
);
1280 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1281 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1282 TRACE("fct:%u var:%u impl:%u\n",
1283 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1284 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1285 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1286 dump_TLBFuncDesc(pty
->funclist
);
1287 dump_TLBVarDesc(pty
->varlist
);
1288 dump_TLBImplType(pty
->impltypelist
);
1291 void dump_VARDESC(VARDESC
*v
)
1293 MESSAGE("memid %ld\n",v
->memid
);
1294 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1295 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1296 dump_ELEMDESC(&(v
->elemdescVar
));
1297 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1298 MESSAGE("varkind %d\n",v
->varkind
);
1301 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1303 /* VT_LPWSTR is largest type that */
1304 /* may appear in type description*/
1305 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1306 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1307 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1308 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1309 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1310 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1314 static void TLB_abort()
1318 static void * TLB_Alloc(unsigned size
)
1321 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1323 ERR("cannot allocate memory\n");
1328 static void TLB_Free(void * ptr
)
1330 HeapFree(GetProcessHeap(), 0, ptr
);
1333 /* deep copy a typedesc */
1334 static void copy_typedesc(TYPEDESC
*out
, const TYPEDESC
*in
)
1339 out
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC
));
1340 copy_typedesc(out
->u
.lptdesc
, in
->u
.lptdesc
);
1342 case VT_USERDEFINED
:
1343 out
->u
.hreftype
= in
->u
.hreftype
;
1346 out
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC
) +
1347 (in
->u
.lpadesc
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
1348 copy_typedesc(&out
->u
.lpadesc
->tdescElem
, &in
->u
.lpadesc
->tdescElem
);
1349 out
->u
.lpadesc
->cDims
= in
->u
.lpadesc
->cDims
;
1350 memcpy(out
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->cDims
* sizeof(SAFEARRAYBOUND
));
1357 /* free()s any allocated memory pointed to by the tdesc. NB does not
1358 free the tdesc itself - this is because the tdesc is typically part
1359 of a larger structure */
1360 static void free_deep_typedesc(TYPEDESC
*tdesc
)
1364 free_deep_typedesc(tdesc
->u
.lptdesc
);
1365 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lptdesc
);
1366 tdesc
->u
.lptdesc
= NULL
;
1369 free_deep_typedesc(&tdesc
->u
.lpadesc
->tdescElem
);
1370 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lpadesc
);
1371 tdesc
->u
.lpadesc
= NULL
;
1378 /**********************************************************************
1380 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1383 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1385 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1386 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1388 if (where
!= DO_NOT_SEEK
)
1390 where
+= pcx
->oStart
;
1391 if (where
> pcx
->length
)
1394 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1399 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1400 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1405 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1410 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1411 FromLEDWords(buffer
, ret
);
1416 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1421 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1422 FromLEWords(buffer
, ret
);
1427 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1429 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1430 memset(pGuid
,0, sizeof(GUID
));
1433 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1434 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1435 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1436 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1437 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1440 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1443 MSFT_NameIntro niName
;
1445 WCHAR
* pwstring
= NULL
;
1446 BSTR bstrName
= NULL
;
1448 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1449 pcx
->pTblDir
->pNametab
.offset
+offset
);
1450 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1451 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1452 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1453 name
[niName
.namelen
& 0xff]='\0';
1455 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1458 /* no invalid characters in string */
1461 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1463 /* don't check for invalid character since this has been done previously */
1464 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1466 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1467 lengthInChars
= SysStringLen(bstrName
);
1468 HeapFree(GetProcessHeap(), 0, pwstring
);
1471 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1475 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1482 if(offset
<0) return NULL
;
1483 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1484 if(length
<= 0) return 0;
1485 string
=TLB_Alloc(length
+1);
1486 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1487 string
[length
]='\0';
1489 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1490 string
, -1, NULL
, 0);
1492 /* no invalid characters in string */
1495 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1497 /* don't check for invalid character since this has been done previously */
1498 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1500 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1501 lengthInChars
= SysStringLen(bstr
);
1502 HeapFree(GetProcessHeap(), 0, pwstring
);
1505 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1509 * read a value and fill a VARIANT structure
1511 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1515 TRACE_(typelib
)("\n");
1517 if(offset
<0) { /* data are packed in here */
1518 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1519 V_UNION(pVar
, iVal
) = offset
& 0x3ffffff;
1522 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1523 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1524 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1525 switch (V_VT(pVar
)){
1526 case VT_EMPTY
: /* FIXME: is this right? */
1527 case VT_NULL
: /* FIXME: is this right? */
1528 case VT_I2
: /* this should not happen */
1539 case VT_VOID
: /* FIXME: is this right? */
1547 case VT_DECIMAL
: /* FIXME: is this right? */
1550 /* pointer types with known behaviour */
1553 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1555 FIXME("BSTR length = %d?\n", size
);
1557 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1558 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1559 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1560 /* FIXME: do we need a AtoW conversion here? */
1561 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1562 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1567 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1574 case VT_USERDEFINED
:
1580 case VT_STREAMED_OBJECT
:
1581 case VT_STORED_OBJECT
:
1582 case VT_BLOB_OBJECT
:
1587 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1591 if(size
>0) /* (big|small) endian correct? */
1592 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1596 * create a linked list with custom data
1598 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1604 TRACE_(typelib
)("\n");
1608 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1609 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1610 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1611 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1612 /* add new custom data at head of the list */
1613 pNew
->next
=*ppCustData
;
1615 offset
= entry
.next
;
1620 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1624 pTd
->vt
=type
& VT_TYPEMASK
;
1626 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1628 if(pTd
->vt
== VT_USERDEFINED
)
1629 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1631 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1635 MSFT_DoFuncs(TLBContext
* pcx
,
1640 TLBFuncDesc
** pptfd
)
1643 * member information is stored in a data structure at offset
1644 * indicated by the memoffset field of the typeinfo structure
1645 * There are several distinctive parts.
1646 * the first part starts with a field that holds the total length
1647 * of this (first) part excluding this field. Then follow the records,
1648 * for each member there is one record.
1650 * First entry is always the length of the record (including this
1652 * Rest of the record depends on the type of the member. If there is
1653 * a field indicating the member type (function variable intereface etc)
1654 * I have not found it yet. At this time we depend on the information
1655 * in the type info and the usual order how things are stored.
1657 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1660 * Third is a equal sized array with file offsets to the name entry
1663 * Forth and last (?) part is an array with offsets to the records in the
1664 * first part of this file segment.
1667 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1668 int recoffset
= offset
+ sizeof(INT
);
1671 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1673 TRACE_(typelib
)("\n");
1675 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1677 for ( i
= 0; i
< cFuncs
; i
++ )
1679 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1681 /* name, eventually add to a hash table */
1682 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1683 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1685 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1687 /* read the function information record */
1688 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1692 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1694 /* do the attributes */
1695 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1698 if ( nrattributes
> 0 )
1700 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1702 if ( nrattributes
> 1 )
1704 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1705 pFuncRec
->OptAttr
[1]) ;
1707 if ( nrattributes
> 2 )
1709 if ( pFuncRec
->FKCCIC
& 0x2000 )
1711 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1715 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1716 pFuncRec
->OptAttr
[2]);
1718 if( nrattributes
> 5 )
1720 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1722 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1725 pFuncRec
->OptAttr
[6],
1726 &(*pptfd
)->pCustData
);
1733 /* fill the FuncDesc Structure */
1734 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1735 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1737 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1738 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1739 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1740 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1741 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1742 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1743 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1747 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1750 /* do the parameters/arguments */
1751 if(pFuncRec
->nrargs
)
1754 MSFT_ParameterInfo paraminfo
;
1756 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1757 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1759 (*pptfd
)->pParamDesc
=
1760 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1762 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1763 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1765 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1767 TYPEDESC
* lpArgTypeDesc
= 0;
1771 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1774 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1776 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1778 /* SEEK value = jump to offset,
1779 * from there jump to the end of record,
1780 * go back by (j-1) arguments
1782 MSFT_ReadLEDWords( ¶minfo
,
1783 sizeof(MSFT_ParameterInfo
), pcx
,
1784 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1785 * sizeof(MSFT_ParameterInfo
)));
1787 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1789 while ( lpArgTypeDesc
!= NULL
)
1791 switch ( lpArgTypeDesc
->vt
)
1794 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1798 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1801 case VT_USERDEFINED
:
1802 MSFT_DoRefType(pcx
, pTI
,
1803 lpArgTypeDesc
->u
.hreftype
);
1805 lpArgTypeDesc
= NULL
;
1809 lpArgTypeDesc
= NULL
;
1815 /* parameter is the return value! */
1816 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1818 TYPEDESC
* lpArgTypeDesc
;
1820 (*pptfd
)->funcdesc
.elemdescFunc
=
1821 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1823 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1825 while ( lpArgTypeDesc
!= NULL
)
1827 switch ( lpArgTypeDesc
->vt
)
1830 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1834 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1838 case VT_USERDEFINED
:
1841 lpArgTypeDesc
->u
.hreftype
);
1843 lpArgTypeDesc
= NULL
;
1847 lpArgTypeDesc
= NULL
;
1852 /* second time around */
1853 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1856 (*pptfd
)->pParamDesc
[j
].Name
=
1857 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1860 if ( (PARAMFLAG_FHASDEFAULT
&
1861 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1862 ((pFuncRec
->FKCCIC
) & 0x1000) )
1864 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1866 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1868 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1870 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1871 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1873 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1877 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1880 pFuncRec
->OptAttr
[7+j
],
1881 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1886 /* scode is not used: archaic win16 stuff FIXME: right? */
1887 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1888 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1890 pptfd
= & ((*pptfd
)->next
);
1891 recoffset
+= reclength
;
1895 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1896 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1898 int infolen
, nameoffset
, reclength
;
1900 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1904 TRACE_(typelib
)("\n");
1906 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1907 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1908 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1909 recoffset
+= offset
+sizeof(INT
);
1910 for(i
=0;i
<cVars
;i
++){
1911 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1912 /* name, eventually add to a hash table */
1913 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1914 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1915 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1916 /* read the variable information record */
1917 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1919 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1921 if(reclength
>(6*sizeof(INT
)) )
1922 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1923 if(reclength
>(7*sizeof(INT
)) )
1924 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1925 if(reclength
>(8*sizeof(INT
)) )
1926 if(reclength
>(9*sizeof(INT
)) )
1927 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1928 /* fill the VarDesc Structure */
1929 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1930 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1931 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1932 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1933 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1934 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1935 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1936 if(pVarRec
->VarKind
== VAR_CONST
){
1937 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1938 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1939 pVarRec
->OffsValue
, pcx
);
1941 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1942 pptvd
=&((*pptvd
)->next
);
1943 recoffset
+= reclength
;
1946 /* fill in data for a hreftype (offset). When the refernced type is contained
1947 * in the typelib, it's just an (file) offset in the type info base dir.
1948 * If comes from import, it's an offset+1 in the ImpInfo table
1950 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1954 TLBRefType
**ppRefType
= &pTI
->reflist
;
1956 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1959 if((*ppRefType
)->reference
== offset
)
1961 ppRefType
= &(*ppRefType
)->next
;
1964 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1965 sizeof(**ppRefType
));
1967 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1968 /* external typelib */
1969 MSFT_ImpInfo impinfo
;
1970 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1972 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1974 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1975 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1976 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1977 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1978 pImpLib
=pImpLib
->next
;
1981 (*ppRefType
)->reference
=offset
;
1982 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1983 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1984 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1986 ERR("Cannot find a reference\n");
1987 (*ppRefType
)->reference
=-1;
1988 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1991 /* in this typelib */
1992 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1993 (*ppRefType
)->reference
=offset
;
1994 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1998 /* process Implemented Interfaces of a com class */
1999 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2003 MSFT_RefRecord refrec
;
2004 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2006 TRACE_(typelib
)("\n");
2008 for(i
=0;i
<count
;i
++){
2009 if(offset
<0) break; /* paranoia */
2010 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2011 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2012 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
2013 (*ppImpl
)->hRef
= refrec
.reftype
;
2014 (*ppImpl
)->implflags
=refrec
.flags
;
2015 (*ppImpl
)->ctCustData
=
2016 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2017 offset
=refrec
.onext
;
2018 ppImpl
=&((*ppImpl
)->next
);
2022 * process a typeinfo record
2024 ITypeInfoImpl
* MSFT_DoTypeInfo(
2027 ITypeLibImpl
* pLibInfo
)
2029 MSFT_TypeInfoBase tiBase
;
2030 ITypeInfoImpl
*ptiRet
;
2032 TRACE_(typelib
)("count=%u\n", count
);
2034 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2035 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2036 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2037 /* this is where we are coming from */
2038 ptiRet
->pTypeLib
= pLibInfo
;
2039 ptiRet
->index
=count
;
2040 /* fill in the typeattr fields */
2041 WARN("Assign constructor/destructor memid\n");
2043 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2044 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2045 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
2046 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
2047 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2048 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2049 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2050 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2051 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2052 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2053 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2054 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2055 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2056 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2057 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2058 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2059 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2060 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2063 /* IDLDESC idldescType; *//* never saw this one != zero */
2065 /* name, eventually add to a hash table */
2066 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2067 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2069 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2070 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2071 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2072 /* note: InfoType's Help file and HelpStringDll come from the containing
2073 * library. Further HelpString and Docstring appear to be the same thing :(
2076 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2077 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2078 ptiRet
->TypeAttr
.cVars
,
2079 tiBase
.memoffset
, & ptiRet
->funclist
);
2081 if(ptiRet
->TypeAttr
.cVars
>0 )
2082 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2083 ptiRet
->TypeAttr
.cVars
,
2084 tiBase
.memoffset
, & ptiRet
->varlist
);
2085 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2086 switch(ptiRet
->TypeAttr
.typekind
)
2089 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2092 case TKIND_DISPATCH
:
2093 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2095 if (tiBase
.datatype1
!= -1)
2097 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2098 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2101 { /* FIXME: This is a really bad hack to add IDispatch */
2102 const char* szStdOle
= "stdole2.tlb\0";
2103 int nStdOleLen
= strlen(szStdOle
);
2104 TLBRefType
**ppRef
= &ptiRet
->reflist
;
2107 if((*ppRef
)->reference
== -1)
2109 ppRef
= &(*ppRef
)->next
;
2112 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
2113 (*ppRef
)->guid
= IID_IDispatch
;
2114 (*ppRef
)->reference
= -1;
2115 (*ppRef
)->index
= TLB_REF_USE_GUID
;
2116 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
2117 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
2118 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
2121 MultiByteToWideChar(CP_ACP
,
2125 (*ppRef
)->pImpTLInfo
->name
,
2126 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
2128 (*ppRef
)->pImpTLInfo
->lcid
= 0;
2129 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
2130 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
2135 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2136 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2137 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2142 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2144 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2145 debugstr_w(ptiRet
->Name
),
2146 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2147 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2152 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2153 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2154 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2157 static ITypeLibImpl
*tlb_cache_first
;
2158 static CRITICAL_SECTION cache_section
;
2159 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2161 0, 0, &cache_section
,
2162 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2163 0, 0, { 0, (DWORD
)(__FILE__
": typelib loader cache") }
2165 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2168 /****************************************************************************
2171 * find the type of the typelib file and map the typelib resource into
2174 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2175 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2176 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2178 ITypeLibImpl
*entry
;
2179 int ret
= TYPE_E_CANTLOADLIBRARY
;
2180 DWORD dwSignature
= 0;
2183 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2187 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2188 EnterCriticalSection(&cache_section
);
2189 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2191 if (!strcmpiW(entry
->path
, pszFileName
))
2193 TRACE("cache hit\n");
2194 *ppTypeLib
= (ITypeLib2
*)entry
;
2195 ITypeLib_AddRef(*ppTypeLib
);
2196 LeaveCriticalSection(&cache_section
);
2200 LeaveCriticalSection(&cache_section
);
2202 /* check the signature of the file */
2203 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2204 if (INVALID_HANDLE_VALUE
!= hFile
)
2206 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2209 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2212 /* retrieve file size */
2213 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2215 /* first try to load as *.tlb */
2216 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2217 if ( dwSignature
== MSFT_SIGNATURE
)
2219 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2221 else if ( dwSignature
== SLTG_SIGNATURE
)
2223 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2225 UnmapViewOfFile(pBase
);
2227 CloseHandle(hMapping
);
2232 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
2234 /* find the typelibrary resource*/
2235 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2236 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2239 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2240 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2243 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2246 LPVOID pBase
= LockResource(hGlobal
);
2247 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2251 /* try to load as incore resource */
2252 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2253 if ( dwSignature
== MSFT_SIGNATURE
)
2255 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2257 else if ( dwSignature
== SLTG_SIGNATURE
)
2259 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2263 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2266 FreeResource( hGlobal
);
2269 FreeLibrary(hinstDLL
);
2274 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2276 TRACE("adding to cache\n");
2277 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2278 lstrcpyW(impl
->path
, pszFileName
);
2279 /* We should really canonicalise the path here. */
2281 /* FIXME: check if it has added already in the meantime */
2282 EnterCriticalSection(&cache_section
);
2283 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2285 tlb_cache_first
= impl
;
2286 LeaveCriticalSection(&cache_section
);
2289 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2294 /*================== ITypeLib(2) Methods ===================================*/
2296 /****************************************************************************
2297 * ITypeLib2_Constructor_MSFT
2299 * loading an MSFT typelib from an in-memory image
2301 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2305 MSFT_Header tlbHeader
;
2306 MSFT_SegDir tlbSegDir
;
2307 ITypeLibImpl
* pTypeLibImpl
;
2309 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2311 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2312 if (!pTypeLibImpl
) return NULL
;
2314 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2315 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2316 pTypeLibImpl
->ref
= 1;
2318 /* get pointer to beginning of typelib data */
2322 cx
.pLibInfo
= pTypeLibImpl
;
2323 cx
.length
= dwTLBLength
;
2326 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2328 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2329 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2330 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2333 /* there is a small amount of information here until the next important
2335 * the segment directory . Try to calculate the amount of data */
2336 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2338 /* now read the segment directory */
2339 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2340 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2341 cx
.pTblDir
= &tlbSegDir
;
2343 /* just check two entries */
2344 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2346 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2347 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2351 /* now fill our internal data */
2352 /* TLIBATTR fields */
2353 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2355 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2356 /* Windows seems to have zero here, is this correct? */
2357 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2358 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2360 pTypeLibImpl
->LibAttr
.lcid
= 0;
2362 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2363 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2364 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2365 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2367 /* name, eventually add to a hash table */
2368 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2371 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2372 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2374 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2377 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2378 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2381 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2384 if(tlbHeader
.CustomDataOffset
>= 0)
2386 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2389 /* fill in typedescriptions */
2390 if(tlbSegDir
.pTypdescTab
.length
> 0)
2392 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2394 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2395 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2398 /* FIXME: add several sanity checks here */
2399 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2400 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2402 /* FIXME: check safearray */
2404 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2406 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2408 else if(td
[0] == VT_CARRAY
)
2410 /* array descr table here */
2411 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2413 else if(td
[0] == VT_USERDEFINED
)
2415 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2417 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2420 /* second time around to fill the array subscript info */
2423 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2424 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2426 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2427 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2430 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2432 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2434 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2436 for(j
= 0; j
<td
[2]; j
++)
2438 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2439 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2440 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2441 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2446 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2447 ERR("didn't find array description data\n");
2452 /* imported type libs */
2453 if(tlbSegDir
.pImpFiles
.offset
>0)
2455 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2456 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2459 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2464 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2465 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2466 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2468 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2469 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2470 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2471 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2474 name
= TLB_Alloc(size
+1);
2475 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2476 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2477 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2478 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2481 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2482 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2484 ppImpLib
= &(*ppImpLib
)->next
;
2489 if(tlbHeader
.nrtypeinfos
>= 0 )
2491 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2492 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2495 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2497 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2499 ppTI
= &((*ppTI
)->next
);
2500 (pTypeLibImpl
->TypeInfoCount
)++;
2504 TRACE("(%p)\n", pTypeLibImpl
);
2505 return (ITypeLib2
*) pTypeLibImpl
;
2509 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2515 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2516 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2517 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2518 ret
= SysAllocString(nameW
);
2519 HeapFree(GetProcessHeap(), 0, nameW
);
2523 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2529 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2530 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2534 guid
->Data4
[0] = s
>> 8;
2535 guid
->Data4
[1] = s
& 0xff;
2538 for(i
= 0; i
< 6; i
++) {
2539 memcpy(b
, str
+ 24 + 2 * i
, 2);
2540 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2545 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2552 bytelen
= *(WORD
*)ptr
;
2553 if(bytelen
== 0xffff) return 2;
2554 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2555 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2556 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2557 *pBstr
= SysAllocStringLen(nameW
, len
);
2558 HeapFree(GetProcessHeap(), 0, nameW
);
2562 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2567 bytelen
= *(WORD
*)ptr
;
2568 if(bytelen
== 0xffff) return 2;
2569 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2570 memcpy(*str
, ptr
+ 2, bytelen
);
2571 (*str
)[bytelen
] = '\0';
2575 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2577 char *ptr
= pLibBlk
;
2580 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2581 FIXME("libblk magic = %04x\n", w
);
2586 if((w
= *(WORD
*)ptr
) != 0xffff) {
2587 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2592 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2594 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2596 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2599 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2602 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2603 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2605 pTypeLibImpl
->LibAttr
.lcid
= 0;
2608 ptr
+= 4; /* skip res12 */
2610 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2613 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2616 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2619 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2620 ptr
+= sizeof(GUID
);
2622 return ptr
- (char*)pLibBlk
;
2625 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2628 TYPEDESC
*pTD
= &pElem
->tdesc
;
2630 /* Handle [in/out] first */
2631 if((*pType
& 0xc000) == 0xc000)
2632 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2633 else if(*pType
& 0x8000)
2634 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2635 else if(*pType
& 0x4000)
2636 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2638 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2641 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2644 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2647 if((*pType
& 0xe00) == 0xe00) {
2649 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2651 pTD
= pTD
->u
.lptdesc
;
2653 switch(*pType
& 0x7f) {
2656 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2658 pTD
= pTD
->u
.lptdesc
;
2661 case VT_USERDEFINED
:
2662 pTD
->vt
= VT_USERDEFINED
;
2663 pTD
->u
.hreftype
= *(++pType
) / 4;
2669 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2672 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2674 pTD
->vt
= VT_CARRAY
;
2675 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2677 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2678 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2679 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2680 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2682 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2688 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2692 pTD
->vt
= VT_SAFEARRAY
;
2693 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2695 pTD
= pTD
->u
.lptdesc
;
2699 pTD
->vt
= *pType
& 0x7f;
2709 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2714 TLBRefType
**ppRefType
;
2716 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2717 FIXME("Ref magic = %x\n", pRef
->magic
);
2720 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2722 ppRefType
= &pTI
->reflist
;
2723 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2725 unsigned int lib_offs
, type_num
;
2727 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2728 sizeof(**ppRefType
));
2730 name
+= SLTG_ReadStringA(name
, &refname
);
2731 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2732 FIXME("Can't sscanf ref\n");
2733 if(lib_offs
!= 0xffff) {
2734 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2737 if((*import
)->offset
== lib_offs
)
2739 import
= &(*import
)->next
;
2742 char fname
[MAX_PATH
+1];
2745 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2747 (*import
)->offset
= lib_offs
;
2748 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2750 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2751 &(*import
)->wVersionMajor
,
2752 &(*import
)->wVersionMinor
,
2753 &(*import
)->lcid
, fname
) != 4) {
2754 FIXME("can't sscanf ref %s\n",
2755 pNameTable
+ lib_offs
+ 40);
2757 len
= strlen(fname
);
2758 if(fname
[len
-1] != '#')
2759 FIXME("fname = %s\n", fname
);
2760 fname
[len
-1] = '\0';
2761 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2763 (*ppRefType
)->pImpTLInfo
= *import
;
2764 } else { /* internal ref */
2765 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2767 (*ppRefType
)->reference
= ref
;
2768 (*ppRefType
)->index
= type_num
;
2770 HeapFree(GetProcessHeap(), 0, refname
);
2771 ppRefType
= &(*ppRefType
)->next
;
2773 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2774 FIXME("End of ref block magic = %x\n", *name
);
2775 dump_TLBRefType(pTI
->reflist
);
2778 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2781 SLTG_ImplInfo
*info
;
2782 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2783 /* I don't really get this structure, usually it's 0x16 bytes
2784 long, but iuser.tlb contains some that are 0x18 bytes long.
2785 That's ok because we can use the next ptr to jump to the next
2786 one. But how do we know the length of the last one? The WORD
2787 at offs 0x8 might be the clue. For now I'm just assuming that
2788 the last one is the regular 0x16 bytes. */
2790 info
= (SLTG_ImplInfo
*)pBlk
;
2792 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2793 sizeof(**ppImplType
));
2794 (*ppImplType
)->hRef
= info
->ref
;
2795 (*ppImplType
)->implflags
= info
->impltypeflags
;
2796 pTI
->TypeAttr
.cImplTypes
++;
2797 ppImplType
= &(*ppImplType
)->next
;
2799 if(info
->next
== 0xffff)
2802 FIXME("Interface inheriting more than one interface\n");
2803 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2805 info
++; /* see comment at top of function */
2809 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2812 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2813 SLTG_MemberHeader
*pMemHeader
;
2814 char *pFirstItem
, *pNextItem
;
2816 if(pTIHeader
->href_table
!= 0xffffffff) {
2817 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2822 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2824 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2826 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2827 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2830 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2834 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2837 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2838 SLTG_MemberHeader
*pMemHeader
;
2839 SLTG_Function
*pFunc
;
2840 char *pFirstItem
, *pNextItem
;
2841 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2844 if(pTIHeader
->href_table
!= 0xffffffff) {
2845 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2849 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2851 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2853 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2854 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2857 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2858 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2863 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2864 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2865 FIXME("func magic = %02x\n", pFunc
->magic
);
2868 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2869 sizeof(**ppFuncDesc
));
2870 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2872 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2873 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2874 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2875 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2876 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2877 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2879 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2880 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2882 if(pFunc
->retnextopt
& 0x80)
2883 pType
= &pFunc
->rettype
;
2885 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2888 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2890 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2891 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2892 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2893 (*ppFuncDesc
)->pParamDesc
=
2894 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2895 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2897 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2899 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2900 char *paramName
= pNameTable
+ *pArg
;
2902 /* If arg type follows then paramName points to the 2nd
2903 letter of the name, else the next WORD is an offset to
2904 the arg type and paramName points to the first letter.
2905 So let's take one char off paramName and see if we're
2906 pointing at an alpha-numeric char. However if *pArg is
2907 0xffff or 0xfffe then the param has no name, the former
2908 meaning that the next WORD is the type, the latter
2909 meaning the the next WORD is an offset to the type. */
2914 else if(*pArg
== 0xfffe) {
2918 else if(!isalnum(*(paramName
-1)))
2923 if(HaveOffs
) { /* the next word is an offset to type */
2924 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2925 SLTG_DoType(pType
, pFirstItem
,
2926 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2931 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2932 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2935 /* Are we an optional param ? */
2936 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2937 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2938 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2941 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2942 TLB_MultiByteToBSTR(paramName
);
2946 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2947 if(pFunc
->next
== 0xffff) break;
2949 pTI
->TypeAttr
.cFuncs
= num
;
2950 dump_TLBFuncDesc(pTI
->funclist
);
2951 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2954 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2957 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2958 SLTG_MemberHeader
*pMemHeader
;
2959 SLTG_RecordItem
*pItem
;
2961 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2966 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2968 pFirstItem
= (char*)(pMemHeader
+ 1);
2969 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2970 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2971 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2972 FIXME("record magic = %02x\n", pItem
->magic
);
2975 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2976 sizeof(**ppVarDesc
));
2977 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2978 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2979 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2980 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2982 if(pItem
->typepos
== 0x02)
2983 pType
= &pItem
->type
;
2984 else if(pItem
->typepos
== 0x00)
2985 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2987 FIXME("typepos = %02x\n", pItem
->typepos
);
2991 SLTG_DoType(pType
, pFirstItem
,
2992 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2994 /* FIXME("helpcontext, helpstring\n"); */
2996 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2998 ppVarDesc
= &((*ppVarDesc
)->next
);
2999 if(pItem
->next
== 0xffff) break;
3001 pTI
->TypeAttr
.cVars
= num
;
3002 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3005 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3008 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3009 SLTG_MemberHeader
*pMemHeader
;
3010 SLTG_AliasItem
*pItem
;
3013 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3014 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3017 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3018 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
3019 if (pItem
->vt
== 0xffff) {
3020 if (i
<(pMemHeader
->cbExtra
/4-1))
3021 FIXME("Endmarker too early in process alias data!\n");
3025 FIXME("Chain extends over last entry?\n");
3028 if (pItem
->vt
== VT_USERDEFINED
) {
3029 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
3030 /* guessing here ... */
3031 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
3032 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
3035 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
3036 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
3040 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3043 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3046 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3047 SLTG_MemberHeader
*pMemHeader
;
3048 SLTG_AliasItem
*pItem
;
3050 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3051 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3052 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
3053 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
3054 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3057 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3060 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3061 SLTG_MemberHeader
*pMemHeader
;
3062 SLTG_EnumItem
*pItem
;
3064 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3067 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3069 pFirstItem
= (char*)(pMemHeader
+ 1);
3070 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
3071 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
3072 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
3073 FIXME("enumitem magic = %04x\n", pItem
->magic
);
3076 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3077 sizeof(**ppVarDesc
));
3078 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3079 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3080 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3082 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3083 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
3084 *(INT
*)(pItem
->value
+ pFirstItem
);
3085 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
3086 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3087 /* FIXME("helpcontext, helpstring\n"); */
3089 ppVarDesc
= &((*ppVarDesc
)->next
);
3090 if(pItem
->next
== 0xffff) break;
3092 pTI
->TypeAttr
.cVars
= num
;
3093 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3096 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3097 managable copy of it into this */
3110 } SLTG_InternalOtherTypeInfo
;
3112 /****************************************************************************
3113 * ITypeLib2_Constructor_SLTG
3115 * loading a SLTG typelib from an in-memory image
3117 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3119 ITypeLibImpl
*pTypeLibImpl
;
3120 SLTG_Header
*pHeader
;
3121 SLTG_BlkEntry
*pBlkEntry
;
3125 LPVOID pBlk
, pFirstBlk
;
3126 SLTG_LibBlk
*pLibBlk
;
3127 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3128 char *pAfterOTIBlks
= NULL
;
3129 char *pNameTable
, *ptr
;
3132 ITypeInfoImpl
**ppTypeInfoImpl
;
3134 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3136 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
3137 if (!pTypeLibImpl
) return NULL
;
3139 pTypeLibImpl
->lpVtbl
= &tlbvt
;
3140 pTypeLibImpl
->ref
= 1;
3145 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
3146 pHeader
->nrOfFileBlks
);
3147 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3148 FIXME("Header type magic 0x%08lx not supported.\n",
3149 pHeader
->SLTG_magic
);
3153 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3154 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3156 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3157 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3159 /* Next we have a magic block */
3160 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3162 /* Let's see if we're still in sync */
3163 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3164 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3165 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3168 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3169 sizeof(SLTG_DIR_MAGIC
))) {
3170 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3174 pIndex
= (SLTG_Index
*)(pMagic
+1);
3176 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3178 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3180 /* We'll set up a ptr to the main library block, which is the last one. */
3182 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3183 pBlkEntry
[order
].next
!= 0;
3184 order
= pBlkEntry
[order
].next
- 1, i
++) {
3185 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3189 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3191 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3196 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3198 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3199 sizeof(*pOtherTypeInfoBlks
) *
3200 pTypeLibImpl
->TypeInfoCount
);
3203 ptr
= (char*)pLibBlk
+ len
;
3205 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3209 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3211 w
= *(WORD
*)(ptr
+ 2);
3214 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3216 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3217 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3219 w
= *(WORD
*)(ptr
+ 4 + len
);
3221 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3223 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3225 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3226 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3228 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3229 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3230 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3232 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3234 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3237 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3238 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3239 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3240 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3241 len
+= sizeof(SLTG_OtherTypeInfo
);
3245 pAfterOTIBlks
= ptr
;
3247 /* Skip this WORD and get the next DWORD */
3248 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3250 /* Now add this to pLibBLk look at what we're pointing at and
3251 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3252 dust and we should be pointing at the beginning of the name
3255 pNameTable
= (char*)pLibBlk
+ len
;
3257 switch(*(WORD
*)pNameTable
) {
3264 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3268 pNameTable
+= 0x216;
3272 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3274 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3277 /* Hopefully we now have enough ptrs set up to actually read in
3278 some TypeInfos. It's not clear which order to do them in, so
3279 I'll just follow the links along the BlkEntry chain and read
3280 them in in the order in which they're in the file */
3282 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3284 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3285 pBlkEntry
[order
].next
!= 0;
3286 order
= pBlkEntry
[order
].next
- 1, i
++) {
3288 SLTG_TypeInfoHeader
*pTIHeader
;
3289 SLTG_TypeInfoTail
*pTITail
;
3291 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3292 pOtherTypeInfoBlks
[i
].index_name
)) {
3293 FIXME("Index strings don't match\n");
3298 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3299 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3302 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3303 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3304 (*ppTypeInfoImpl
)->index
= i
;
3305 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3306 pOtherTypeInfoBlks
[i
].name_offs
+
3308 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3309 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3311 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3312 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3313 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3314 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3315 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3317 if((pTIHeader
->typeflags1
& 7) != 2)
3318 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3319 if(pTIHeader
->typeflags3
!= 2)
3320 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3322 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3323 debugstr_w((*ppTypeInfoImpl
)->Name
),
3324 typekind_desc
[pTIHeader
->typekind
],
3325 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3326 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3328 switch(pTIHeader
->typekind
) {
3330 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3334 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3337 case TKIND_INTERFACE
:
3338 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3342 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3346 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3347 if (pTITail
->tdescalias_vt
)
3348 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3351 case TKIND_DISPATCH
:
3352 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3356 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3362 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3363 but we've already set those */
3364 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3365 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3366 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3368 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3390 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3391 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3394 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3395 FIXME("Somehow processed %d TypeInfos\n", i
);
3399 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3400 return (ITypeLib2
*)pTypeLibImpl
;
3403 /* ITypeLib::QueryInterface
3405 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3410 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3412 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3415 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3416 IsEqualIID(riid
,&IID_ITypeLib
)||
3417 IsEqualIID(riid
,&IID_ITypeLib2
))
3424 ITypeLib2_AddRef(iface
);
3425 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3428 TRACE("-- Interface: E_NOINTERFACE\n");
3429 return E_NOINTERFACE
;
3434 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3436 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3437 ULONG ref
= InterlockedIncrement(&This
->ref
);
3439 TRACE("(%p)->ref was %lu\n",This
, ref
- 1);
3444 /* ITypeLib::Release
3446 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3448 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3449 ULONG ref
= InterlockedDecrement(&This
->ref
);
3451 TRACE("(%p)->(%lu)\n",This
, ref
);
3455 /* remove cache entry */
3456 TRACE("removing from cache list\n");
3457 EnterCriticalSection(&cache_section
);
3458 if (This
->next
) This
->next
->prev
= This
->prev
;
3459 if (This
->prev
) This
->prev
->next
= This
->next
;
3460 else tlb_cache_first
= This
->next
;
3461 LeaveCriticalSection(&cache_section
);
3463 /* FIXME destroy child objects */
3464 TRACE(" destroying ITypeLib(%p)\n",This
);
3468 SysFreeString(This
->Name
);
3472 if (This
->DocString
)
3474 SysFreeString(This
->DocString
);
3475 This
->DocString
= NULL
;
3480 SysFreeString(This
->HelpFile
);
3481 This
->HelpFile
= NULL
;
3484 if (This
->HelpStringDll
)
3486 SysFreeString(This
->HelpStringDll
);
3487 This
->HelpStringDll
= NULL
;
3490 if (This
->pTypeInfo
) /* can be NULL */
3491 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3492 HeapFree(GetProcessHeap(),0,This
);
3499 /* ITypeLib::GetTypeInfoCount
3501 * Returns the number of type descriptions in the type library
3503 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3505 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3506 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3507 return This
->TypeInfoCount
;
3510 /* ITypeLib::GetTypeInfo
3512 * retrieves the specified type description in the library.
3514 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3517 ITypeInfo
**ppTInfo
)
3521 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3522 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3524 TRACE("(%p)->(index=%d) \n", This
, index
);
3526 if (!ppTInfo
) return E_INVALIDARG
;
3528 /* search element n in list */
3529 for(i
=0; i
< index
; i
++)
3531 pTypeInfo
= pTypeInfo
->next
;
3534 TRACE("-- element not found\n");
3535 return TYPE_E_ELEMENTNOTFOUND
;
3539 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3541 ITypeInfo_AddRef(*ppTInfo
);
3542 TRACE("-- found (%p)\n",*ppTInfo
);
3547 /* ITypeLibs::GetTypeInfoType
3549 * Retrieves the type of a type description.
3551 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3556 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3558 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3560 TRACE("(%p) index %d \n",This
, index
);
3562 if(!pTKind
) return E_INVALIDARG
;
3564 /* search element n in list */
3565 for(i
=0; i
< index
; i
++)
3569 TRACE("-- element not found\n");
3570 return TYPE_E_ELEMENTNOTFOUND
;
3572 pTInfo
= pTInfo
->next
;
3575 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3576 TRACE("-- found Type (%d)\n", *pTKind
);
3580 /* ITypeLib::GetTypeInfoOfGuid
3582 * Retrieves the type description that corresponds to the specified GUID.
3585 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3588 ITypeInfo
**ppTInfo
)
3590 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3591 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3593 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3595 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3597 /* search linked list for guid */
3598 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3600 pTypeInfo
= pTypeInfo
->next
;
3604 /* end of list reached */
3605 TRACE("-- element not found\n");
3606 return TYPE_E_ELEMENTNOTFOUND
;
3610 TRACE("-- found (%p, %s)\n",
3612 debugstr_w(pTypeInfo
->Name
));
3614 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3615 ITypeInfo_AddRef(*ppTInfo
);
3619 /* ITypeLib::GetLibAttr
3621 * Retrieves the structure that contains the library's attributes.
3624 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3626 LPTLIBATTR
*ppTLibAttr
)
3628 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3629 TRACE("(%p)\n",This
);
3630 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3631 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3635 /* ITypeLib::GetTypeComp
3637 * Enables a client compiler to bind to a library's types, variables,
3638 * constants, and global functions.
3641 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3643 ITypeComp
**ppTComp
)
3645 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3647 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3648 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3649 ITypeComp_AddRef(*ppTComp
);
3654 /* ITypeLib::GetDocumentation
3656 * Retrieves the library's documentation string, the complete Help file name
3657 * and path, and the context identifier for the library Help topic in the Help
3660 * On a successful return all non-null BSTR pointers will have been set,
3663 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3667 BSTR
*pBstrDocString
,
3668 DWORD
*pdwHelpContext
,
3669 BSTR
*pBstrHelpFile
)
3671 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3673 HRESULT result
= E_INVALIDARG
;
3678 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3680 pBstrName
, pBstrDocString
,
3681 pdwHelpContext
, pBstrHelpFile
);
3685 /* documentation for the typelib */
3689 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3695 if (This
->DocString
)
3696 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3697 else if (This
->Name
)
3698 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3700 *pBstrDocString
= NULL
;
3704 *pdwHelpContext
= This
->dwHelpContext
;
3709 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3711 *pBstrHelpFile
= NULL
;
3718 /* for a typeinfo */
3719 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3721 if(SUCCEEDED(result
))
3723 result
= ITypeInfo_GetDocumentation(pTInfo
,
3727 pdwHelpContext
, pBstrHelpFile
);
3729 ITypeInfo_Release(pTInfo
);
3734 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3736 if (pBstrName
) SysFreeString (*pBstrName
);
3738 return STG_E_INSUFFICIENTMEMORY
;
3743 * Indicates whether a passed-in string contains the name of a type or member
3744 * described in the library.
3747 static HRESULT WINAPI
ITypeLib2_fnIsName(
3753 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3754 ITypeInfoImpl
*pTInfo
;
3755 TLBFuncDesc
*pFInfo
;
3758 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3760 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3764 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3765 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3766 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3767 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3768 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3769 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3770 goto ITypeLib2_fnIsName_exit
;
3772 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3773 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3778 ITypeLib2_fnIsName_exit
:
3779 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3780 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3785 /* ITypeLib::FindName
3787 * Finds occurrences of a type description in a type library. This may be used
3788 * to quickly verify that a name exists in a type library.
3791 static HRESULT WINAPI
ITypeLib2_fnFindName(
3795 ITypeInfo
**ppTInfo
,
3799 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3800 ITypeInfoImpl
*pTInfo
;
3801 TLBFuncDesc
*pFInfo
;
3805 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3807 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3808 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3809 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3810 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3811 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3812 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3813 goto ITypeLib2_fnFindName_exit
;
3815 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3816 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3818 ITypeLib2_fnFindName_exit
:
3819 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3820 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3823 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3824 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3831 /* ITypeLib::ReleaseTLibAttr
3833 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3836 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3838 TLIBATTR
*pTLibAttr
)
3840 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3841 TRACE("freeing (%p)\n",This
);
3842 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3846 /* ITypeLib2::GetCustData
3848 * gets the custom data
3850 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3855 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3856 TLBCustData
*pCData
;
3858 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3860 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3863 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3867 VariantInit( pVarVal
);
3868 VariantCopy( pVarVal
, &pCData
->data
);
3871 return E_INVALIDARG
; /* FIXME: correct? */
3874 /* ITypeLib2::GetLibStatistics
3876 * Returns statistics about a type library that are required for efficient
3877 * sizing of hash tables.
3880 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3882 ULONG
*pcUniqueNames
,
3883 ULONG
*pcchUniqueNames
)
3885 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3887 FIXME("(%p): stub!\n", This
);
3889 if(pcUniqueNames
) *pcUniqueNames
=1;
3890 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3894 /* ITypeLib2::GetDocumentation2
3896 * Retrieves the library's documentation string, the complete Help file name
3897 * and path, the localization context to use, and the context ID for the
3898 * library Help topic in the Help file.
3901 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3905 BSTR
*pbstrHelpString
,
3906 DWORD
*pdwHelpStringContext
,
3907 BSTR
*pbstrHelpStringDll
)
3909 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3913 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3915 /* the help string should be obtained from the helpstringdll,
3916 * using the _DLLGetDocumentation function, based on the supplied
3917 * lcid. Nice to do sometime...
3921 /* documentation for the typelib */
3923 *pbstrHelpString
=SysAllocString(This
->DocString
);
3924 if(pdwHelpStringContext
)
3925 *pdwHelpStringContext
=This
->dwHelpContext
;
3926 if(pbstrHelpStringDll
)
3927 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3933 /* for a typeinfo */
3934 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3936 if(SUCCEEDED(result
))
3938 ITypeInfo2
* pTInfo2
;
3939 result
= ITypeInfo_QueryInterface(pTInfo
,
3941 (LPVOID
*) &pTInfo2
);
3943 if(SUCCEEDED(result
))
3945 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3949 pdwHelpStringContext
,
3950 pbstrHelpStringDll
);
3952 ITypeInfo2_Release(pTInfo2
);
3955 ITypeInfo_Release(pTInfo
);
3961 /* ITypeLib2::GetAllCustData
3963 * Gets all custom data items for the library.
3966 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3968 CUSTDATA
*pCustData
)
3970 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3971 TLBCustData
*pCData
;
3973 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3974 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3975 if(pCustData
->prgCustData
){
3976 pCustData
->cCustData
=This
->ctCustData
;
3977 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3978 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3979 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3982 ERR(" OUT OF MEMORY! \n");
3983 return E_OUTOFMEMORY
;
3988 static ITypeLib2Vtbl tlbvt
= {
3989 ITypeLib2_fnQueryInterface
,
3991 ITypeLib2_fnRelease
,
3992 ITypeLib2_fnGetTypeInfoCount
,
3993 ITypeLib2_fnGetTypeInfo
,
3994 ITypeLib2_fnGetTypeInfoType
,
3995 ITypeLib2_fnGetTypeInfoOfGuid
,
3996 ITypeLib2_fnGetLibAttr
,
3997 ITypeLib2_fnGetTypeComp
,
3998 ITypeLib2_fnGetDocumentation
,
4000 ITypeLib2_fnFindName
,
4001 ITypeLib2_fnReleaseTLibAttr
,
4003 ITypeLib2_fnGetCustData
,
4004 ITypeLib2_fnGetLibStatistics
,
4005 ITypeLib2_fnGetDocumentation2
,
4006 ITypeLib2_fnGetAllCustData
4010 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4012 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4014 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
4017 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4019 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4021 return ITypeInfo_AddRef((ITypeInfo
*)This
);
4024 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4026 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4028 return ITypeInfo_Release((ITypeInfo
*)This
);
4031 static HRESULT WINAPI
ITypeLibComp_fnBind(
4036 ITypeInfo
** ppTInfo
,
4037 DESCKIND
* pDescKind
,
4040 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4044 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4048 ITypeInfo
** ppTInfo
,
4049 ITypeComp
** ppTComp
)
4051 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4055 static ITypeCompVtbl tlbtcvt
=
4058 ITypeLibComp_fnQueryInterface
,
4059 ITypeLibComp_fnAddRef
,
4060 ITypeLibComp_fnRelease
,
4062 ITypeLibComp_fnBind
,
4063 ITypeLibComp_fnBindType
4066 /*================== ITypeInfo(2) Methods ===================================*/
4067 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4069 ITypeInfoImpl
* pTypeInfoImpl
;
4071 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4074 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4075 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4076 pTypeInfoImpl
->ref
=1;
4078 TRACE("(%p)\n", pTypeInfoImpl
);
4079 return (ITypeInfo2
*) pTypeInfoImpl
;
4082 /* ITypeInfo::QueryInterface
4084 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4089 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4091 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4094 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4095 IsEqualIID(riid
,&IID_ITypeInfo
)||
4096 IsEqualIID(riid
,&IID_ITypeInfo2
))
4100 ITypeInfo_AddRef(iface
);
4101 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4104 TRACE("-- Interface: E_NOINTERFACE\n");
4105 return E_NOINTERFACE
;
4108 /* ITypeInfo::AddRef
4110 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4112 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4113 ULONG ref
= InterlockedIncrement(&This
->ref
);
4115 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4117 TRACE("(%p)->ref is %lu\n",This
, ref
);
4121 /* ITypeInfo::Release
4123 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4125 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4126 ULONG ref
= InterlockedDecrement(&This
->ref
);
4128 TRACE("(%p)->(%lu)\n",This
, ref
);
4131 /* We don't release ITypeLib when ref=0 becouse
4132 it means that funtion is called by ITypeLi2_Release */
4133 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4135 FIXME("destroy child objects\n");
4137 TRACE("destroying ITypeInfo(%p)\n",This
);
4140 SysFreeString(This
->Name
);
4144 if (This
->DocString
)
4146 SysFreeString(This
->DocString
);
4147 This
->DocString
= 0;
4152 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4155 HeapFree(GetProcessHeap(),0,This
);
4161 /* ITypeInfo::GetTypeAttr
4163 * Retrieves a TYPEATTR structure that contains the attributes of the type
4167 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4168 LPTYPEATTR
*ppTypeAttr
)
4170 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4171 TRACE("(%p)\n",This
);
4172 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr
));
4173 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4175 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
) /* need to deep copy typedesc */
4176 copy_typedesc(&(*ppTypeAttr
)->tdescAlias
, &This
->TypeAttr
.tdescAlias
);
4178 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
&& (*ppTypeAttr
)->wTypeFlags
& TYPEFLAG_FDUAL
) {
4179 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4181 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4182 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4187 /* ITypeInfo::GetTypeComp
4189 * Retrieves the ITypeComp interface for the type description, which enables a
4190 * client compiler to bind to the type description's members.
4193 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4194 ITypeComp
* *ppTComp
)
4196 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4198 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4200 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4201 ITypeComp_AddRef(*ppTComp
);
4205 /* ITypeInfo::GetFuncDesc
4207 * Retrieves the FUNCDESC structure that contains information about a
4208 * specified function.
4211 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4212 LPFUNCDESC
*ppFuncDesc
)
4214 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4216 TLBFuncDesc
* pFDesc
;
4217 TRACE("(%p) index %d\n", This
, index
);
4218 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4221 /* FIXME: must do a copy here */
4222 *ppFuncDesc
=&pFDesc
->funcdesc
;
4225 return E_INVALIDARG
;
4228 /* ITypeInfo::GetVarDesc
4230 * Retrieves a VARDESC structure that describes the specified variable.
4233 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4234 LPVARDESC
*ppVarDesc
)
4236 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4238 TLBVarDesc
* pVDesc
;
4239 TRACE("(%p) index %d\n", This
, index
);
4240 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4243 /* FIXME: must do a copy here */
4244 *ppVarDesc
=&pVDesc
->vardesc
;
4247 return E_INVALIDARG
;
4250 /* ITypeInfo_GetNames
4252 * Retrieves the variable with the specified member ID (or the name of the
4253 * property or method and its parameters) that correspond to the specified
4256 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4257 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4259 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4260 TLBFuncDesc
* pFDesc
;
4261 TLBVarDesc
* pVDesc
;
4263 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4264 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4267 /* function found, now return function and parameter names */
4268 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4271 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4273 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4279 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4282 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4287 if(This
->TypeAttr
.cImplTypes
&&
4288 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4289 /* recursive search */
4292 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4294 if(SUCCEEDED(result
))
4296 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4297 ITypeInfo_Release(pTInfo
);
4300 WARN("Could not search inherited interface!\n");
4304 WARN("no names found\n");
4307 return TYPE_E_ELEMENTNOTFOUND
;
4314 /* ITypeInfo::GetRefTypeOfImplType
4316 * If a type description describes a COM class, it retrieves the type
4317 * description of the implemented interface types. For an interface,
4318 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4322 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4327 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4329 TLBImplType
*pImpl
= This
->impltypelist
;
4331 TRACE("(%p) index %d\n", This
, index
);
4332 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4336 /* only valid on dual interfaces;
4337 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4339 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4341 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4342 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4348 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4349 *pRefType
= pImpl
->hRef
;
4354 /* get element n from linked list */
4355 for(i
=0; pImpl
&& i
<index
; i
++)
4357 pImpl
= pImpl
->next
;
4360 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4362 *pRefType
= pImpl
->hRef
;
4364 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4371 /* ITypeInfo::GetImplTypeFlags
4373 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4374 * or base interface in a type description.
4376 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4377 UINT index
, INT
*pImplTypeFlags
)
4379 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4383 TRACE("(%p) index %d\n", This
, index
);
4384 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4385 i
++, pImpl
=pImpl
->next
)
4387 if(i
==index
&& pImpl
){
4388 *pImplTypeFlags
=pImpl
->implflags
;
4392 return TYPE_E_ELEMENTNOTFOUND
;
4396 * Maps between member names and member IDs, and parameter names and
4399 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4400 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4402 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4403 TLBFuncDesc
* pFDesc
;
4404 TLBVarDesc
* pVDesc
;
4407 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4409 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4411 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4412 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4413 for(i
=1; i
< cNames
; i
++){
4414 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4415 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4417 if( j
<pFDesc
->funcdesc
.cParams
)
4420 ret
=DISP_E_UNKNOWNNAME
;
4425 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4426 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4427 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4431 /* not found, see if this is and interface with an inheritance */
4432 if(This
->TypeAttr
.cImplTypes
&&
4433 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4434 /* recursive search */
4436 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4437 This
->impltypelist
->hRef
, &pTInfo
);
4439 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4440 ITypeInfo_Release(pTInfo
);
4443 WARN("Could not search inherited interface!\n");
4445 WARN("no names found\n");
4446 return DISP_E_UNKNOWNNAME
;
4449 /* ITypeInfo::Invoke
4451 * Invokes a method, or accesses a property of an object, that implements the
4452 * interface described by the type description.
4455 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4458 if (TRACE_ON(ole
)) {
4460 TRACE("Calling %p(",func
);
4461 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4473 res
= func(args
[0]);
4476 res
= func(args
[0],args
[1]);
4479 res
= func(args
[0],args
[1],args
[2]);
4482 res
= func(args
[0],args
[1],args
[2],args
[3]);
4485 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4488 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4491 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4494 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4497 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4500 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
4503 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
4506 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4512 FIXME("unsupported calling convention %d\n",callconv
);
4516 TRACE("returns %08lx\n",res
);
4520 extern int _argsize(DWORD vt
);
4522 /****************************************************************************
4523 * Helper functions for Dispcall / Invoke, which copies one variant
4524 * with target type onto the argument stack.
4527 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4528 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4530 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4534 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4535 memcpy(argpos
,&arg
,sizeof(void*));
4539 if (V_VT(arg
) == vt
) {
4540 memcpy(argpos
, &V_UNION(arg
,lVal
), arglen
);
4544 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4545 memcpy(argpos
, &V_UNION(arg
,parray
), sizeof(SAFEARRAY
*));
4549 if (vt
== VT_VARIANT
) {
4550 memcpy(argpos
, arg
, arglen
);
4553 /* Deref BYREF vars if there is need */
4554 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4555 memcpy(argpos
,(void*)V_UNION(arg
,lVal
), arglen
);
4558 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4559 /* in this context, if the type lib specifies IUnknown*, giving an
4560 IDispatch* is correct; so, don't invoke VariantChangeType */
4561 memcpy(argpos
,&V_UNION(arg
,lVal
), arglen
);
4564 if ((vt
== VT_PTR
) && tdesc
)
4565 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4567 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4568 ITypeInfo
*tinfo2
= NULL
;
4569 TYPEATTR
*tattr
= NULL
;
4572 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4574 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4575 "while coercing from vt 0x%x. Copying 4 byte.\n",
4576 tdesc
->u
.hreftype
,V_VT(arg
));
4577 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4580 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4583 ERR("GetTypeAttr failed\n");
4584 ITypeInfo_Release(tinfo2
);
4587 switch (tattr
->typekind
) {
4589 switch ( V_VT( arg
) ) {
4591 *argpos
= V_UNION(arg
,iVal
);
4595 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4599 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4606 tdesc
= &(tattr
->tdescAlias
);
4607 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4610 case TKIND_INTERFACE
:
4611 if (V_VT(arg
) == VT_DISPATCH
) {
4613 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4614 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4618 hres
=IUnknown_QueryInterface(V_UNION(arg
,pdispVal
),
4619 &IID_IDispatch
,(LPVOID
*)&disp
);
4620 if (SUCCEEDED(hres
)) {
4621 memcpy(argpos
,&disp
,4);
4622 IUnknown_Release(V_UNION(arg
,pdispVal
));
4626 FIXME("Failed to query IDispatch interface from %s while "
4627 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4631 if (V_VT(arg
) == VT_UNKNOWN
) {
4632 memcpy(argpos
, &V_UNION(arg
,punkVal
), 4);
4636 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4637 V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4641 case TKIND_DISPATCH
:
4642 if (V_VT(arg
) == VT_DISPATCH
) {
4643 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4648 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4652 FIXME("TKIND_RECORD unhandled.\n");
4656 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4660 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4661 ITypeInfo_Release(tinfo2
);
4667 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4668 memcpy(argpos
,&V_UNION(&va
,lVal
), arglen
);
4669 FIXME("Should not use VariantChangeType here."
4670 " (conversion from 0x%x -> 0x%x) %08lx\n",
4671 V_VT(arg
), vt
, *argpos
4675 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4679 /***********************************************************************
4680 * DispCallFunc (OLEAUT32.@)
4684 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4685 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4687 int i
, argsize
, argspos
;
4691 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4692 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4694 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4695 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4697 for (i
=0;i
<cActuals
;i
++) {
4698 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4699 dump_Variant(prgpvarg
[i
]);
4700 argsize
+= _argsize(prgvt
[i
]);
4702 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4703 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4705 for (i
=0;i
<cActuals
;i
++) {
4706 VARIANT
*arg
= prgpvarg
[i
];
4707 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4708 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4709 argspos
+= _argsize(prgvt
[i
]);
4712 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4714 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4719 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4720 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4721 FIXME("Method returned %lx\n",hres
);
4723 HeapFree(GetProcessHeap(),0,args
);
4727 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4732 DISPPARAMS
*pDispParams
,
4733 VARIANT
*pVarResult
,
4734 EXCEPINFO
*pExcepInfo
,
4737 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4739 unsigned int func_index
, var_index
;
4743 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4744 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4746 dump_DispParms(pDispParams
);
4748 hres
= ITypeInfo2_GetFuncIndexOfMemId(iface
, memid
, dwFlags
, &func_index
);
4749 if (SUCCEEDED(hres
)) {
4750 FUNCDESC
*func_desc
;
4752 hres
= ITypeInfo2_GetFuncDesc(iface
, func_index
, &func_desc
);
4753 if(FAILED(hres
)) return hres
;
4755 switch (func_desc
->funckind
) {
4756 case FUNC_PUREVIRTUAL
:
4757 case FUNC_VIRTUAL
: {
4759 int numargs
, numargs2
, argspos
, args2pos
;
4760 DWORD
*args
, *args2
;
4761 VARIANT
*rgvarg
= HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT
) * func_desc
->cParams
);
4762 memcpy(rgvarg
,pDispParams
->rgvarg
,sizeof(VARIANT
)*pDispParams
->cArgs
);
4765 numargs
= 1; numargs2
= 0;
4766 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4767 if (i
<pDispParams
->cArgs
)
4768 numargs
+= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4770 numargs
+= 1; /* sizeof(lpvoid) */
4771 numargs2
+= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4775 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4776 args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4778 args
[0] = (DWORD
)pIUnk
;
4779 argspos
= 1; args2pos
= 0;
4780 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4781 int arglen
= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4782 if (i
<pDispParams
->cArgs
) {
4783 VARIANT
*arg
= &rgvarg
[pDispParams
->cArgs
-i
-1];
4784 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4785 USHORT paramFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
4786 if (paramFlags
& PARAMFLAG_FOPT
) {
4787 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4788 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4789 if(V_VT(arg
) == VT_EMPTY
4790 || ((V_VT(arg
) & VT_BYREF
) && !V_BYREF(arg
))) {
4791 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4792 How to determine it? */
4794 if(paramFlags
& PARAMFLAG_FHASDEFAULT
)
4795 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4796 V_VT(arg
) = VT_ERROR
;
4797 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4798 arglen
= _argsize(VT_ERROR
);
4801 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4802 if (FAILED(hres
)) goto func_fail
;
4804 } else if(func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FOPT
) {
4805 VARIANT
*arg
= &rgvarg
[i
];
4806 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4807 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4808 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4809 if(func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4810 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4811 V_VT(arg
) = VT_ERROR
;
4812 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4813 arglen
= _argsize(VT_ERROR
);
4814 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4815 if (FAILED(hres
)) goto func_fail
;
4818 TYPEDESC
*tdesc
= &(func_desc
->lprgelemdescParam
[i
].tdesc
);
4819 if (tdesc
->vt
!= VT_PTR
)
4820 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4821 /*FIXME: give pointers for the rest, so propertyget works*/
4822 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4824 /* If pointer to variant, pass reference it. */
4825 if ((tdesc
->vt
== VT_PTR
) &&
4826 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4829 args
[argspos
]= (DWORD
)pVarResult
;
4834 if (func_desc
->cParamsOpt
< 0)
4835 FIXME("Does not support optional parameters (%d)\n", func_desc
->cParamsOpt
);
4837 res
= _invoke((*(FARPROC
**)pIUnk
)[func_desc
->oVft
/4],
4838 func_desc
->callconv
,
4843 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4845 for (i
= 0; i
< func_desc
->cParams
- pDispParams
->cArgs
; i
++) {
4846 int arglen
= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4847 TYPEDESC
*tdesc
= &(func_desc
->lprgelemdescParam
[i
+ pDispParams
->cArgs
].tdesc
);
4849 i4_tdesc
.vt
= VT_I4
;
4851 /* If we are a pointer to a variant, we are done already */
4852 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4855 VariantInit(pVarResult
);
4856 memcpy(&V_UNION(pVarResult
,intVal
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4858 if (tdesc
->vt
== VT_PTR
)
4859 tdesc
= tdesc
->u
.lptdesc
;
4860 if (tdesc
->vt
== VT_USERDEFINED
) {
4864 hres
= ITypeInfo_GetRefTypeInfo(iface
,tdesc
->u
.hreftype
,&tinfo2
);
4866 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc
->u
.hreftype
);
4869 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4870 switch (tattr
->typekind
) {
4872 /* force the return type to be VT_I4 */
4876 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr
->tdescAlias
.vt
);
4877 tdesc
= &(tattr
->tdescAlias
);
4880 case TKIND_INTERFACE
:
4881 FIXME("TKIND_INTERFACE unhandled.\n");
4883 case TKIND_DISPATCH
:
4884 FIXME("TKIND_DISPATCH unhandled.\n");
4887 FIXME("TKIND_RECORD unhandled.\n");
4890 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4893 ITypeInfo_Release(tinfo2
);
4895 V_VT(pVarResult
) = tdesc
->vt
;
4897 /* HACK: VB5 likes this.
4898 * I do not know why. There is 1 example in MSDN which uses
4899 * this which appears broken (mixes int vals and
4902 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4903 V_VT(pVarResult
) = VT_DISPATCH
;
4904 TRACE("storing into variant:\n");
4905 dump_Variant(pVarResult
);
4910 HeapFree(GetProcessHeap(), 0, rgvarg
);
4911 HeapFree(GetProcessHeap(),0,args2
);
4912 HeapFree(GetProcessHeap(),0,args
);
4915 case FUNC_DISPATCH
: {
4918 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4919 if (SUCCEEDED(hres
)) {
4920 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4921 hres
= IDispatch_Invoke(
4922 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4923 pVarResult
,pExcepInfo
,pArgErr
4926 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres
);
4927 IDispatch_Release(disp
);
4929 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4933 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
4938 ITypeInfo2_ReleaseFuncDesc(iface
, func_desc
);
4941 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
4944 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
4945 if(FAILED(hres
)) return hres
;
4947 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4948 dump_VARDESC(var_desc
);
4949 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
4953 /* not found, look for it in inherited interfaces */
4954 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
4955 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
4957 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface
, 0, &ref_type
))) {
4958 /* recursive search */
4960 hres
= ITypeInfo_GetRefTypeInfo(iface
, ref_type
, &pTInfo
);
4961 if(SUCCEEDED(hres
)){
4962 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4963 ITypeInfo_Release(pTInfo
);
4966 WARN("Could not search inherited interface!\n");
4969 ERR("did not find member id %08lx, flags %d!\n", memid
, dwFlags
);
4970 return DISP_E_MEMBERNOTFOUND
;
4973 /* ITypeInfo::GetDocumentation
4975 * Retrieves the documentation string, the complete Help file name and path,
4976 * and the context ID for the Help topic for a specified type description.
4978 * (Can be tested by the Visual Basic Editor in Word for instance.)
4980 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4981 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4982 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4984 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4985 TLBFuncDesc
* pFDesc
;
4986 TLBVarDesc
* pVDesc
;
4987 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4988 " HelpContext(%p) HelpFile(%p)\n",
4989 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4990 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4992 *pBstrName
=SysAllocString(This
->Name
);
4994 *pBstrDocString
=SysAllocString(This
->DocString
);
4996 *pdwHelpContext
=This
->dwHelpContext
;
4998 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
5000 }else {/* for a member */
5001 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5002 if(pFDesc
->funcdesc
.memid
==memid
){
5004 *pBstrName
= SysAllocString(pFDesc
->Name
);
5006 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
5008 *pdwHelpContext
=pFDesc
->helpcontext
;
5011 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5012 if(pVDesc
->vardesc
.memid
==memid
){
5014 *pBstrName
= SysAllocString(pVDesc
->Name
);
5016 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
5018 *pdwHelpContext
=pVDesc
->HelpContext
;
5022 return TYPE_E_ELEMENTNOTFOUND
;
5025 /* ITypeInfo::GetDllEntry
5027 * Retrieves a description or specification of an entry point for a function
5030 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5031 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5034 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5035 TLBFuncDesc
*pFDesc
;
5037 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5039 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5040 if(pFDesc
->funcdesc
.memid
==memid
){
5041 dump_TypeInfo(This
);
5042 dump_TLBFuncDescOne(pFDesc
);
5044 /* FIXME: This is wrong, but how do you find that out? */
5046 static const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5047 *pBstrDllName
= SysAllocString(oleaut32W
);
5050 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5052 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5060 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5066 /* ITypeInfo::GetRefTypeInfo
5068 * If a type description references other type descriptions, it retrieves
5069 * the referenced type descriptions.
5071 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5074 ITypeInfo
**ppTInfo
)
5076 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5077 HRESULT result
= E_FAIL
;
5080 if (hRefType
== -1 &&
5081 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5082 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5084 /* when we meet a DUAL dispinterface, we must create the interface
5087 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5090 /* the interface version contains the same information as the dispinterface
5091 * copy the contents of the structs.
5093 *pTypeInfoImpl
= *This
;
5094 pTypeInfoImpl
->ref
= 1;
5096 /* change the type to interface */
5097 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5099 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5101 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
5106 TLBRefType
*pRefType
;
5107 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5108 if(pRefType
->reference
== hRefType
)
5112 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
5113 if(pRefType
&& hRefType
!= -1) {
5114 ITypeLib
*pTLib
= NULL
;
5116 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5118 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5120 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5121 TRACE("typeinfo in imported typelib that is already loaded\n");
5122 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5123 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5126 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5127 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5128 pRefType
->pImpTLInfo
->wVersionMajor
,
5129 pRefType
->pImpTLInfo
->wVersionMinor
,
5130 pRefType
->pImpTLInfo
->lcid
,
5133 if(!SUCCEEDED(result
)) {
5134 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5135 result
=LoadTypeLib(libnam
, &pTLib
);
5136 SysFreeString(libnam
);
5138 if(SUCCEEDED(result
)) {
5139 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5140 ITypeLib2_AddRef(pTLib
);
5144 if(SUCCEEDED(result
)) {
5145 if(pRefType
->index
== TLB_REF_USE_GUID
)
5146 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5150 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5154 ITypeLib2_Release(pTLib
);
5158 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
5159 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5163 /* ITypeInfo::AddressOfMember
5165 * Retrieves the addresses of static functions or variables, such as those
5168 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5169 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5171 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5172 FIXME("(%p) stub!\n", This
);
5176 /* ITypeInfo::CreateInstance
5178 * Creates a new instance of a type that describes a component object class
5181 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
5182 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
5184 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5185 FIXME("(%p) stub!\n", This
);
5189 /* ITypeInfo::GetMops
5191 * Retrieves marshalling information.
5193 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
5196 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5197 FIXME("(%p) stub!\n", This
);
5201 /* ITypeInfo::GetContainingTypeLib
5203 * Retrieves the containing type library and the index of the type description
5204 * within that type library.
5206 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
5207 ITypeLib
* *ppTLib
, UINT
*pIndex
)
5209 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5211 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5213 *pIndex
=This
->index
;
5214 TRACE("returning pIndex=%d\n", *pIndex
);
5218 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
5219 ITypeLib2_AddRef(*ppTLib
);
5220 TRACE("returning ppTLib=%p\n", *ppTLib
);
5226 /* ITypeInfo::ReleaseTypeAttr
5228 * Releases a TYPEATTR previously returned by GetTypeAttr.
5231 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
5232 TYPEATTR
* pTypeAttr
)
5234 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5235 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
5236 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5237 free_deep_typedesc(&pTypeAttr
->tdescAlias
);
5238 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
5241 /* ITypeInfo::ReleaseFuncDesc
5243 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5245 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
5247 FUNCDESC
*pFuncDesc
)
5249 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5250 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
5253 /* ITypeInfo::ReleaseVarDesc
5255 * Releases a VARDESC previously returned by GetVarDesc.
5257 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5260 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5261 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5264 /* ITypeInfo2::GetTypeKind
5266 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5269 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5270 TYPEKIND
*pTypeKind
)
5272 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5273 *pTypeKind
=This
->TypeAttr
.typekind
;
5274 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5278 /* ITypeInfo2::GetTypeFlags
5280 * Returns the type flags without any allocations. This returns a DWORD type
5281 * flag, which expands the type flags without growing the TYPEATTR (type
5285 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5287 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5288 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5289 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5293 /* ITypeInfo2::GetFuncIndexOfMemId
5294 * Binds to a specific member based on a known DISPID, where the member name
5295 * is not known (for example, when binding to a default member).
5298 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5299 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5301 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5302 TLBFuncDesc
*pFuncInfo
;
5306 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
5307 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
5313 result
= TYPE_E_ELEMENTNOTFOUND
;
5315 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5316 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5320 /* TypeInfo2::GetVarIndexOfMemId
5322 * Binds to a specific member based on a known DISPID, where the member name
5323 * is not known (for example, when binding to a default member).
5326 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5327 MEMBERID memid
, UINT
*pVarIndex
)
5329 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5330 TLBVarDesc
*pVarInfo
;
5333 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5334 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5340 result
= TYPE_E_ELEMENTNOTFOUND
;
5342 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5343 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5347 /* ITypeInfo2::GetCustData
5349 * Gets the custom data
5351 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5356 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5357 TLBCustData
*pCData
;
5359 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5360 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5362 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5366 VariantInit( pVarVal
);
5367 VariantCopy( pVarVal
, &pCData
->data
);
5370 return E_INVALIDARG
; /* FIXME: correct? */
5373 /* ITypeInfo2::GetFuncCustData
5375 * Gets the custom data
5377 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5383 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5384 TLBCustData
*pCData
=NULL
;
5385 TLBFuncDesc
* pFDesc
;
5387 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5388 pFDesc
=pFDesc
->next
);
5391 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5392 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5394 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5397 VariantInit( pVarVal
);
5398 VariantCopy( pVarVal
, &pCData
->data
);
5401 return E_INVALIDARG
; /* FIXME: correct? */
5404 /* ITypeInfo2::GetParamCustData
5406 * Gets the custom data
5408 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5415 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5416 TLBCustData
*pCData
=NULL
;
5417 TLBFuncDesc
* pFDesc
;
5420 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5422 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5423 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5424 pCData
= pCData
->next
)
5425 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5427 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5431 VariantInit( pVarVal
);
5432 VariantCopy( pVarVal
, &pCData
->data
);
5435 return E_INVALIDARG
; /* FIXME: correct? */
5438 /* ITypeInfo2::GetVarCustData
5440 * Gets the custom data
5442 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5448 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5449 TLBCustData
*pCData
=NULL
;
5450 TLBVarDesc
* pVDesc
;
5453 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5457 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5459 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5463 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5467 VariantInit( pVarVal
);
5468 VariantCopy( pVarVal
, &pCData
->data
);
5471 return E_INVALIDARG
; /* FIXME: correct? */
5474 /* ITypeInfo2::GetImplCustData
5476 * Gets the custom data
5478 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5484 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5485 TLBCustData
*pCData
=NULL
;
5486 TLBImplType
* pRDesc
;
5489 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5493 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5495 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5499 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5503 VariantInit( pVarVal
);
5504 VariantCopy( pVarVal
, &pCData
->data
);
5507 return E_INVALIDARG
; /* FIXME: correct? */
5510 /* ITypeInfo2::GetDocumentation2
5512 * Retrieves the documentation string, the complete Help file name and path,
5513 * the localization context to use, and the context ID for the library Help
5514 * topic in the Help file.
5517 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5521 BSTR
*pbstrHelpString
,
5522 DWORD
*pdwHelpStringContext
,
5523 BSTR
*pbstrHelpStringDll
)
5525 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5526 TLBFuncDesc
* pFDesc
;
5527 TLBVarDesc
* pVDesc
;
5528 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5529 "HelpStringContext(%p) HelpStringDll(%p)\n",
5530 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5531 pbstrHelpStringDll
);
5532 /* the help string should be obtained from the helpstringdll,
5533 * using the _DLLGetDocumentation function, based on the supplied
5534 * lcid. Nice to do sometime...
5536 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5538 *pbstrHelpString
=SysAllocString(This
->Name
);
5539 if(pdwHelpStringContext
)
5540 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5541 if(pbstrHelpStringDll
)
5542 *pbstrHelpStringDll
=
5543 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5545 }else {/* for a member */
5546 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5547 if(pFDesc
->funcdesc
.memid
==memid
){
5549 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5550 if(pdwHelpStringContext
)
5551 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5552 if(pbstrHelpStringDll
)
5553 *pbstrHelpStringDll
=
5554 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5557 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5558 if(pVDesc
->vardesc
.memid
==memid
){
5560 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5561 if(pdwHelpStringContext
)
5562 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5563 if(pbstrHelpStringDll
)
5564 *pbstrHelpStringDll
=
5565 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5569 return TYPE_E_ELEMENTNOTFOUND
;
5572 /* ITypeInfo2::GetAllCustData
5574 * Gets all custom data items for the Type info.
5577 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5579 CUSTDATA
*pCustData
)
5581 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5582 TLBCustData
*pCData
;
5585 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5587 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5588 if(pCustData
->prgCustData
){
5589 pCustData
->cCustData
=This
->ctCustData
;
5590 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5591 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5592 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5595 ERR(" OUT OF MEMORY! \n");
5596 return E_OUTOFMEMORY
;
5601 /* ITypeInfo2::GetAllFuncCustData
5603 * Gets all custom data items for the specified Function
5606 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5609 CUSTDATA
*pCustData
)
5611 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5612 TLBCustData
*pCData
;
5613 TLBFuncDesc
* pFDesc
;
5615 TRACE("(%p) index %d\n", This
, index
);
5616 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5617 pFDesc
=pFDesc
->next
)
5620 pCustData
->prgCustData
=
5621 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5622 if(pCustData
->prgCustData
){
5623 pCustData
->cCustData
=pFDesc
->ctCustData
;
5624 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5625 pCData
= pCData
->next
){
5626 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5627 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5631 ERR(" OUT OF MEMORY! \n");
5632 return E_OUTOFMEMORY
;
5636 return TYPE_E_ELEMENTNOTFOUND
;
5639 /* ITypeInfo2::GetAllParamCustData
5641 * Gets all custom data items for the Functions
5644 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5645 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5647 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5648 TLBCustData
*pCData
=NULL
;
5649 TLBFuncDesc
* pFDesc
;
5651 TRACE("(%p) index %d\n", This
, indexFunc
);
5652 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5653 pFDesc
=pFDesc
->next
)
5655 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5656 pCustData
->prgCustData
=
5657 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5658 sizeof(CUSTDATAITEM
));
5659 if(pCustData
->prgCustData
){
5660 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5661 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5662 pCData
; i
++, pCData
= pCData
->next
){
5663 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5664 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5668 ERR(" OUT OF MEMORY! \n");
5669 return E_OUTOFMEMORY
;
5673 return TYPE_E_ELEMENTNOTFOUND
;
5676 /* ITypeInfo2::GetAllVarCustData
5678 * Gets all custom data items for the specified Variable
5681 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5682 UINT index
, CUSTDATA
*pCustData
)
5684 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5685 TLBCustData
*pCData
;
5686 TLBVarDesc
* pVDesc
;
5688 TRACE("(%p) index %d\n", This
, index
);
5689 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5690 pVDesc
=pVDesc
->next
)
5693 pCustData
->prgCustData
=
5694 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5695 if(pCustData
->prgCustData
){
5696 pCustData
->cCustData
=pVDesc
->ctCustData
;
5697 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5698 pCData
= pCData
->next
){
5699 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5700 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5704 ERR(" OUT OF MEMORY! \n");
5705 return E_OUTOFMEMORY
;
5709 return TYPE_E_ELEMENTNOTFOUND
;
5712 /* ITypeInfo2::GetAllImplCustData
5714 * Gets all custom data items for the specified implementation type
5717 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5720 CUSTDATA
*pCustData
)
5722 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5723 TLBCustData
*pCData
;
5724 TLBImplType
* pRDesc
;
5726 TRACE("(%p) index %d\n", This
, index
);
5727 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5728 pRDesc
=pRDesc
->next
)
5731 pCustData
->prgCustData
=
5732 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5733 if(pCustData
->prgCustData
){
5734 pCustData
->cCustData
=pRDesc
->ctCustData
;
5735 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5736 pCData
= pCData
->next
){
5737 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5738 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5742 ERR(" OUT OF MEMORY! \n");
5743 return E_OUTOFMEMORY
;
5747 return TYPE_E_ELEMENTNOTFOUND
;
5750 static ITypeInfo2Vtbl tinfvt
=
5753 ITypeInfo_fnQueryInterface
,
5755 ITypeInfo_fnRelease
,
5757 ITypeInfo_fnGetTypeAttr
,
5758 ITypeInfo_fnGetTypeComp
,
5759 ITypeInfo_fnGetFuncDesc
,
5760 ITypeInfo_fnGetVarDesc
,
5761 ITypeInfo_fnGetNames
,
5762 ITypeInfo_fnGetRefTypeOfImplType
,
5763 ITypeInfo_fnGetImplTypeFlags
,
5764 ITypeInfo_fnGetIDsOfNames
,
5766 ITypeInfo_fnGetDocumentation
,
5767 ITypeInfo_fnGetDllEntry
,
5768 ITypeInfo_fnGetRefTypeInfo
,
5769 ITypeInfo_fnAddressOfMember
,
5770 ITypeInfo_fnCreateInstance
,
5771 ITypeInfo_fnGetMops
,
5772 ITypeInfo_fnGetContainingTypeLib
,
5773 ITypeInfo_fnReleaseTypeAttr
,
5774 ITypeInfo_fnReleaseFuncDesc
,
5775 ITypeInfo_fnReleaseVarDesc
,
5777 ITypeInfo2_fnGetTypeKind
,
5778 ITypeInfo2_fnGetTypeFlags
,
5779 ITypeInfo2_fnGetFuncIndexOfMemId
,
5780 ITypeInfo2_fnGetVarIndexOfMemId
,
5781 ITypeInfo2_fnGetCustData
,
5782 ITypeInfo2_fnGetFuncCustData
,
5783 ITypeInfo2_fnGetParamCustData
,
5784 ITypeInfo2_fnGetVarCustData
,
5785 ITypeInfo2_fnGetImplTypeCustData
,
5786 ITypeInfo2_fnGetDocumentation2
,
5787 ITypeInfo2_fnGetAllCustData
,
5788 ITypeInfo2_fnGetAllFuncCustData
,
5789 ITypeInfo2_fnGetAllParamCustData
,
5790 ITypeInfo2_fnGetAllVarCustData
,
5791 ITypeInfo2_fnGetAllImplTypeCustData
,
5794 /******************************************************************************
5795 * CreateDispTypeInfo [OLEAUT32.31]
5797 * Build type information for an object so it can be called through an
5798 * IDispatch interface.
5801 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5802 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5805 * This call allows an objects methods to be accessed through IDispatch, by
5806 * building an ITypeInfo object that IDispatch can use to call through.
5808 HRESULT WINAPI
CreateDispTypeInfo(
5809 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
5810 LCID lcid
, /* [I] Locale Id */
5811 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
5813 ITypeInfoImpl
*pTIImpl
;
5815 TLBFuncDesc
**ppFuncDesc
;
5817 pTIImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
5818 pTIImpl
->pTypeLib
= NULL
;
5820 pTIImpl
->Name
= NULL
;
5821 pTIImpl
->dwHelpContext
= -1;
5822 memset(&pTIImpl
->TypeAttr
.guid
, 0, sizeof(GUID
));
5823 pTIImpl
->TypeAttr
.lcid
= lcid
;
5824 pTIImpl
->TypeAttr
.typekind
= TKIND_COCLASS
;
5825 pTIImpl
->TypeAttr
.wMajorVerNum
= 0;
5826 pTIImpl
->TypeAttr
.wMinorVerNum
= 0;
5827 pTIImpl
->TypeAttr
.cbAlignment
= 2;
5828 pTIImpl
->TypeAttr
.cbSizeInstance
= -1;
5829 pTIImpl
->TypeAttr
.cbSizeVft
= -1;
5830 pTIImpl
->TypeAttr
.cFuncs
= 0;
5831 pTIImpl
->TypeAttr
.cImplTypes
= 1;
5832 pTIImpl
->TypeAttr
.cVars
= 0;
5833 pTIImpl
->TypeAttr
.wTypeFlags
= 0;
5835 ppFuncDesc
= &pTIImpl
->funclist
;
5836 for(func
= 0; func
< pidata
->cMembers
; func
++) {
5837 METHODDATA
*md
= pidata
->pmethdata
+ func
;
5838 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
5839 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
5840 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
5841 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
5842 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
5843 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
5844 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
5845 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
;
5846 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0; /*??*/
5847 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
5848 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5849 md
->cArgs
* sizeof(ELEMDESC
));
5850 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5851 md
->cArgs
* sizeof(TLBParDesc
));
5852 for(param
= 0; param
< md
->cArgs
; param
++) {
5853 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
5854 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
5856 ppFuncDesc
= &(*ppFuncDesc
)->next
;
5858 *pptinfo
= (ITypeInfo
*)pTIImpl
;
5863 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5865 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5867 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
5870 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
5872 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5874 return ITypeInfo_AddRef((ITypeInfo
*)This
);
5877 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
5879 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5881 return ITypeInfo_Release((ITypeInfo
*)This
);
5884 static HRESULT WINAPI
ITypeComp_fnBind(
5889 ITypeInfo
** ppTInfo
,
5890 DESCKIND
* pDescKind
,
5893 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5894 TLBFuncDesc
* pFDesc
;
5895 TLBVarDesc
* pVDesc
;
5897 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5899 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
5900 if (pFDesc
->funcdesc
.invkind
& wFlags
)
5901 if (!strcmpW(pFDesc
->Name
, szName
)) {
5907 *pDescKind
= DESCKIND_FUNCDESC
;
5908 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
5909 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5912 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
5914 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
5915 if (!strcmpW(pVDesc
->Name
, szName
)) {
5916 *pDescKind
= DESCKIND_VARDESC
;
5917 pBindPtr
->lpvardesc
= &pVDesc
->vardesc
;
5918 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5924 /* not found, look for it in inherited interfaces */
5925 if (This
->TypeAttr
.cImplTypes
&&
5926 (This
->TypeAttr
.typekind
== TKIND_INTERFACE
|| This
->TypeAttr
.typekind
== TKIND_DISPATCH
)) {
5927 /* recursive search */
5931 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
5934 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
5935 ITypeInfo_Release(pTInfo
);
5939 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5940 ITypeComp_Release(pTComp
);
5943 WARN("Could not search inherited interface!\n");
5945 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
5946 *pDescKind
= DESCKIND_NONE
;
5947 pBindPtr
->lpfuncdesc
= NULL
;
5949 return DISP_E_MEMBERNOTFOUND
;
5952 static HRESULT WINAPI
ITypeComp_fnBindType(
5956 ITypeInfo
** ppTInfo
,
5957 ITypeComp
** ppTComp
)
5959 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5961 /* strange behaviour (does nothing) but like the
5964 if (!ppTInfo
|| !ppTComp
)
5973 static ITypeCompVtbl tcompvt
=
5976 ITypeComp_fnQueryInterface
,
5978 ITypeComp_fnRelease
,
5981 ITypeComp_fnBindType