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
);
195 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
198 /****************************************************************************
199 * QueryPathOfRegTypeLib [OLEAUT32.164]
201 * Gets the path to a registered type library.
204 * guid [I] referenced guid
205 * wMaj [I] major version
206 * wMin [I] minor version
208 * path [O] path of typelib
212 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
213 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
216 HRESULT WINAPI
QueryPathOfRegTypeLib(
223 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
227 WCHAR Path
[MAX_PATH
];
230 TRACE_(typelib
)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
232 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
234 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
235 if (res
== ERROR_FILE_NOT_FOUND
)
237 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
238 return TYPE_E_LIBNOTREGISTERED
;
240 else if (res
!= ERROR_SUCCESS
)
242 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
243 return TYPE_E_REGISTRYACCESS
;
248 DWORD dwPathLen
= sizeof(Path
);
250 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
252 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
256 else if (myLCID
== lcid
)
258 /* try with sub-langid */
259 myLCID
= SUBLANGID(lcid
);
261 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
263 /* try with system langid */
273 *path
= SysAllocString( Path
);
278 TRACE_(typelib
)("-- 0x%08lx\n", hr
);
282 /******************************************************************************
283 * CreateTypeLib [OLEAUT32.160] creates a typelib
289 HRESULT WINAPI
CreateTypeLib(
290 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
292 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
296 /******************************************************************************
297 * LoadTypeLib [OLEAUT32.161]
299 * Loads a type library
302 * szFile [I] Name of file to load from.
303 * pptLib [O] Pointer that receives ITypeLib object on success.
310 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
312 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
314 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
315 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
318 /******************************************************************************
319 * LoadTypeLibEx [OLEAUT32.183]
321 * Loads and optionally registers a type library
327 HRESULT WINAPI
LoadTypeLibEx(
328 LPCOLESTR szFile
, /* [in] Name of file to load from */
329 REGKIND regkind
, /* [in] Specify kind of registration */
330 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
332 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
337 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
339 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
340 memcpy(szPath
, szFile
, (strlenW(szFile
)+1)*sizeof(WCHAR
));
343 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
346 /* Look for a trailing '\\' followed by an index */
347 pIndexStr
= strrchrW(szFile
, '\\');
348 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
349 index
= atoiW(pIndexStr
);
350 memcpy(szFileCopy
, szFile
,
351 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
352 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
353 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
355 return TYPE_E_CANTLOADLIBRARY
;
356 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
357 return TYPE_E_CANTLOADLIBRARY
;
361 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
363 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
368 case REGKIND_DEFAULT
:
369 /* don't register typelibs supplied with full path. Experimentation confirms the following */
371 ((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
372 (szFile
[0] && (szFile
[1] == ':'))) break;
373 /* else fall-through */
375 case REGKIND_REGISTER
:
376 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
378 IUnknown_Release(*pptLib
);
386 TRACE(" returns %08lx\n",res
);
390 /******************************************************************************
391 * LoadRegTypeLib [OLEAUT32.162]
393 * Loads a registered type library.
396 * rguid [I] GUID of the registered type library.
397 * wVerMajor [I] major version.
398 * wVerMinor [I] minor version.
399 * lcid [I] locale ID.
400 * ppTLib [O] pointer that receives an ITypeLib object on success.
404 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
407 HRESULT WINAPI
LoadRegTypeLib(
415 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
419 res
= LoadTypeLib(bstr
, ppTLib
);
423 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
429 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
430 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
431 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
432 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
433 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
434 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
436 /******************************************************************************
437 * RegisterTypeLib [OLEAUT32.163]
438 * Adds information about a type library to the System Registry
440 * Docs: ITypeLib FAR * ptlib
441 * Docs: OLECHAR FAR* szFullPath
442 * Docs: OLECHAR FAR* szHelpDir
448 HRESULT WINAPI
RegisterTypeLib(
449 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
450 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
451 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
454 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
455 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
456 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
466 if (ptlib
== NULL
|| szFullPath
== NULL
)
469 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
472 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
475 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
476 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
480 /* Set the human-readable name of the typelib */
481 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
483 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
484 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
492 /* Make up the name of the typelib path subkey */
493 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
495 /* Create the typelib path subkey */
496 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
497 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
499 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
500 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
508 /* Create the flags subkey */
509 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
510 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
512 /* FIXME: is %u correct? */
513 static const WCHAR formatW
[] = {'%','u',0};
515 sprintfW(buf
, formatW
, attr
->wLibFlags
);
516 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
517 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
525 /* create the helpdir subkey */
526 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
527 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
529 BOOL freeHelpDir
= FALSE
;
532 /* if we created a new key, and helpDir was null, set the helpdir
533 to the directory which contains the typelib. However,
534 if we just opened an existing key, we leave the helpdir alone */
535 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
536 szHelpDir
= SysAllocString(szFullPath
);
537 pIndexStr
= strrchrW(szHelpDir
, '\\');
544 /* if we have an szHelpDir, set it! */
545 if (szHelpDir
!= NULL
) {
546 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
547 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
553 if (freeHelpDir
) SysFreeString(szHelpDir
);
565 /* register OLE Automation-compatible interfaces for this typelib */
566 types
= ITypeLib_GetTypeInfoCount(ptlib
);
567 for (tidx
=0; tidx
<types
; tidx
++) {
568 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
569 LPOLESTR name
= NULL
;
570 ITypeInfo
*tinfo
= NULL
;
572 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
575 case TKIND_INTERFACE
:
576 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
577 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
581 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
582 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
586 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
591 TYPEATTR
*tattr
= NULL
;
592 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
595 TRACE_(typelib
)("guid=%s, flags=%04x (",
596 debugstr_guid(&tattr
->guid
),
599 if (TRACE_ON(typelib
)) {
600 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
621 * FIXME: The 1 is just here until we implement rpcrt4
622 * stub/proxy handling. Until then it helps IShield
625 if (1 || (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
))
627 if (!(tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) {
628 FIXME("Registering non-oleautomation interface!\n");
631 /* register interface<->typelib coupling */
632 get_interface_key( &tattr
->guid
, keyName
);
633 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
634 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
637 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
638 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
640 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
641 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
642 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
643 (BYTE
*)PSOA
, sizeof PSOA
);
647 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
648 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
649 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
650 (BYTE
*)PSOA
, sizeof PSOA
);
654 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
655 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
658 static const WCHAR fmtver
[] = {'%','u','.','%','u',0 };
659 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
661 StringFromGUID2(&attr
->guid
, buffer
, 40);
662 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
663 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
664 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
665 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
666 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
674 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
677 ITypeInfo_Release(tinfo
);
684 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
690 /******************************************************************************
691 * UnRegisterTypeLib [OLEAUT32.186]
692 * Removes information about a type library from the System Registry
699 HRESULT WINAPI
UnRegisterTypeLib(
700 REFGUID libid
, /* [in] Guid of the library */
701 WORD wVerMajor
, /* [in] major version */
702 WORD wVerMinor
, /* [in] minor version */
703 LCID lcid
, /* [in] locale id */
706 BSTR tlibPath
= NULL
;
709 WCHAR subKeyName
[50];
712 BOOL deleteOtherStuff
;
715 TYPEATTR
* typeAttr
= NULL
;
717 ITypeInfo
* typeInfo
= NULL
;
718 ITypeLib
* typeLib
= NULL
;
721 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
723 /* Create the path to the key */
724 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
726 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
728 TRACE("Unsupported syskind %i\n", syskind
);
729 result
= E_INVALIDARG
;
733 /* get the path to the typelib on disk */
734 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
735 result
= E_INVALIDARG
;
739 /* Try and open the key to the type library. */
740 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != S_OK
) {
741 result
= E_INVALIDARG
;
745 /* Try and load the type library */
746 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
747 result
= TYPE_E_INVALIDSTATE
;
751 /* remove any types registered with this typelib */
752 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
753 for (i
=0; i
<numTypes
; i
++) {
754 /* get the kind of type */
755 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
759 /* skip non-interfaces, and get type info for the type */
760 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
763 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
766 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
770 /* the path to the type */
771 get_interface_key( &typeAttr
->guid
, subKeyName
);
773 /* Delete its bits */
774 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != S_OK
) {
777 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
778 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
779 RegDeleteKeyW(subKey
, TypeLibW
);
782 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
785 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
787 if (typeInfo
) ITypeInfo_Release(typeInfo
);
791 /* Now, delete the type library path subkey */
792 get_lcid_subkey( lcid
, syskind
, subKeyName
);
793 RegDeleteKeyW(key
, subKeyName
);
794 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
795 RegDeleteKeyW(key
, subKeyName
);
797 /* check if there is anything besides the FLAGS/HELPDIR keys.
798 If there is, we don't delete them */
799 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
800 deleteOtherStuff
= TRUE
;
802 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == S_OK
) {
803 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
805 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
806 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
807 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
808 deleteOtherStuff
= FALSE
;
812 /* only delete the other parts of the key if we're absolutely sure */
813 if (deleteOtherStuff
) {
814 RegDeleteKeyW(key
, FLAGSW
);
815 RegDeleteKeyW(key
, HELPDIRW
);
819 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
820 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
821 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
825 if (tlibPath
) SysFreeString(tlibPath
);
826 if (typeLib
) ITypeLib_Release(typeLib
);
827 if (subKey
) RegCloseKey(subKey
);
828 if (key
) RegCloseKey(key
);
832 /*======================= ITypeLib implementation =======================*/
834 typedef struct tagTLBCustData
838 struct tagTLBCustData
* next
;
841 /* data structure for import typelibs */
842 typedef struct tagTLBImpLib
844 int offset
; /* offset in the file (MSFT)
845 offset in nametable (SLTG)
846 just used to identify library while reading
848 GUID guid
; /* libid */
849 BSTR name
; /* name */
851 LCID lcid
; /* lcid of imported typelib */
853 WORD wVersionMajor
; /* major version number */
854 WORD wVersionMinor
; /* minor version number */
856 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
857 NULL if not yet loaded */
858 struct tagTLBImpLib
* next
;
861 /* internal ITypeLib data */
862 typedef struct tagITypeLibImpl
864 const ITypeLib2Vtbl
*lpVtbl
;
865 const ITypeCompVtbl
*lpVtblTypeComp
;
867 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
869 /* strings can be stored in tlb as multibyte strings BUT they are *always*
870 * exported to the application as a UNICODE string.
876 unsigned long dwHelpContext
;
877 int TypeInfoCount
; /* nr of typeinfo's in librarry */
878 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
879 int ctCustData
; /* number of items in cust data list */
880 TLBCustData
* pCustData
; /* linked list to cust data */
881 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
882 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
883 libary. Only used while read MSFT
886 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
887 struct tagITypeLibImpl
*next
, *prev
;
892 static const ITypeLib2Vtbl tlbvt
;
893 static const ITypeCompVtbl tlbtcvt
;
895 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
896 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
898 /* ITypeLib methods */
899 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
900 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
902 /*======================= ITypeInfo implementation =======================*/
904 /* data for referenced types */
905 typedef struct tagTLBRefType
907 INT index
; /* Type index for internal ref or for external ref
908 it the format is SLTG. -2 indicates to
911 GUID guid
; /* guid of the referenced type */
912 /* if index == TLB_REF_USE_GUID */
914 HREFTYPE reference
; /* The href of this ref */
915 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
916 TLB_REF_INTERNAL for internal refs
917 TLB_REF_NOT_FOUND for broken refs */
919 struct tagTLBRefType
* next
;
922 #define TLB_REF_USE_GUID -2
924 #define TLB_REF_INTERNAL (void*)-2
925 #define TLB_REF_NOT_FOUND (void*)-1
927 /* internal Parameter data */
928 typedef struct tagTLBParDesc
932 TLBCustData
* pCustData
; /* linked list to cust data */
935 /* internal Function data */
936 typedef struct tagTLBFuncDesc
938 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
939 BSTR Name
; /* the name of this function */
940 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
942 int HelpStringContext
;
944 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
946 TLBCustData
* pCustData
; /* linked list to cust data; */
947 struct tagTLBFuncDesc
* next
;
950 /* internal Variable data */
951 typedef struct tagTLBVarDesc
953 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
954 BSTR Name
; /* the name of this variable */
956 int HelpStringContext
; /* FIXME: where? */
959 TLBCustData
* pCustData
;/* linked list to cust data; */
960 struct tagTLBVarDesc
* next
;
963 /* internal implemented interface data */
964 typedef struct tagTLBImplType
966 HREFTYPE hRef
; /* hRef of interface */
967 int implflags
; /* IMPLFLAG_*s */
969 TLBCustData
* pCustData
;/* linked list to custom data; */
970 struct tagTLBImplType
*next
;
973 /* internal TypeInfo data */
974 typedef struct tagITypeInfoImpl
976 const ITypeInfo2Vtbl
*lpVtbl
;
977 const ITypeCompVtbl
*lpVtblTypeComp
;
979 TYPEATTR TypeAttr
; /* _lots_ of type information. */
980 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
981 int index
; /* index in this typelib; */
982 /* type libs seem to store the doc strings in ascii
983 * so why should we do it in unicode?
987 unsigned long dwHelpContext
;
988 unsigned long dwHelpStringContext
;
991 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
994 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
996 /* Implemented Interfaces */
997 TLBImplType
* impltypelist
;
999 TLBRefType
* reflist
;
1001 TLBCustData
* pCustData
; /* linked list to cust data; */
1002 struct tagITypeInfoImpl
* next
;
1005 static const ITypeInfo2Vtbl tinfvt
;
1006 static const ITypeCompVtbl tcompvt
;
1008 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void);
1010 typedef struct tagTLBContext
1012 unsigned int oStart
; /* start of TLB in file */
1013 unsigned int pos
; /* current pos */
1014 unsigned int length
; /* total length */
1015 void *mapping
; /* memory mapping */
1016 MSFT_SegDir
* pTblDir
;
1017 ITypeLibImpl
* pLibInfo
;
1021 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
1026 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
1027 if (pTD
->vt
& VT_RESERVED
)
1028 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1029 if (pTD
->vt
& VT_BYREF
)
1030 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1031 if (pTD
->vt
& VT_ARRAY
)
1032 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1033 if (pTD
->vt
& VT_VECTOR
)
1034 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1035 switch(pTD
->vt
& VT_TYPEMASK
) {
1036 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1037 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1038 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1039 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1040 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1041 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1042 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1043 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1044 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1045 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1046 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1047 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1048 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1049 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1050 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1051 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1052 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1053 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1054 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1055 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1056 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
1057 pTD
->u
.hreftype
); break;
1058 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1059 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1061 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1062 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1064 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1065 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1066 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1069 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1073 void dump_ELEMDESC(ELEMDESC
*edesc
) {
1075 dump_TypeDesc(&edesc
->tdesc
,buf
);
1076 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1077 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
1078 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1080 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
1082 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
1083 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1084 MESSAGE("Param %d:\n",i
);
1085 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1087 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1088 switch (funcdesc
->funckind
) {
1089 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1090 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1091 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1092 case FUNC_STATIC
: MESSAGE("static");break;
1093 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1094 default: MESSAGE("unknown");break;
1096 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1097 switch (funcdesc
->invkind
) {
1098 case INVOKE_FUNC
: MESSAGE("func");break;
1099 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1100 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1101 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1103 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1104 switch (funcdesc
->callconv
) {
1105 case CC_CDECL
: MESSAGE("cdecl");break;
1106 case CC_PASCAL
: MESSAGE("pascal");break;
1107 case CC_STDCALL
: MESSAGE("stdcall");break;
1108 case CC_SYSCALL
: MESSAGE("syscall");break;
1111 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1112 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1113 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1115 MESSAGE("\telemdescFunc (return value type):\n");
1116 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1119 void dump_IDLDESC(IDLDESC
*idl
) {
1120 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
1123 static const char * typekind_desc
[] =
1136 void dump_TYPEATTR(TYPEATTR
*tattr
) {
1138 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
1139 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
1140 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
1141 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
1142 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
1143 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
1144 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
1145 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
1146 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
1147 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
1148 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
1149 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
1150 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
1151 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
1152 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
1153 MESSAGE("\ttypedesc: %s\n", buf
);
1154 dump_IDLDESC(&tattr
->idldescType
);
1157 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
1160 if (!TRACE_ON(typelib
))
1162 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1163 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1164 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1167 dump_FUNCDESC(&(pfd
->funcdesc
));
1169 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1170 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1172 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
1176 dump_TLBFuncDescOne(pfd
);
1180 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
1184 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1189 static void dump_TLBImpLib(TLBImpLib
*import
)
1191 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1192 debugstr_w(import
->name
));
1193 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1194 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1197 static void dump_TLBRefType(TLBRefType
* prt
)
1201 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1202 if(prt
->index
== -1)
1203 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1205 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1207 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1208 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1209 TRACE_(typelib
)("in lib\n");
1210 dump_TLBImpLib(prt
->pImpTLInfo
);
1216 static void dump_TLBImplType(TLBImplType
* impl
)
1220 "implementing/inheriting interface hRef = %lx implflags %x\n",
1221 impl
->hRef
, impl
->implflags
);
1226 void dump_Variant(VARIANT
* pvar
)
1230 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1234 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1235 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1237 TRACE(",%p", V_BYREF(pvar
));
1239 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1243 else switch (V_TYPE(pvar
))
1245 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1246 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1247 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1248 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1250 case VT_I4
: TRACE(",%ld", V_I4(pvar
)); break;
1252 case VT_UI4
: TRACE(",%ld", V_UI4(pvar
)); break;
1253 case VT_I8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_I8(pvar
) >> 32),
1254 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1255 case VT_UI8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_UI8(pvar
) >> 32),
1256 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1257 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1258 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1259 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1260 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1261 case VT_CY
: TRACE(",0x%08lx,0x%08lx", V_CY(pvar
).s
.Hi
,
1262 V_CY(pvar
).s
.Lo
); break;
1264 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1265 TRACE(",<invalid>");
1267 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1268 st
.wHour
, st
.wMinute
, st
.wSecond
);
1272 case VT_USERDEFINED
:
1274 case VT_NULL
: break;
1275 default: TRACE(",?"); break;
1281 static void dump_DispParms(DISPPARAMS
* pdp
)
1285 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1287 while (index
< pdp
->cArgs
)
1289 dump_Variant( &pdp
->rgvarg
[index
] );
1294 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1296 TRACE("%p ref=%lu\n", pty
, pty
->ref
);
1297 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1298 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1299 TRACE("fct:%u var:%u impl:%u\n",
1300 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1301 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1302 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1303 dump_TLBFuncDesc(pty
->funclist
);
1304 dump_TLBVarDesc(pty
->varlist
);
1305 dump_TLBImplType(pty
->impltypelist
);
1308 void dump_VARDESC(VARDESC
*v
)
1310 MESSAGE("memid %ld\n",v
->memid
);
1311 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1312 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1313 dump_ELEMDESC(&(v
->elemdescVar
));
1314 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1315 MESSAGE("varkind %d\n",v
->varkind
);
1318 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1320 /* VT_LPWSTR is largest type that */
1321 /* may appear in type description*/
1322 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1323 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1324 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1325 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1326 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1327 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1331 static void TLB_abort()
1335 static void * TLB_Alloc(unsigned size
)
1338 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1340 ERR("cannot allocate memory\n");
1345 static void TLB_Free(void * ptr
)
1347 HeapFree(GetProcessHeap(), 0, ptr
);
1350 /* deep copy a typedesc */
1351 static void copy_typedesc(TYPEDESC
*out
, const TYPEDESC
*in
)
1356 out
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC
));
1357 copy_typedesc(out
->u
.lptdesc
, in
->u
.lptdesc
);
1359 case VT_USERDEFINED
:
1360 out
->u
.hreftype
= in
->u
.hreftype
;
1363 out
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC
) +
1364 (in
->u
.lpadesc
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
1365 copy_typedesc(&out
->u
.lpadesc
->tdescElem
, &in
->u
.lpadesc
->tdescElem
);
1366 out
->u
.lpadesc
->cDims
= in
->u
.lpadesc
->cDims
;
1367 memcpy(out
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->rgbounds
, in
->u
.lpadesc
->cDims
* sizeof(SAFEARRAYBOUND
));
1374 /* free()s any allocated memory pointed to by the tdesc. NB does not
1375 free the tdesc itself - this is because the tdesc is typically part
1376 of a larger structure */
1377 static void free_deep_typedesc(TYPEDESC
*tdesc
)
1381 free_deep_typedesc(tdesc
->u
.lptdesc
);
1382 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lptdesc
);
1383 tdesc
->u
.lptdesc
= NULL
;
1386 free_deep_typedesc(&tdesc
->u
.lpadesc
->tdescElem
);
1387 HeapFree(GetProcessHeap(), 0, tdesc
->u
.lpadesc
);
1388 tdesc
->u
.lpadesc
= NULL
;
1395 /**********************************************************************
1397 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1400 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1402 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1403 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1405 if (where
!= DO_NOT_SEEK
)
1407 where
+= pcx
->oStart
;
1408 if (where
> pcx
->length
)
1411 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1416 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1417 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1422 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1427 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1428 FromLEDWords(buffer
, ret
);
1433 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1438 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1439 FromLEWords(buffer
, ret
);
1444 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1446 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1447 memset(pGuid
,0, sizeof(GUID
));
1450 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1451 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1452 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1453 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1454 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1457 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1460 MSFT_NameIntro niName
;
1462 WCHAR
* pwstring
= NULL
;
1463 BSTR bstrName
= NULL
;
1465 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1466 pcx
->pTblDir
->pNametab
.offset
+offset
);
1467 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1468 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1469 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1470 name
[niName
.namelen
& 0xff]='\0';
1472 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1475 /* no invalid characters in string */
1478 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1480 /* don't check for invalid character since this has been done previously */
1481 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1483 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1484 lengthInChars
= SysStringLen(bstrName
);
1485 HeapFree(GetProcessHeap(), 0, pwstring
);
1488 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1492 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1499 if(offset
<0) return NULL
;
1500 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1501 if(length
<= 0) return 0;
1502 string
=TLB_Alloc(length
+1);
1503 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1504 string
[length
]='\0';
1506 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1507 string
, -1, NULL
, 0);
1509 /* no invalid characters in string */
1512 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1514 /* don't check for invalid character since this has been done previously */
1515 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1517 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1518 lengthInChars
= SysStringLen(bstr
);
1519 HeapFree(GetProcessHeap(), 0, pwstring
);
1522 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1526 * read a value and fill a VARIANT structure
1528 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1532 TRACE_(typelib
)("\n");
1534 if(offset
<0) { /* data are packed in here */
1535 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1536 V_I2(pVar
) = offset
& 0x3ffffff;
1539 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1540 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1541 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1542 switch (V_VT(pVar
)){
1543 case VT_EMPTY
: /* FIXME: is this right? */
1544 case VT_NULL
: /* FIXME: is this right? */
1545 case VT_I2
: /* this should not happen */
1556 case VT_VOID
: /* FIXME: is this right? */
1564 case VT_DECIMAL
: /* FIXME: is this right? */
1567 /* pointer types with known behaviour */
1570 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1572 FIXME("BSTR length = %d?\n", size
);
1574 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1575 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1576 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1577 /* FIXME: do we need a AtoW conversion here? */
1578 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1579 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1584 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1591 case VT_USERDEFINED
:
1597 case VT_STREAMED_OBJECT
:
1598 case VT_STORED_OBJECT
:
1599 case VT_BLOB_OBJECT
:
1604 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1608 if(size
>0) /* (big|small) endian correct? */
1609 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1613 * create a linked list with custom data
1615 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1621 TRACE_(typelib
)("\n");
1625 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1626 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1627 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1628 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1629 /* add new custom data at head of the list */
1630 pNew
->next
=*ppCustData
;
1632 offset
= entry
.next
;
1637 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1641 pTd
->vt
=type
& VT_TYPEMASK
;
1643 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1645 if(pTd
->vt
== VT_USERDEFINED
)
1646 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1648 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1652 MSFT_DoFuncs(TLBContext
* pcx
,
1657 TLBFuncDesc
** pptfd
)
1660 * member information is stored in a data structure at offset
1661 * indicated by the memoffset field of the typeinfo structure
1662 * There are several distinctive parts.
1663 * The first part starts with a field that holds the total length
1664 * of this (first) part excluding this field. Then follow the records,
1665 * for each member there is one record.
1667 * The first entry is always the length of the record (including this
1669 * The rest of the record depends on the type of the member. If there is
1670 * a field indicating the member type (function, variable, interface, etc)
1671 * I have not found it yet. At this time we depend on the information
1672 * in the type info and the usual order how things are stored.
1674 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1677 * Third is an equal sized array with file offsets to the name entry
1680 * The fourth and last (?) part is an array with offsets to the records
1681 * in the first part of this file segment.
1684 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1685 int recoffset
= offset
+ sizeof(INT
);
1688 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1690 TRACE_(typelib
)("\n");
1692 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1694 for ( i
= 0; i
< cFuncs
; i
++ )
1696 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1698 /* name, eventually add to a hash table */
1699 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1700 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1702 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1704 /* read the function information record */
1705 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1709 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1711 /* do the attributes */
1712 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1715 if ( nrattributes
> 0 )
1717 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1719 if ( nrattributes
> 1 )
1721 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1722 pFuncRec
->OptAttr
[1]) ;
1724 if ( nrattributes
> 2 )
1726 if ( pFuncRec
->FKCCIC
& 0x2000 )
1728 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1732 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1733 pFuncRec
->OptAttr
[2]);
1735 if( nrattributes
> 5 )
1737 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1739 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1742 pFuncRec
->OptAttr
[6],
1743 &(*pptfd
)->pCustData
);
1750 /* fill the FuncDesc Structure */
1751 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1752 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1754 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1755 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1756 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1757 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1758 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1759 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1760 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1764 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1767 /* do the parameters/arguments */
1768 if(pFuncRec
->nrargs
)
1771 MSFT_ParameterInfo paraminfo
;
1773 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1774 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1776 (*pptfd
)->pParamDesc
=
1777 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1779 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1780 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1782 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1784 TYPEDESC
* lpArgTypeDesc
= 0;
1788 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1791 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1793 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1795 /* SEEK value = jump to offset,
1796 * from there jump to the end of record,
1797 * go back by (j-1) arguments
1799 MSFT_ReadLEDWords( ¶minfo
,
1800 sizeof(MSFT_ParameterInfo
), pcx
,
1801 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1802 * sizeof(MSFT_ParameterInfo
)));
1804 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1806 while ( lpArgTypeDesc
!= NULL
)
1808 switch ( lpArgTypeDesc
->vt
)
1811 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1815 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1818 case VT_USERDEFINED
:
1819 MSFT_DoRefType(pcx
, pTI
,
1820 lpArgTypeDesc
->u
.hreftype
);
1822 lpArgTypeDesc
= NULL
;
1826 lpArgTypeDesc
= NULL
;
1832 /* parameter is the return value! */
1833 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1835 TYPEDESC
* lpArgTypeDesc
;
1837 (*pptfd
)->funcdesc
.elemdescFunc
=
1838 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1840 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1842 while ( lpArgTypeDesc
!= NULL
)
1844 switch ( lpArgTypeDesc
->vt
)
1847 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1851 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1855 case VT_USERDEFINED
:
1858 lpArgTypeDesc
->u
.hreftype
);
1860 lpArgTypeDesc
= NULL
;
1864 lpArgTypeDesc
= NULL
;
1869 /* second time around */
1870 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1873 (*pptfd
)->pParamDesc
[j
].Name
=
1874 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1877 if ( (PARAMFLAG_FHASDEFAULT
&
1878 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1879 ((pFuncRec
->FKCCIC
) & 0x1000) )
1881 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1883 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1885 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1887 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1888 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1890 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1894 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1897 pFuncRec
->OptAttr
[7+j
],
1898 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1903 /* scode is not used: archaic win16 stuff FIXME: right? */
1904 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1905 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1907 pptfd
= & ((*pptfd
)->next
);
1908 recoffset
+= reclength
;
1912 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1913 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1915 int infolen
, nameoffset
, reclength
;
1917 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1921 TRACE_(typelib
)("\n");
1923 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1924 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1925 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1926 recoffset
+= offset
+sizeof(INT
);
1927 for(i
=0;i
<cVars
;i
++){
1928 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1929 /* name, eventually add to a hash table */
1930 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1931 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1932 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1933 /* read the variable information record */
1934 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1936 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1938 if(reclength
>(6*sizeof(INT
)) )
1939 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1940 if(reclength
>(7*sizeof(INT
)) )
1941 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1942 if(reclength
>(8*sizeof(INT
)) )
1943 if(reclength
>(9*sizeof(INT
)) )
1944 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1945 /* fill the VarDesc Structure */
1946 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1947 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1948 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1949 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1950 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1951 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1952 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1953 if(pVarRec
->VarKind
== VAR_CONST
){
1954 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1955 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1956 pVarRec
->OffsValue
, pcx
);
1958 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1959 pptvd
=&((*pptvd
)->next
);
1960 recoffset
+= reclength
;
1963 /* fill in data for a hreftype (offset). When the referenced type is contained
1964 * in the typelib, it's just an (file) offset in the type info base dir.
1965 * If comes from import, it's an offset+1 in the ImpInfo table
1967 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1971 TLBRefType
**ppRefType
= &pTI
->reflist
;
1973 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1976 if((*ppRefType
)->reference
== offset
)
1978 ppRefType
= &(*ppRefType
)->next
;
1981 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1982 sizeof(**ppRefType
));
1984 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1985 /* external typelib */
1986 MSFT_ImpInfo impinfo
;
1987 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1989 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1991 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1992 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1993 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1994 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1995 pImpLib
=pImpLib
->next
;
1998 (*ppRefType
)->reference
=offset
;
1999 (*ppRefType
)->pImpTLInfo
= pImpLib
;
2000 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
2001 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
2003 ERR("Cannot find a reference\n");
2004 (*ppRefType
)->reference
=-1;
2005 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
2008 /* in this typelib */
2009 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
2010 (*ppRefType
)->reference
=offset
;
2011 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
2015 /* process Implemented Interfaces of a com class */
2016 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2020 MSFT_RefRecord refrec
;
2021 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
2023 TRACE_(typelib
)("\n");
2025 for(i
=0;i
<count
;i
++){
2026 if(offset
<0) break; /* paranoia */
2027 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
2028 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2029 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
2030 (*ppImpl
)->hRef
= refrec
.reftype
;
2031 (*ppImpl
)->implflags
=refrec
.flags
;
2032 (*ppImpl
)->ctCustData
=
2033 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
2034 offset
=refrec
.onext
;
2035 ppImpl
=&((*ppImpl
)->next
);
2039 * process a typeinfo record
2041 ITypeInfoImpl
* MSFT_DoTypeInfo(
2044 ITypeLibImpl
* pLibInfo
)
2046 MSFT_TypeInfoBase tiBase
;
2047 ITypeInfoImpl
*ptiRet
;
2049 TRACE_(typelib
)("count=%u\n", count
);
2051 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
2052 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2053 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2054 /* this is where we are coming from */
2055 ptiRet
->pTypeLib
= pLibInfo
;
2056 ptiRet
->index
=count
;
2057 /* fill in the typeattr fields */
2058 WARN("Assign constructor/destructor memid\n");
2060 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2061 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2062 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
2063 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
2064 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2065 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2066 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2067 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2068 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2069 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2070 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2071 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2072 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2073 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2074 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2075 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2076 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2077 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2080 /* IDLDESC idldescType; *//* never saw this one != zero */
2082 /* name, eventually add to a hash table */
2083 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2084 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2086 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2087 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2088 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2089 /* note: InfoType's Help file and HelpStringDll come from the containing
2090 * library. Further HelpString and Docstring appear to be the same thing :(
2093 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2094 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2095 ptiRet
->TypeAttr
.cVars
,
2096 tiBase
.memoffset
, & ptiRet
->funclist
);
2098 if(ptiRet
->TypeAttr
.cVars
>0 )
2099 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2100 ptiRet
->TypeAttr
.cVars
,
2101 tiBase
.memoffset
, & ptiRet
->varlist
);
2102 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2103 switch(ptiRet
->TypeAttr
.typekind
)
2106 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2109 case TKIND_DISPATCH
:
2110 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2112 if (tiBase
.datatype1
!= -1)
2114 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2115 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2118 { /* FIXME: This is a really bad hack to add IDispatch */
2119 const char* szStdOle
= "stdole2.tlb\0";
2120 int nStdOleLen
= strlen(szStdOle
);
2121 TLBRefType
**ppRef
= &ptiRet
->reflist
;
2124 if((*ppRef
)->reference
== -1)
2126 ppRef
= &(*ppRef
)->next
;
2129 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
2130 (*ppRef
)->guid
= IID_IDispatch
;
2131 (*ppRef
)->reference
= -1;
2132 (*ppRef
)->index
= TLB_REF_USE_GUID
;
2133 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
2134 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
2135 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
2138 MultiByteToWideChar(CP_ACP
,
2142 (*ppRef
)->pImpTLInfo
->name
,
2143 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
2145 (*ppRef
)->pImpTLInfo
->lcid
= 0;
2146 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
2147 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
2152 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2153 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2154 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2159 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2161 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2162 debugstr_w(ptiRet
->Name
),
2163 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2164 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2169 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2170 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2171 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2174 static ITypeLibImpl
*tlb_cache_first
;
2175 static CRITICAL_SECTION cache_section
;
2176 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2178 0, 0, &cache_section
,
2179 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2180 0, 0, { 0, (DWORD
)(__FILE__
": typelib loader cache") }
2182 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2185 /****************************************************************************
2188 * find the type of the typelib file and map the typelib resource into
2191 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2192 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2193 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2195 ITypeLibImpl
*entry
;
2196 int ret
= TYPE_E_CANTLOADLIBRARY
;
2197 DWORD dwSignature
= 0;
2200 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2204 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2205 EnterCriticalSection(&cache_section
);
2206 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2208 if (!strcmpiW(entry
->path
, pszFileName
) && entry
->index
== index
)
2210 TRACE("cache hit\n");
2211 *ppTypeLib
= (ITypeLib2
*)entry
;
2212 ITypeLib_AddRef(*ppTypeLib
);
2213 LeaveCriticalSection(&cache_section
);
2217 LeaveCriticalSection(&cache_section
);
2219 /* check the signature of the file */
2220 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2221 if (INVALID_HANDLE_VALUE
!= hFile
)
2223 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2226 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2229 /* retrieve file size */
2230 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2232 /* first try to load as *.tlb */
2233 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2234 if ( dwSignature
== MSFT_SIGNATURE
)
2236 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2238 else if ( dwSignature
== SLTG_SIGNATURE
)
2240 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2242 UnmapViewOfFile(pBase
);
2244 CloseHandle(hMapping
);
2250 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName
));
2253 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2254 if (((WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
) || (dwSignature
== 0))
2256 /* find the typelibrary resource*/
2257 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2258 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2261 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2262 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2265 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2268 LPVOID pBase
= LockResource(hGlobal
);
2269 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2273 /* try to load as incore resource */
2274 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2275 if ( dwSignature
== MSFT_SIGNATURE
)
2277 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2279 else if ( dwSignature
== SLTG_SIGNATURE
)
2281 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2285 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2288 FreeResource( hGlobal
);
2291 FreeLibrary(hinstDLL
);
2296 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2298 TRACE("adding to cache\n");
2299 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2300 lstrcpyW(impl
->path
, pszFileName
);
2301 /* We should really canonicalise the path here. */
2302 impl
->index
= index
;
2304 /* FIXME: check if it has added already in the meantime */
2305 EnterCriticalSection(&cache_section
);
2306 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2308 tlb_cache_first
= impl
;
2309 LeaveCriticalSection(&cache_section
);
2312 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2317 /*================== ITypeLib(2) Methods ===================================*/
2319 /****************************************************************************
2320 * ITypeLib2_Constructor_MSFT
2322 * loading an MSFT typelib from an in-memory image
2324 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2328 MSFT_Header tlbHeader
;
2329 MSFT_SegDir tlbSegDir
;
2330 ITypeLibImpl
* pTypeLibImpl
;
2332 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2334 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2335 if (!pTypeLibImpl
) return NULL
;
2337 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2338 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2339 pTypeLibImpl
->ref
= 1;
2341 /* get pointer to beginning of typelib data */
2345 cx
.pLibInfo
= pTypeLibImpl
;
2346 cx
.length
= dwTLBLength
;
2349 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2351 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2352 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2353 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2356 /* there is a small amount of information here until the next important
2358 * the segment directory . Try to calculate the amount of data */
2359 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2361 /* now read the segment directory */
2362 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2363 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2364 cx
.pTblDir
= &tlbSegDir
;
2366 /* just check two entries */
2367 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2369 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2370 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2374 /* now fill our internal data */
2375 /* TLIBATTR fields */
2376 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2378 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2379 /* Windows seems to have zero here, is this correct? */
2380 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2381 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2383 pTypeLibImpl
->LibAttr
.lcid
= 0;
2385 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2386 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2387 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2388 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2390 /* name, eventually add to a hash table */
2391 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2394 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2395 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2397 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2400 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2401 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2404 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2407 if(tlbHeader
.CustomDataOffset
>= 0)
2409 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2412 /* fill in typedescriptions */
2413 if(tlbSegDir
.pTypdescTab
.length
> 0)
2415 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2417 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2418 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2421 /* FIXME: add several sanity checks here */
2422 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2423 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2425 /* FIXME: check safearray */
2427 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2429 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2431 else if(td
[0] == VT_CARRAY
)
2433 /* array descr table here */
2434 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2436 else if(td
[0] == VT_USERDEFINED
)
2438 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2440 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2443 /* second time around to fill the array subscript info */
2446 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2447 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2449 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2450 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2453 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2455 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2457 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2459 for(j
= 0; j
<td
[2]; j
++)
2461 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2462 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2463 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2464 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2469 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2470 ERR("didn't find array description data\n");
2475 /* imported type libs */
2476 if(tlbSegDir
.pImpFiles
.offset
>0)
2478 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2479 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2482 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2487 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2488 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2489 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2491 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2492 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2493 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2494 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2497 name
= TLB_Alloc(size
+1);
2498 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2499 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2500 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2501 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2504 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2505 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2507 ppImpLib
= &(*ppImpLib
)->next
;
2512 if(tlbHeader
.nrtypeinfos
>= 0 )
2514 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2515 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2518 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2520 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2522 ppTI
= &((*ppTI
)->next
);
2523 (pTypeLibImpl
->TypeInfoCount
)++;
2527 TRACE("(%p)\n", pTypeLibImpl
);
2528 return (ITypeLib2
*) pTypeLibImpl
;
2532 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2538 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2539 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2540 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2541 ret
= SysAllocString(nameW
);
2542 HeapFree(GetProcessHeap(), 0, nameW
);
2546 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2552 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2553 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2557 guid
->Data4
[0] = s
>> 8;
2558 guid
->Data4
[1] = s
& 0xff;
2561 for(i
= 0; i
< 6; i
++) {
2562 memcpy(b
, str
+ 24 + 2 * i
, 2);
2563 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2568 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2575 bytelen
= *(WORD
*)ptr
;
2576 if(bytelen
== 0xffff) return 2;
2577 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2578 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2579 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2580 *pBstr
= SysAllocStringLen(nameW
, len
);
2581 HeapFree(GetProcessHeap(), 0, nameW
);
2585 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2590 bytelen
= *(WORD
*)ptr
;
2591 if(bytelen
== 0xffff) return 2;
2592 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2593 memcpy(*str
, ptr
+ 2, bytelen
);
2594 (*str
)[bytelen
] = '\0';
2598 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2600 char *ptr
= pLibBlk
;
2603 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2604 FIXME("libblk magic = %04x\n", w
);
2609 if((w
= *(WORD
*)ptr
) != 0xffff) {
2610 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2615 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2617 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2619 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2622 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2625 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2626 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2628 pTypeLibImpl
->LibAttr
.lcid
= 0;
2631 ptr
+= 4; /* skip res12 */
2633 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2636 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2639 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2642 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2643 ptr
+= sizeof(GUID
);
2645 return ptr
- (char*)pLibBlk
;
2648 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2651 TYPEDESC
*pTD
= &pElem
->tdesc
;
2653 /* Handle [in/out] first */
2654 if((*pType
& 0xc000) == 0xc000)
2655 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2656 else if(*pType
& 0x8000)
2657 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2658 else if(*pType
& 0x4000)
2659 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2661 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2664 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2667 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2670 if((*pType
& 0xe00) == 0xe00) {
2672 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2674 pTD
= pTD
->u
.lptdesc
;
2676 switch(*pType
& 0x7f) {
2679 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2681 pTD
= pTD
->u
.lptdesc
;
2684 case VT_USERDEFINED
:
2685 pTD
->vt
= VT_USERDEFINED
;
2686 pTD
->u
.hreftype
= *(++pType
) / 4;
2692 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2695 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2697 pTD
->vt
= VT_CARRAY
;
2698 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2700 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2701 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2702 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2703 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2705 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2711 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2715 pTD
->vt
= VT_SAFEARRAY
;
2716 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2718 pTD
= pTD
->u
.lptdesc
;
2722 pTD
->vt
= *pType
& 0x7f;
2732 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2737 TLBRefType
**ppRefType
;
2739 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2740 FIXME("Ref magic = %x\n", pRef
->magic
);
2743 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2745 ppRefType
= &pTI
->reflist
;
2746 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2748 unsigned int lib_offs
, type_num
;
2750 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2751 sizeof(**ppRefType
));
2753 name
+= SLTG_ReadStringA(name
, &refname
);
2754 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2755 FIXME("Can't sscanf ref\n");
2756 if(lib_offs
!= 0xffff) {
2757 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2760 if((*import
)->offset
== lib_offs
)
2762 import
= &(*import
)->next
;
2765 char fname
[MAX_PATH
+1];
2768 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2770 (*import
)->offset
= lib_offs
;
2771 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2773 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2774 &(*import
)->wVersionMajor
,
2775 &(*import
)->wVersionMinor
,
2776 &(*import
)->lcid
, fname
) != 4) {
2777 FIXME("can't sscanf ref %s\n",
2778 pNameTable
+ lib_offs
+ 40);
2780 len
= strlen(fname
);
2781 if(fname
[len
-1] != '#')
2782 FIXME("fname = %s\n", fname
);
2783 fname
[len
-1] = '\0';
2784 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2786 (*ppRefType
)->pImpTLInfo
= *import
;
2787 } else { /* internal ref */
2788 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2790 (*ppRefType
)->reference
= ref
;
2791 (*ppRefType
)->index
= type_num
;
2793 HeapFree(GetProcessHeap(), 0, refname
);
2794 ppRefType
= &(*ppRefType
)->next
;
2796 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2797 FIXME("End of ref block magic = %x\n", *name
);
2798 dump_TLBRefType(pTI
->reflist
);
2801 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2804 SLTG_ImplInfo
*info
;
2805 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2806 /* I don't really get this structure, usually it's 0x16 bytes
2807 long, but iuser.tlb contains some that are 0x18 bytes long.
2808 That's ok because we can use the next ptr to jump to the next
2809 one. But how do we know the length of the last one? The WORD
2810 at offs 0x8 might be the clue. For now I'm just assuming that
2811 the last one is the regular 0x16 bytes. */
2813 info
= (SLTG_ImplInfo
*)pBlk
;
2815 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2816 sizeof(**ppImplType
));
2817 (*ppImplType
)->hRef
= info
->ref
;
2818 (*ppImplType
)->implflags
= info
->impltypeflags
;
2819 pTI
->TypeAttr
.cImplTypes
++;
2820 ppImplType
= &(*ppImplType
)->next
;
2822 if(info
->next
== 0xffff)
2825 FIXME("Interface inheriting more than one interface\n");
2826 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2828 info
++; /* see comment at top of function */
2832 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2835 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2836 SLTG_MemberHeader
*pMemHeader
;
2837 char *pFirstItem
, *pNextItem
;
2839 if(pTIHeader
->href_table
!= 0xffffffff) {
2840 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2845 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2847 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2849 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2850 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2853 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2857 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2860 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2861 SLTG_MemberHeader
*pMemHeader
;
2862 SLTG_Function
*pFunc
;
2863 char *pFirstItem
, *pNextItem
;
2864 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2867 if(pTIHeader
->href_table
!= 0xffffffff) {
2868 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2872 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2874 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2876 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2877 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2880 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2881 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2886 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2887 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2888 FIXME("func magic = %02x\n", pFunc
->magic
);
2891 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2892 sizeof(**ppFuncDesc
));
2893 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2895 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2896 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2897 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2898 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2899 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2900 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2902 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2903 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2905 if(pFunc
->retnextopt
& 0x80)
2906 pType
= &pFunc
->rettype
;
2908 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2911 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2913 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2914 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2915 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2916 (*ppFuncDesc
)->pParamDesc
=
2917 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2918 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2920 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2922 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2923 char *paramName
= pNameTable
+ *pArg
;
2925 /* If arg type follows then paramName points to the 2nd
2926 letter of the name, else the next WORD is an offset to
2927 the arg type and paramName points to the first letter.
2928 So let's take one char off paramName and see if we're
2929 pointing at an alpha-numeric char. However if *pArg is
2930 0xffff or 0xfffe then the param has no name, the former
2931 meaning that the next WORD is the type, the latter
2932 meaning the the next WORD is an offset to the type. */
2937 else if(*pArg
== 0xfffe) {
2941 else if(!isalnum(*(paramName
-1)))
2946 if(HaveOffs
) { /* the next word is an offset to type */
2947 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2948 SLTG_DoType(pType
, pFirstItem
,
2949 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2954 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2955 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2958 /* Are we an optional param ? */
2959 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2960 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2961 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2964 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2965 TLB_MultiByteToBSTR(paramName
);
2969 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2970 if(pFunc
->next
== 0xffff) break;
2972 pTI
->TypeAttr
.cFuncs
= num
;
2973 dump_TLBFuncDesc(pTI
->funclist
);
2974 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2977 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2980 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2981 SLTG_MemberHeader
*pMemHeader
;
2982 SLTG_RecordItem
*pItem
;
2984 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2989 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2991 pFirstItem
= (char*)(pMemHeader
+ 1);
2992 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2993 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2994 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2995 FIXME("record magic = %02x\n", pItem
->magic
);
2998 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2999 sizeof(**ppVarDesc
));
3000 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3001 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3002 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
3003 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
3005 if(pItem
->typepos
== 0x02)
3006 pType
= &pItem
->type
;
3007 else if(pItem
->typepos
== 0x00)
3008 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
3010 FIXME("typepos = %02x\n", pItem
->typepos
);
3014 SLTG_DoType(pType
, pFirstItem
,
3015 &(*ppVarDesc
)->vardesc
.elemdescVar
);
3017 /* FIXME("helpcontext, helpstring\n"); */
3019 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
3021 ppVarDesc
= &((*ppVarDesc
)->next
);
3022 if(pItem
->next
== 0xffff) break;
3024 pTI
->TypeAttr
.cVars
= num
;
3025 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3028 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3031 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3032 SLTG_MemberHeader
*pMemHeader
;
3033 SLTG_AliasItem
*pItem
;
3036 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3037 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3040 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3041 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
3042 if (pItem
->vt
== 0xffff) {
3043 if (i
<(pMemHeader
->cbExtra
/4-1))
3044 FIXME("Endmarker too early in process alias data!\n");
3048 FIXME("Chain extends over last entry?\n");
3051 if (pItem
->vt
== VT_USERDEFINED
) {
3052 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
3053 /* guessing here ... */
3054 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
3055 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
3058 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
3059 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
3063 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3066 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3069 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3070 SLTG_MemberHeader
*pMemHeader
;
3071 SLTG_AliasItem
*pItem
;
3073 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3074 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3075 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
3076 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
3077 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3080 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3083 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3084 SLTG_MemberHeader
*pMemHeader
;
3085 SLTG_EnumItem
*pItem
;
3087 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3090 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3092 pFirstItem
= (char*)(pMemHeader
+ 1);
3093 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
3094 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
3095 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
3096 FIXME("enumitem magic = %04x\n", pItem
->magic
);
3099 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3100 sizeof(**ppVarDesc
));
3101 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3102 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3103 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3105 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3106 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
3107 *(INT
*)(pItem
->value
+ pFirstItem
);
3108 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
3109 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3110 /* FIXME("helpcontext, helpstring\n"); */
3112 ppVarDesc
= &((*ppVarDesc
)->next
);
3113 if(pItem
->next
== 0xffff) break;
3115 pTI
->TypeAttr
.cVars
= num
;
3116 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3119 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3120 managable copy of it into this */
3133 } SLTG_InternalOtherTypeInfo
;
3135 /****************************************************************************
3136 * ITypeLib2_Constructor_SLTG
3138 * loading a SLTG typelib from an in-memory image
3140 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3142 ITypeLibImpl
*pTypeLibImpl
;
3143 SLTG_Header
*pHeader
;
3144 SLTG_BlkEntry
*pBlkEntry
;
3148 LPVOID pBlk
, pFirstBlk
;
3149 SLTG_LibBlk
*pLibBlk
;
3150 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3151 char *pAfterOTIBlks
= NULL
;
3152 char *pNameTable
, *ptr
;
3155 ITypeInfoImpl
**ppTypeInfoImpl
;
3157 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3159 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
3160 if (!pTypeLibImpl
) return NULL
;
3162 pTypeLibImpl
->lpVtbl
= &tlbvt
;
3163 pTypeLibImpl
->ref
= 1;
3168 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
3169 pHeader
->nrOfFileBlks
);
3170 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3171 FIXME("Header type magic 0x%08lx not supported.\n",
3172 pHeader
->SLTG_magic
);
3176 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3177 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3179 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3180 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3182 /* Next we have a magic block */
3183 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3185 /* Let's see if we're still in sync */
3186 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3187 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3188 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3191 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3192 sizeof(SLTG_DIR_MAGIC
))) {
3193 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3197 pIndex
= (SLTG_Index
*)(pMagic
+1);
3199 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3201 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3203 /* We'll set up a ptr to the main library block, which is the last one. */
3205 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3206 pBlkEntry
[order
].next
!= 0;
3207 order
= pBlkEntry
[order
].next
- 1, i
++) {
3208 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3212 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3214 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3219 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3221 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3222 sizeof(*pOtherTypeInfoBlks
) *
3223 pTypeLibImpl
->TypeInfoCount
);
3226 ptr
= (char*)pLibBlk
+ len
;
3228 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3232 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3234 w
= *(WORD
*)(ptr
+ 2);
3237 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3239 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3240 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3242 w
= *(WORD
*)(ptr
+ 4 + len
);
3244 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3246 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3248 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3249 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3251 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3252 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3253 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3255 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3257 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3260 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3261 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3262 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3263 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3264 len
+= sizeof(SLTG_OtherTypeInfo
);
3268 pAfterOTIBlks
= ptr
;
3270 /* Skip this WORD and get the next DWORD */
3271 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3273 /* Now add this to pLibBLk look at what we're pointing at and
3274 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3275 dust and we should be pointing at the beginning of the name
3278 pNameTable
= (char*)pLibBlk
+ len
;
3280 switch(*(WORD
*)pNameTable
) {
3287 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3291 pNameTable
+= 0x216;
3295 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3297 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3300 /* Hopefully we now have enough ptrs set up to actually read in
3301 some TypeInfos. It's not clear which order to do them in, so
3302 I'll just follow the links along the BlkEntry chain and read
3303 them in in the order in which they're in the file */
3305 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3307 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3308 pBlkEntry
[order
].next
!= 0;
3309 order
= pBlkEntry
[order
].next
- 1, i
++) {
3311 SLTG_TypeInfoHeader
*pTIHeader
;
3312 SLTG_TypeInfoTail
*pTITail
;
3314 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3315 pOtherTypeInfoBlks
[i
].index_name
)) {
3316 FIXME("Index strings don't match\n");
3321 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3322 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3325 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3326 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3327 (*ppTypeInfoImpl
)->index
= i
;
3328 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3329 pOtherTypeInfoBlks
[i
].name_offs
+
3331 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3332 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3334 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3335 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3336 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3337 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3338 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3340 if((pTIHeader
->typeflags1
& 7) != 2)
3341 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3342 if(pTIHeader
->typeflags3
!= 2)
3343 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3345 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3346 debugstr_w((*ppTypeInfoImpl
)->Name
),
3347 typekind_desc
[pTIHeader
->typekind
],
3348 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3349 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3351 switch(pTIHeader
->typekind
) {
3353 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3357 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3360 case TKIND_INTERFACE
:
3361 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3365 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3369 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3370 if (pTITail
->tdescalias_vt
)
3371 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3374 case TKIND_DISPATCH
:
3375 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3379 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3385 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3386 but we've already set those */
3387 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3388 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3389 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3391 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3413 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3414 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3417 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3418 FIXME("Somehow processed %d TypeInfos\n", i
);
3422 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3423 return (ITypeLib2
*)pTypeLibImpl
;
3426 /* ITypeLib::QueryInterface
3428 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3433 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3435 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3438 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3439 IsEqualIID(riid
,&IID_ITypeLib
)||
3440 IsEqualIID(riid
,&IID_ITypeLib2
))
3447 ITypeLib2_AddRef(iface
);
3448 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3451 TRACE("-- Interface: E_NOINTERFACE\n");
3452 return E_NOINTERFACE
;
3457 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3459 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3460 ULONG ref
= InterlockedIncrement(&This
->ref
);
3462 TRACE("(%p)->ref was %lu\n",This
, ref
- 1);
3467 /* ITypeLib::Release
3469 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3471 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3472 ULONG ref
= InterlockedDecrement(&This
->ref
);
3474 TRACE("(%p)->(%lu)\n",This
, ref
);
3478 /* remove cache entry */
3479 TRACE("removing from cache list\n");
3480 EnterCriticalSection(&cache_section
);
3481 if (This
->next
) This
->next
->prev
= This
->prev
;
3482 if (This
->prev
) This
->prev
->next
= This
->next
;
3483 else tlb_cache_first
= This
->next
;
3484 LeaveCriticalSection(&cache_section
);
3486 /* FIXME destroy child objects */
3487 TRACE(" destroying ITypeLib(%p)\n",This
);
3491 SysFreeString(This
->Name
);
3495 if (This
->DocString
)
3497 SysFreeString(This
->DocString
);
3498 This
->DocString
= NULL
;
3503 SysFreeString(This
->HelpFile
);
3504 This
->HelpFile
= NULL
;
3507 if (This
->HelpStringDll
)
3509 SysFreeString(This
->HelpStringDll
);
3510 This
->HelpStringDll
= NULL
;
3513 if (This
->pTypeInfo
) /* can be NULL */
3514 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3515 HeapFree(GetProcessHeap(),0,This
);
3522 /* ITypeLib::GetTypeInfoCount
3524 * Returns the number of type descriptions in the type library
3526 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3528 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3529 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3530 return This
->TypeInfoCount
;
3533 /* ITypeLib::GetTypeInfo
3535 * retrieves the specified type description in the library.
3537 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3540 ITypeInfo
**ppTInfo
)
3544 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3545 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3547 TRACE("(%p)->(index=%d) \n", This
, index
);
3549 if (!ppTInfo
) return E_INVALIDARG
;
3551 /* search element n in list */
3552 for(i
=0; i
< index
; i
++)
3554 pTypeInfo
= pTypeInfo
->next
;
3557 TRACE("-- element not found\n");
3558 return TYPE_E_ELEMENTNOTFOUND
;
3562 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3564 ITypeInfo_AddRef(*ppTInfo
);
3565 TRACE("-- found (%p)\n",*ppTInfo
);
3570 /* ITypeLibs::GetTypeInfoType
3572 * Retrieves the type of a type description.
3574 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3579 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3581 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3583 TRACE("(%p) index %d \n",This
, index
);
3585 if(!pTKind
) return E_INVALIDARG
;
3587 /* search element n in list */
3588 for(i
=0; i
< index
; i
++)
3592 TRACE("-- element not found\n");
3593 return TYPE_E_ELEMENTNOTFOUND
;
3595 pTInfo
= pTInfo
->next
;
3598 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3599 TRACE("-- found Type (%d)\n", *pTKind
);
3603 /* ITypeLib::GetTypeInfoOfGuid
3605 * Retrieves the type description that corresponds to the specified GUID.
3608 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3611 ITypeInfo
**ppTInfo
)
3613 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3614 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3616 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3618 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3620 /* search linked list for guid */
3621 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3623 pTypeInfo
= pTypeInfo
->next
;
3627 /* end of list reached */
3628 TRACE("-- element not found\n");
3629 return TYPE_E_ELEMENTNOTFOUND
;
3633 TRACE("-- found (%p, %s)\n",
3635 debugstr_w(pTypeInfo
->Name
));
3637 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3638 ITypeInfo_AddRef(*ppTInfo
);
3642 /* ITypeLib::GetLibAttr
3644 * Retrieves the structure that contains the library's attributes.
3647 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3649 LPTLIBATTR
*ppTLibAttr
)
3651 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3652 TRACE("(%p)\n",This
);
3653 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3654 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3658 /* ITypeLib::GetTypeComp
3660 * Enables a client compiler to bind to a library's types, variables,
3661 * constants, and global functions.
3664 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3666 ITypeComp
**ppTComp
)
3668 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3670 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3671 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3672 ITypeComp_AddRef(*ppTComp
);
3677 /* ITypeLib::GetDocumentation
3679 * Retrieves the library's documentation string, the complete Help file name
3680 * and path, and the context identifier for the library Help topic in the Help
3683 * On a successful return all non-null BSTR pointers will have been set,
3686 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3690 BSTR
*pBstrDocString
,
3691 DWORD
*pdwHelpContext
,
3692 BSTR
*pBstrHelpFile
)
3694 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3696 HRESULT result
= E_INVALIDARG
;
3701 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3703 pBstrName
, pBstrDocString
,
3704 pdwHelpContext
, pBstrHelpFile
);
3708 /* documentation for the typelib */
3712 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3718 if (This
->DocString
)
3719 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3720 else if (This
->Name
)
3721 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3723 *pBstrDocString
= NULL
;
3727 *pdwHelpContext
= This
->dwHelpContext
;
3732 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3734 *pBstrHelpFile
= NULL
;
3741 /* for a typeinfo */
3742 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3744 if(SUCCEEDED(result
))
3746 result
= ITypeInfo_GetDocumentation(pTInfo
,
3750 pdwHelpContext
, pBstrHelpFile
);
3752 ITypeInfo_Release(pTInfo
);
3757 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3759 if (pBstrName
) SysFreeString (*pBstrName
);
3761 return STG_E_INSUFFICIENTMEMORY
;
3766 * Indicates whether a passed-in string contains the name of a type or member
3767 * described in the library.
3770 static HRESULT WINAPI
ITypeLib2_fnIsName(
3776 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3777 ITypeInfoImpl
*pTInfo
;
3778 TLBFuncDesc
*pFInfo
;
3781 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3783 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3787 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3788 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3789 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3790 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3791 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3792 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3793 goto ITypeLib2_fnIsName_exit
;
3795 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3796 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3801 ITypeLib2_fnIsName_exit
:
3802 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3803 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3808 /* ITypeLib::FindName
3810 * Finds occurrences of a type description in a type library. This may be used
3811 * to quickly verify that a name exists in a type library.
3814 static HRESULT WINAPI
ITypeLib2_fnFindName(
3818 ITypeInfo
**ppTInfo
,
3822 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3823 ITypeInfoImpl
*pTInfo
;
3824 TLBFuncDesc
*pFInfo
;
3828 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3830 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3831 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3832 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3833 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3834 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3835 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3836 goto ITypeLib2_fnFindName_exit
;
3838 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3839 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3841 ITypeLib2_fnFindName_exit
:
3842 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3843 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3846 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3847 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3854 /* ITypeLib::ReleaseTLibAttr
3856 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3859 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3861 TLIBATTR
*pTLibAttr
)
3863 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3864 TRACE("freeing (%p)\n",This
);
3865 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3869 /* ITypeLib2::GetCustData
3871 * gets the custom data
3873 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3878 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3879 TLBCustData
*pCData
;
3881 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3883 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3886 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3890 VariantInit( pVarVal
);
3891 VariantCopy( pVarVal
, &pCData
->data
);
3894 return E_INVALIDARG
; /* FIXME: correct? */
3897 /* ITypeLib2::GetLibStatistics
3899 * Returns statistics about a type library that are required for efficient
3900 * sizing of hash tables.
3903 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3905 ULONG
*pcUniqueNames
,
3906 ULONG
*pcchUniqueNames
)
3908 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3910 FIXME("(%p): stub!\n", This
);
3912 if(pcUniqueNames
) *pcUniqueNames
=1;
3913 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3917 /* ITypeLib2::GetDocumentation2
3919 * Retrieves the library's documentation string, the complete Help file name
3920 * and path, the localization context to use, and the context ID for the
3921 * library Help topic in the Help file.
3924 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3928 BSTR
*pbstrHelpString
,
3929 DWORD
*pdwHelpStringContext
,
3930 BSTR
*pbstrHelpStringDll
)
3932 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3936 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3938 /* the help string should be obtained from the helpstringdll,
3939 * using the _DLLGetDocumentation function, based on the supplied
3940 * lcid. Nice to do sometime...
3944 /* documentation for the typelib */
3946 *pbstrHelpString
=SysAllocString(This
->DocString
);
3947 if(pdwHelpStringContext
)
3948 *pdwHelpStringContext
=This
->dwHelpContext
;
3949 if(pbstrHelpStringDll
)
3950 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3956 /* for a typeinfo */
3957 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3959 if(SUCCEEDED(result
))
3961 ITypeInfo2
* pTInfo2
;
3962 result
= ITypeInfo_QueryInterface(pTInfo
,
3964 (LPVOID
*) &pTInfo2
);
3966 if(SUCCEEDED(result
))
3968 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3972 pdwHelpStringContext
,
3973 pbstrHelpStringDll
);
3975 ITypeInfo2_Release(pTInfo2
);
3978 ITypeInfo_Release(pTInfo
);
3984 /* ITypeLib2::GetAllCustData
3986 * Gets all custom data items for the library.
3989 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3991 CUSTDATA
*pCustData
)
3993 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3994 TLBCustData
*pCData
;
3996 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3997 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3998 if(pCustData
->prgCustData
){
3999 pCustData
->cCustData
=This
->ctCustData
;
4000 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4001 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4002 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4005 ERR(" OUT OF MEMORY! \n");
4006 return E_OUTOFMEMORY
;
4011 static const ITypeLib2Vtbl tlbvt
= {
4012 ITypeLib2_fnQueryInterface
,
4014 ITypeLib2_fnRelease
,
4015 ITypeLib2_fnGetTypeInfoCount
,
4016 ITypeLib2_fnGetTypeInfo
,
4017 ITypeLib2_fnGetTypeInfoType
,
4018 ITypeLib2_fnGetTypeInfoOfGuid
,
4019 ITypeLib2_fnGetLibAttr
,
4020 ITypeLib2_fnGetTypeComp
,
4021 ITypeLib2_fnGetDocumentation
,
4023 ITypeLib2_fnFindName
,
4024 ITypeLib2_fnReleaseTLibAttr
,
4026 ITypeLib2_fnGetCustData
,
4027 ITypeLib2_fnGetLibStatistics
,
4028 ITypeLib2_fnGetDocumentation2
,
4029 ITypeLib2_fnGetAllCustData
4033 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4035 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4037 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
4040 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4042 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4044 return ITypeInfo_AddRef((ITypeInfo
*)This
);
4047 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4049 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
4051 return ITypeInfo_Release((ITypeInfo
*)This
);
4054 static HRESULT WINAPI
ITypeLibComp_fnBind(
4059 ITypeInfo
** ppTInfo
,
4060 DESCKIND
* pDescKind
,
4063 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4067 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4071 ITypeInfo
** ppTInfo
,
4072 ITypeComp
** ppTComp
)
4074 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4078 static const ITypeCompVtbl tlbtcvt
=
4081 ITypeLibComp_fnQueryInterface
,
4082 ITypeLibComp_fnAddRef
,
4083 ITypeLibComp_fnRelease
,
4085 ITypeLibComp_fnBind
,
4086 ITypeLibComp_fnBindType
4089 /*================== ITypeInfo(2) Methods ===================================*/
4090 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4092 ITypeInfoImpl
* pTypeInfoImpl
;
4094 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4097 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4098 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4099 pTypeInfoImpl
->ref
=1;
4101 TRACE("(%p)\n", pTypeInfoImpl
);
4102 return (ITypeInfo2
*) pTypeInfoImpl
;
4105 /* ITypeInfo::QueryInterface
4107 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4112 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4114 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4117 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4118 IsEqualIID(riid
,&IID_ITypeInfo
)||
4119 IsEqualIID(riid
,&IID_ITypeInfo2
))
4123 ITypeInfo_AddRef(iface
);
4124 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4127 TRACE("-- Interface: E_NOINTERFACE\n");
4128 return E_NOINTERFACE
;
4131 /* ITypeInfo::AddRef
4133 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4135 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4136 ULONG ref
= InterlockedIncrement(&This
->ref
);
4138 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4140 TRACE("(%p)->ref is %lu\n",This
, ref
);
4144 /* ITypeInfo::Release
4146 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4148 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4149 ULONG ref
= InterlockedDecrement(&This
->ref
);
4151 TRACE("(%p)->(%lu)\n",This
, ref
);
4154 /* We don't release ITypeLib when ref=0 because
4155 it means that function is called by ITypeLib2_Release */
4156 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4158 FIXME("destroy child objects\n");
4160 TRACE("destroying ITypeInfo(%p)\n",This
);
4163 SysFreeString(This
->Name
);
4167 if (This
->DocString
)
4169 SysFreeString(This
->DocString
);
4170 This
->DocString
= 0;
4175 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4178 HeapFree(GetProcessHeap(),0,This
);
4184 /* ITypeInfo::GetTypeAttr
4186 * Retrieves a TYPEATTR structure that contains the attributes of the type
4190 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4191 LPTYPEATTR
*ppTypeAttr
)
4193 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4194 TRACE("(%p)\n",This
);
4195 *ppTypeAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr
));
4196 memcpy(*ppTypeAttr
, &This
->TypeAttr
, sizeof(**ppTypeAttr
));
4198 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
) /* need to deep copy typedesc */
4199 copy_typedesc(&(*ppTypeAttr
)->tdescAlias
, &This
->TypeAttr
.tdescAlias
);
4201 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
&& (*ppTypeAttr
)->wTypeFlags
& TYPEFLAG_FDUAL
) {
4202 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ 4; /* This should include all the inherited
4204 (*ppTypeAttr
)->cbSizeVft
= 28; /* This is always the size of IDispatch's vtbl */
4205 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
4210 /* ITypeInfo::GetTypeComp
4212 * Retrieves the ITypeComp interface for the type description, which enables a
4213 * client compiler to bind to the type description's members.
4216 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4217 ITypeComp
* *ppTComp
)
4219 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4221 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4223 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4224 ITypeComp_AddRef(*ppTComp
);
4228 /* ITypeInfo::GetFuncDesc
4230 * Retrieves the FUNCDESC structure that contains information about a
4231 * specified function.
4234 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4235 LPFUNCDESC
*ppFuncDesc
)
4237 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4239 TLBFuncDesc
* pFDesc
;
4240 TRACE("(%p) index %d\n", This
, index
);
4241 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4244 /* FIXME: must do a copy here */
4245 *ppFuncDesc
=&pFDesc
->funcdesc
;
4248 return E_INVALIDARG
;
4251 /* ITypeInfo::GetVarDesc
4253 * Retrieves a VARDESC structure that describes the specified variable.
4256 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4257 LPVARDESC
*ppVarDesc
)
4259 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4261 TLBVarDesc
* pVDesc
;
4262 TRACE("(%p) index %d\n", This
, index
);
4263 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4266 /* FIXME: must do a copy here */
4267 *ppVarDesc
=&pVDesc
->vardesc
;
4270 return E_INVALIDARG
;
4273 /* ITypeInfo_GetNames
4275 * Retrieves the variable with the specified member ID (or the name of the
4276 * property or method and its parameters) that correspond to the specified
4279 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4280 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4282 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4283 TLBFuncDesc
* pFDesc
;
4284 TLBVarDesc
* pVDesc
;
4286 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4287 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4290 /* function found, now return function and parameter names */
4291 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4294 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4296 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4302 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4305 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4310 if(This
->TypeAttr
.cImplTypes
&&
4311 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4312 /* recursive search */
4315 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4317 if(SUCCEEDED(result
))
4319 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4320 ITypeInfo_Release(pTInfo
);
4323 WARN("Could not search inherited interface!\n");
4327 WARN("no names found\n");
4330 return TYPE_E_ELEMENTNOTFOUND
;
4337 /* ITypeInfo::GetRefTypeOfImplType
4339 * If a type description describes a COM class, it retrieves the type
4340 * description of the implemented interface types. For an interface,
4341 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4345 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4350 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4352 TLBImplType
*pImpl
= This
->impltypelist
;
4354 TRACE("(%p) index %d\n", This
, index
);
4355 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4359 /* only valid on dual interfaces;
4360 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4362 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4364 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4365 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4371 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4372 *pRefType
= pImpl
->hRef
;
4377 /* get element n from linked list */
4378 for(i
=0; pImpl
&& i
<index
; i
++)
4380 pImpl
= pImpl
->next
;
4383 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4385 *pRefType
= pImpl
->hRef
;
4387 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4394 /* ITypeInfo::GetImplTypeFlags
4396 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4397 * or base interface in a type description.
4399 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4400 UINT index
, INT
*pImplTypeFlags
)
4402 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4406 TRACE("(%p) index %d\n", This
, index
);
4407 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4408 i
++, pImpl
=pImpl
->next
)
4410 if(i
==index
&& pImpl
){
4411 *pImplTypeFlags
=pImpl
->implflags
;
4415 return TYPE_E_ELEMENTNOTFOUND
;
4419 * Maps between member names and member IDs, and parameter names and
4422 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4423 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4425 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4426 TLBFuncDesc
* pFDesc
;
4427 TLBVarDesc
* pVDesc
;
4430 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4432 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4434 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4435 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4436 for(i
=1; i
< cNames
; i
++){
4437 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4438 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4440 if( j
<pFDesc
->funcdesc
.cParams
)
4443 ret
=DISP_E_UNKNOWNNAME
;
4448 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4449 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4450 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4454 /* not found, see if this is and interface with an inheritance */
4455 if(This
->TypeAttr
.cImplTypes
&&
4456 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4457 /* recursive search */
4459 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4460 This
->impltypelist
->hRef
, &pTInfo
);
4462 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4463 ITypeInfo_Release(pTInfo
);
4466 WARN("Could not search inherited interface!\n");
4468 WARN("no names found\n");
4469 return DISP_E_UNKNOWNNAME
;
4472 /* ITypeInfo::Invoke
4474 * Invokes a method, or accesses a property of an object, that implements the
4475 * interface described by the type description.
4478 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4481 if (TRACE_ON(ole
)) {
4483 TRACE("Calling %p(",func
);
4484 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4496 res
= func(args
[0]);
4499 res
= func(args
[0],args
[1]);
4502 res
= func(args
[0],args
[1],args
[2]);
4505 res
= func(args
[0],args
[1],args
[2],args
[3]);
4508 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4511 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4514 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4517 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4520 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4523 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
4526 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
4529 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4535 FIXME("unsupported calling convention %d\n",callconv
);
4539 TRACE("returns %08lx\n",res
);
4543 extern int _argsize(DWORD vt
);
4545 /****************************************************************************
4546 * Helper functions for Dispcall / Invoke, which copies one variant
4547 * with target type onto the argument stack.
4550 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4551 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4553 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4556 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4557 memcpy(argpos
,&arg
,sizeof(void*));
4561 if (V_VT(arg
) == vt
) {
4562 memcpy(argpos
, &V_I4(arg
), arglen
);
4566 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4567 memcpy(argpos
, &V_ARRAY(arg
), sizeof(SAFEARRAY
*));
4571 if (vt
== VT_VARIANT
) {
4572 memcpy(argpos
, arg
, arglen
);
4575 /* Deref BYREF vars if there is need */
4576 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4577 memcpy(argpos
,(void*)V_I4(arg
), arglen
);
4580 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4581 /* in this context, if the type lib specifies IUnknown*, giving an
4582 IDispatch* is correct; so, don't invoke VariantChangeType */
4583 memcpy(argpos
,&V_I4(arg
), arglen
);
4586 if ((vt
== VT_PTR
) && tdesc
)
4587 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4589 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4590 ITypeInfo
*tinfo2
= NULL
;
4591 TYPEATTR
*tattr
= NULL
;
4594 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4596 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4597 "while coercing from vt 0x%x. Copying 4 byte.\n",
4598 tdesc
->u
.hreftype
,V_VT(arg
));
4599 memcpy(argpos
, &V_I4(arg
), 4);
4602 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4605 ERR("GetTypeAttr failed\n");
4606 ITypeInfo_Release(tinfo2
);
4609 switch (tattr
->typekind
) {
4611 switch ( V_VT( arg
) ) {
4613 *argpos
= V_I2(arg
);
4617 memcpy(argpos
, &V_I4(arg
), 4);
4621 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4628 tdesc
= &(tattr
->tdescAlias
);
4629 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4632 case TKIND_INTERFACE
:
4633 if (V_VT(arg
) == VT_DISPATCH
) {
4635 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4636 memcpy(argpos
, &V_DISPATCH(arg
), 4);
4640 hres
=IUnknown_QueryInterface(V_DISPATCH(arg
),
4641 &IID_IDispatch
,(LPVOID
*)&disp
);
4642 if (SUCCEEDED(hres
)) {
4643 memcpy(argpos
,&disp
,4);
4644 IUnknown_Release(V_DISPATCH(arg
));
4648 FIXME("Failed to query IDispatch interface from %s while "
4649 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4653 if (V_VT(arg
) == VT_UNKNOWN
) {
4654 memcpy(argpos
, &V_UNKNOWN(arg
), 4);
4658 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4659 V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4663 case TKIND_DISPATCH
:
4664 if (V_VT(arg
) == VT_DISPATCH
) {
4665 memcpy(argpos
, &V_DISPATCH(arg
), 4);
4670 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4674 FIXME("TKIND_RECORD unhandled.\n");
4678 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4682 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4683 ITypeInfo_Release(tinfo2
);
4688 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4689 memcpy(argpos
,&V_I4(&va
), arglen
);
4690 FIXME("Should not use VariantChangeType here."
4691 " (conversion from 0x%x -> 0x%x) %08lx\n",
4692 V_VT(arg
), vt
, *argpos
4696 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4700 /***********************************************************************
4701 * DispCallFunc (OLEAUT32.@)
4705 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4706 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4708 int i
, argsize
, argspos
;
4712 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4713 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4715 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4716 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4718 for (i
=0;i
<cActuals
;i
++) {
4719 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4720 dump_Variant(prgpvarg
[i
]);
4721 argsize
+= _argsize(prgvt
[i
]);
4723 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4724 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4726 for (i
=0;i
<cActuals
;i
++) {
4727 VARIANT
*arg
= prgpvarg
[i
];
4728 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4729 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4730 argspos
+= _argsize(prgvt
[i
]);
4733 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4735 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4740 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4741 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4742 FIXME("Method returned %lx\n",hres
);
4744 HeapFree(GetProcessHeap(),0,args
);
4748 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4753 DISPPARAMS
*pDispParams
,
4754 VARIANT
*pVarResult
,
4755 EXCEPINFO
*pExcepInfo
,
4758 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4760 unsigned int func_index
, var_index
;
4764 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4765 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4767 dump_DispParms(pDispParams
);
4769 hres
= ITypeInfo2_GetFuncIndexOfMemId(iface
, memid
, dwFlags
, &func_index
);
4770 if (SUCCEEDED(hres
)) {
4771 FUNCDESC
*func_desc
;
4773 hres
= ITypeInfo2_GetFuncDesc(iface
, func_index
, &func_desc
);
4774 if(FAILED(hres
)) return hres
;
4776 switch (func_desc
->funckind
) {
4777 case FUNC_PUREVIRTUAL
:
4778 case FUNC_VIRTUAL
: {
4780 int numargs
, numargs2
, argspos
, args2pos
;
4781 DWORD
*args
, *args2
;
4782 VARIANT
*rgvarg
= HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT
) * func_desc
->cParams
);
4783 memcpy(rgvarg
,pDispParams
->rgvarg
,sizeof(VARIANT
)*pDispParams
->cArgs
);
4786 numargs
= 1; numargs2
= 0;
4787 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4788 if (i
<pDispParams
->cArgs
)
4789 numargs
+= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4791 numargs
+= 1; /* sizeof(lpvoid) */
4792 numargs2
+= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4796 args
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4797 args2
= HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4799 args
[0] = (DWORD
)pIUnk
;
4800 argspos
= 1; args2pos
= 0;
4801 for (i
= 0; i
< func_desc
->cParams
; i
++) {
4802 int arglen
= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4803 if (i
<pDispParams
->cArgs
) {
4804 VARIANT
*arg
= &rgvarg
[pDispParams
->cArgs
-i
-1];
4805 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4806 USHORT paramFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
4807 if (paramFlags
& PARAMFLAG_FOPT
) {
4808 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4809 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4810 if(V_VT(arg
) == VT_EMPTY
4811 || ((V_ISBYREF(arg
)) && !V_BYREF(arg
))) {
4812 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4813 How to determine it? */
4815 if(paramFlags
& PARAMFLAG_FHASDEFAULT
)
4816 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4817 V_VT(arg
) = VT_ERROR
;
4818 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4819 arglen
= _argsize(VT_ERROR
);
4822 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4823 if (FAILED(hres
)) goto func_fail
;
4825 } else if(func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FOPT
) {
4826 VARIANT
*arg
= &rgvarg
[i
];
4827 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
4828 if(i
< func_desc
->cParams
- func_desc
->cParamsOpt
)
4829 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4830 if(func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4831 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4832 V_VT(arg
) = VT_ERROR
;
4833 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4834 arglen
= _argsize(VT_ERROR
);
4835 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4836 if (FAILED(hres
)) goto func_fail
;
4839 TYPEDESC
*tdesc
= &(func_desc
->lprgelemdescParam
[i
].tdesc
);
4840 if (tdesc
->vt
!= VT_PTR
)
4841 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4842 /*FIXME: give pointers for the rest, so propertyget works*/
4843 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4845 /* If pointer to variant, pass reference it. */
4846 if ((tdesc
->vt
== VT_PTR
) &&
4847 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4850 args
[argspos
]= (DWORD
)pVarResult
;
4855 if (func_desc
->cParamsOpt
< 0)
4856 FIXME("Does not support optional parameters (%d)\n", func_desc
->cParamsOpt
);
4858 res
= _invoke((*(FARPROC
**)pIUnk
)[func_desc
->oVft
/4],
4859 func_desc
->callconv
,
4864 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4866 for (i
= 0; i
< func_desc
->cParams
- pDispParams
->cArgs
; i
++) {
4867 int arglen
= _argsize(func_desc
->lprgelemdescParam
[i
].tdesc
.vt
);
4868 TYPEDESC
*tdesc
= &(func_desc
->lprgelemdescParam
[i
+ pDispParams
->cArgs
].tdesc
);
4870 i4_tdesc
.vt
= VT_I4
;
4872 /* If we are a pointer to a variant, we are done already */
4873 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4876 VariantInit(pVarResult
);
4877 memcpy(&V_INT(pVarResult
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4879 if (tdesc
->vt
== VT_PTR
)
4880 tdesc
= tdesc
->u
.lptdesc
;
4881 if (tdesc
->vt
== VT_USERDEFINED
) {
4885 hres
= ITypeInfo_GetRefTypeInfo(iface
,tdesc
->u
.hreftype
,&tinfo2
);
4887 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc
->u
.hreftype
);
4890 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4891 switch (tattr
->typekind
) {
4893 /* force the return type to be VT_I4 */
4897 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr
->tdescAlias
.vt
);
4898 tdesc
= &(tattr
->tdescAlias
);
4901 case TKIND_INTERFACE
:
4902 FIXME("TKIND_INTERFACE unhandled.\n");
4904 case TKIND_DISPATCH
:
4905 FIXME("TKIND_DISPATCH unhandled.\n");
4908 FIXME("TKIND_RECORD unhandled.\n");
4911 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4914 ITypeInfo_Release(tinfo2
);
4916 V_VT(pVarResult
) = tdesc
->vt
;
4918 /* HACK: VB5 likes this.
4919 * I do not know why. There is 1 example in MSDN which uses
4920 * this which appears broken (mixes int vals and
4923 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4924 V_VT(pVarResult
) = VT_DISPATCH
;
4925 TRACE("storing into variant:\n");
4926 dump_Variant(pVarResult
);
4931 HeapFree(GetProcessHeap(), 0, rgvarg
);
4932 HeapFree(GetProcessHeap(),0,args2
);
4933 HeapFree(GetProcessHeap(),0,args
);
4936 case FUNC_DISPATCH
: {
4939 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4940 if (SUCCEEDED(hres
)) {
4941 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4942 hres
= IDispatch_Invoke(
4943 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4944 pVarResult
,pExcepInfo
,pArgErr
4947 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres
);
4948 IDispatch_Release(disp
);
4950 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4954 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
4959 ITypeInfo2_ReleaseFuncDesc(iface
, func_desc
);
4962 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
4965 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
4966 if(FAILED(hres
)) return hres
;
4968 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4969 dump_VARDESC(var_desc
);
4970 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
4974 /* not found, look for it in inherited interfaces */
4975 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
4976 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
4978 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface
, 0, &ref_type
))) {
4979 /* recursive search */
4981 hres
= ITypeInfo_GetRefTypeInfo(iface
, ref_type
, &pTInfo
);
4982 if(SUCCEEDED(hres
)){
4983 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4984 ITypeInfo_Release(pTInfo
);
4987 WARN("Could not search inherited interface!\n");
4990 ERR("did not find member id %08lx, flags %d!\n", memid
, dwFlags
);
4991 return DISP_E_MEMBERNOTFOUND
;
4994 /* ITypeInfo::GetDocumentation
4996 * Retrieves the documentation string, the complete Help file name and path,
4997 * and the context ID for the Help topic for a specified type description.
4999 * (Can be tested by the Visual Basic Editor in Word for instance.)
5001 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
5002 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
5003 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
5005 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5006 TLBFuncDesc
* pFDesc
;
5007 TLBVarDesc
* pVDesc
;
5008 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5009 " HelpContext(%p) HelpFile(%p)\n",
5010 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
5011 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5013 *pBstrName
=SysAllocString(This
->Name
);
5015 *pBstrDocString
=SysAllocString(This
->DocString
);
5017 *pdwHelpContext
=This
->dwHelpContext
;
5019 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
5021 }else {/* for a member */
5022 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5023 if(pFDesc
->funcdesc
.memid
==memid
){
5025 *pBstrName
= SysAllocString(pFDesc
->Name
);
5027 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
5029 *pdwHelpContext
=pFDesc
->helpcontext
;
5032 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5033 if(pVDesc
->vardesc
.memid
==memid
){
5035 *pBstrName
= SysAllocString(pVDesc
->Name
);
5037 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
5039 *pdwHelpContext
=pVDesc
->HelpContext
;
5043 return TYPE_E_ELEMENTNOTFOUND
;
5046 /* ITypeInfo::GetDllEntry
5048 * Retrieves a description or specification of an entry point for a function
5051 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
5052 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
5055 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5056 TLBFuncDesc
*pFDesc
;
5058 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
5060 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5061 if(pFDesc
->funcdesc
.memid
==memid
){
5062 dump_TypeInfo(This
);
5063 dump_TLBFuncDescOne(pFDesc
);
5065 /* FIXME: This is wrong, but how do you find that out? */
5067 static const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5068 *pBstrDllName
= SysAllocString(oleaut32W
);
5071 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
5073 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5081 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5087 /* ITypeInfo::GetRefTypeInfo
5089 * If a type description references other type descriptions, it retrieves
5090 * the referenced type descriptions.
5092 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5095 ITypeInfo
**ppTInfo
)
5097 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5098 HRESULT result
= E_FAIL
;
5100 if (hRefType
== -1 &&
5101 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5102 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5104 /* when we meet a DUAL dispinterface, we must create the interface
5107 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5110 /* the interface version contains the same information as the dispinterface
5111 * copy the contents of the structs.
5113 *pTypeInfoImpl
= *This
;
5114 pTypeInfoImpl
->ref
= 1;
5116 /* change the type to interface */
5117 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5119 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5121 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
5126 TLBRefType
*pRefType
;
5127 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5128 if(pRefType
->reference
== hRefType
)
5132 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
5133 if(pRefType
&& hRefType
!= -1) {
5134 ITypeLib
*pTLib
= NULL
;
5136 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5138 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5140 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5141 TRACE("typeinfo in imported typelib that is already loaded\n");
5142 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5143 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5146 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5147 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5148 pRefType
->pImpTLInfo
->wVersionMajor
,
5149 pRefType
->pImpTLInfo
->wVersionMinor
,
5150 pRefType
->pImpTLInfo
->lcid
,
5153 if(!SUCCEEDED(result
)) {
5154 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5155 result
=LoadTypeLib(libnam
, &pTLib
);
5156 SysFreeString(libnam
);
5158 if(SUCCEEDED(result
)) {
5159 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5160 ITypeLib2_AddRef(pTLib
);
5164 if(SUCCEEDED(result
)) {
5165 if(pRefType
->index
== TLB_REF_USE_GUID
)
5166 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5170 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5174 ITypeLib2_Release(pTLib
);
5178 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
5179 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5183 /* ITypeInfo::AddressOfMember
5185 * Retrieves the addresses of static functions or variables, such as those
5188 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5189 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5191 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5192 FIXME("(%p) stub!\n", This
);
5196 /* ITypeInfo::CreateInstance
5198 * Creates a new instance of a type that describes a component object class
5201 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
5202 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
5204 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5205 FIXME("(%p) stub!\n", This
);
5209 /* ITypeInfo::GetMops
5211 * Retrieves marshalling information.
5213 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
5216 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5217 FIXME("(%p) stub!\n", This
);
5221 /* ITypeInfo::GetContainingTypeLib
5223 * Retrieves the containing type library and the index of the type description
5224 * within that type library.
5226 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
5227 ITypeLib
* *ppTLib
, UINT
*pIndex
)
5229 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5231 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5233 *pIndex
=This
->index
;
5234 TRACE("returning pIndex=%d\n", *pIndex
);
5238 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
5239 ITypeLib2_AddRef(*ppTLib
);
5240 TRACE("returning ppTLib=%p\n", *ppTLib
);
5246 /* ITypeInfo::ReleaseTypeAttr
5248 * Releases a TYPEATTR previously returned by GetTypeAttr.
5251 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
5252 TYPEATTR
* pTypeAttr
)
5254 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5255 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
5256 if(This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5257 free_deep_typedesc(&pTypeAttr
->tdescAlias
);
5258 HeapFree(GetProcessHeap(), 0, pTypeAttr
);
5261 /* ITypeInfo::ReleaseFuncDesc
5263 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5265 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
5267 FUNCDESC
*pFuncDesc
)
5269 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5270 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
5273 /* ITypeInfo::ReleaseVarDesc
5275 * Releases a VARDESC previously returned by GetVarDesc.
5277 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5280 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5281 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5284 /* ITypeInfo2::GetTypeKind
5286 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5289 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5290 TYPEKIND
*pTypeKind
)
5292 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5293 *pTypeKind
=This
->TypeAttr
.typekind
;
5294 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5298 /* ITypeInfo2::GetTypeFlags
5300 * Returns the type flags without any allocations. This returns a DWORD type
5301 * flag, which expands the type flags without growing the TYPEATTR (type
5305 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5307 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5308 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5309 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5313 /* ITypeInfo2::GetFuncIndexOfMemId
5314 * Binds to a specific member based on a known DISPID, where the member name
5315 * is not known (for example, when binding to a default member).
5318 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5319 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5321 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5322 TLBFuncDesc
*pFuncInfo
;
5326 for(i
= 0, pFuncInfo
= This
->funclist
; pFuncInfo
; i
++, pFuncInfo
=pFuncInfo
->next
)
5327 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
5333 result
= TYPE_E_ELEMENTNOTFOUND
;
5335 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5336 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5340 /* TypeInfo2::GetVarIndexOfMemId
5342 * Binds to a specific member based on a known DISPID, where the member name
5343 * is not known (for example, when binding to a default member).
5346 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5347 MEMBERID memid
, UINT
*pVarIndex
)
5349 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5350 TLBVarDesc
*pVarInfo
;
5353 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5354 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5360 result
= TYPE_E_ELEMENTNOTFOUND
;
5362 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5363 memid
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
5367 /* ITypeInfo2::GetCustData
5369 * Gets the custom data
5371 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5376 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5377 TLBCustData
*pCData
;
5379 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5380 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5382 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5386 VariantInit( pVarVal
);
5387 VariantCopy( pVarVal
, &pCData
->data
);
5390 return E_INVALIDARG
; /* FIXME: correct? */
5393 /* ITypeInfo2::GetFuncCustData
5395 * Gets the custom data
5397 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5403 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5404 TLBCustData
*pCData
=NULL
;
5405 TLBFuncDesc
* pFDesc
;
5407 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5408 pFDesc
=pFDesc
->next
);
5411 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5412 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5414 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5417 VariantInit( pVarVal
);
5418 VariantCopy( pVarVal
, &pCData
->data
);
5421 return E_INVALIDARG
; /* FIXME: correct? */
5424 /* ITypeInfo2::GetParamCustData
5426 * Gets the custom data
5428 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5435 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5436 TLBCustData
*pCData
=NULL
;
5437 TLBFuncDesc
* pFDesc
;
5440 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5442 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5443 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5444 pCData
= pCData
->next
)
5445 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5447 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5451 VariantInit( pVarVal
);
5452 VariantCopy( pVarVal
, &pCData
->data
);
5455 return E_INVALIDARG
; /* FIXME: correct? */
5458 /* ITypeInfo2::GetVarCustData
5460 * Gets the custom data
5462 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5468 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5469 TLBCustData
*pCData
=NULL
;
5470 TLBVarDesc
* pVDesc
;
5473 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5477 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5479 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5483 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5487 VariantInit( pVarVal
);
5488 VariantCopy( pVarVal
, &pCData
->data
);
5491 return E_INVALIDARG
; /* FIXME: correct? */
5494 /* ITypeInfo2::GetImplCustData
5496 * Gets the custom data
5498 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5504 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5505 TLBCustData
*pCData
=NULL
;
5506 TLBImplType
* pRDesc
;
5509 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5513 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5515 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5519 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5523 VariantInit( pVarVal
);
5524 VariantCopy( pVarVal
, &pCData
->data
);
5527 return E_INVALIDARG
; /* FIXME: correct? */
5530 /* ITypeInfo2::GetDocumentation2
5532 * Retrieves the documentation string, the complete Help file name and path,
5533 * the localization context to use, and the context ID for the library Help
5534 * topic in the Help file.
5537 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5541 BSTR
*pbstrHelpString
,
5542 DWORD
*pdwHelpStringContext
,
5543 BSTR
*pbstrHelpStringDll
)
5545 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5546 TLBFuncDesc
* pFDesc
;
5547 TLBVarDesc
* pVDesc
;
5548 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5549 "HelpStringContext(%p) HelpStringDll(%p)\n",
5550 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5551 pbstrHelpStringDll
);
5552 /* the help string should be obtained from the helpstringdll,
5553 * using the _DLLGetDocumentation function, based on the supplied
5554 * lcid. Nice to do sometime...
5556 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5558 *pbstrHelpString
=SysAllocString(This
->Name
);
5559 if(pdwHelpStringContext
)
5560 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5561 if(pbstrHelpStringDll
)
5562 *pbstrHelpStringDll
=
5563 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5565 }else {/* for a member */
5566 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5567 if(pFDesc
->funcdesc
.memid
==memid
){
5569 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5570 if(pdwHelpStringContext
)
5571 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5572 if(pbstrHelpStringDll
)
5573 *pbstrHelpStringDll
=
5574 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5577 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5578 if(pVDesc
->vardesc
.memid
==memid
){
5580 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5581 if(pdwHelpStringContext
)
5582 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5583 if(pbstrHelpStringDll
)
5584 *pbstrHelpStringDll
=
5585 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5589 return TYPE_E_ELEMENTNOTFOUND
;
5592 /* ITypeInfo2::GetAllCustData
5594 * Gets all custom data items for the Type info.
5597 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5599 CUSTDATA
*pCustData
)
5601 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5602 TLBCustData
*pCData
;
5605 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5607 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5608 if(pCustData
->prgCustData
){
5609 pCustData
->cCustData
=This
->ctCustData
;
5610 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5611 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5612 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5615 ERR(" OUT OF MEMORY! \n");
5616 return E_OUTOFMEMORY
;
5621 /* ITypeInfo2::GetAllFuncCustData
5623 * Gets all custom data items for the specified Function
5626 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5629 CUSTDATA
*pCustData
)
5631 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5632 TLBCustData
*pCData
;
5633 TLBFuncDesc
* pFDesc
;
5635 TRACE("(%p) index %d\n", This
, index
);
5636 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5637 pFDesc
=pFDesc
->next
)
5640 pCustData
->prgCustData
=
5641 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5642 if(pCustData
->prgCustData
){
5643 pCustData
->cCustData
=pFDesc
->ctCustData
;
5644 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5645 pCData
= pCData
->next
){
5646 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5647 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5651 ERR(" OUT OF MEMORY! \n");
5652 return E_OUTOFMEMORY
;
5656 return TYPE_E_ELEMENTNOTFOUND
;
5659 /* ITypeInfo2::GetAllParamCustData
5661 * Gets all custom data items for the Functions
5664 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5665 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5667 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5668 TLBCustData
*pCData
=NULL
;
5669 TLBFuncDesc
* pFDesc
;
5671 TRACE("(%p) index %d\n", This
, indexFunc
);
5672 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5673 pFDesc
=pFDesc
->next
)
5675 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5676 pCustData
->prgCustData
=
5677 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5678 sizeof(CUSTDATAITEM
));
5679 if(pCustData
->prgCustData
){
5680 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5681 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5682 pCData
; i
++, pCData
= pCData
->next
){
5683 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5684 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5688 ERR(" OUT OF MEMORY! \n");
5689 return E_OUTOFMEMORY
;
5693 return TYPE_E_ELEMENTNOTFOUND
;
5696 /* ITypeInfo2::GetAllVarCustData
5698 * Gets all custom data items for the specified Variable
5701 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5702 UINT index
, CUSTDATA
*pCustData
)
5704 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5705 TLBCustData
*pCData
;
5706 TLBVarDesc
* pVDesc
;
5708 TRACE("(%p) index %d\n", This
, index
);
5709 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5710 pVDesc
=pVDesc
->next
)
5713 pCustData
->prgCustData
=
5714 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5715 if(pCustData
->prgCustData
){
5716 pCustData
->cCustData
=pVDesc
->ctCustData
;
5717 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5718 pCData
= pCData
->next
){
5719 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5720 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5724 ERR(" OUT OF MEMORY! \n");
5725 return E_OUTOFMEMORY
;
5729 return TYPE_E_ELEMENTNOTFOUND
;
5732 /* ITypeInfo2::GetAllImplCustData
5734 * Gets all custom data items for the specified implementation type
5737 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5740 CUSTDATA
*pCustData
)
5742 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5743 TLBCustData
*pCData
;
5744 TLBImplType
* pRDesc
;
5746 TRACE("(%p) index %d\n", This
, index
);
5747 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5748 pRDesc
=pRDesc
->next
)
5751 pCustData
->prgCustData
=
5752 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5753 if(pCustData
->prgCustData
){
5754 pCustData
->cCustData
=pRDesc
->ctCustData
;
5755 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5756 pCData
= pCData
->next
){
5757 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5758 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5762 ERR(" OUT OF MEMORY! \n");
5763 return E_OUTOFMEMORY
;
5767 return TYPE_E_ELEMENTNOTFOUND
;
5770 static const ITypeInfo2Vtbl tinfvt
=
5773 ITypeInfo_fnQueryInterface
,
5775 ITypeInfo_fnRelease
,
5777 ITypeInfo_fnGetTypeAttr
,
5778 ITypeInfo_fnGetTypeComp
,
5779 ITypeInfo_fnGetFuncDesc
,
5780 ITypeInfo_fnGetVarDesc
,
5781 ITypeInfo_fnGetNames
,
5782 ITypeInfo_fnGetRefTypeOfImplType
,
5783 ITypeInfo_fnGetImplTypeFlags
,
5784 ITypeInfo_fnGetIDsOfNames
,
5786 ITypeInfo_fnGetDocumentation
,
5787 ITypeInfo_fnGetDllEntry
,
5788 ITypeInfo_fnGetRefTypeInfo
,
5789 ITypeInfo_fnAddressOfMember
,
5790 ITypeInfo_fnCreateInstance
,
5791 ITypeInfo_fnGetMops
,
5792 ITypeInfo_fnGetContainingTypeLib
,
5793 ITypeInfo_fnReleaseTypeAttr
,
5794 ITypeInfo_fnReleaseFuncDesc
,
5795 ITypeInfo_fnReleaseVarDesc
,
5797 ITypeInfo2_fnGetTypeKind
,
5798 ITypeInfo2_fnGetTypeFlags
,
5799 ITypeInfo2_fnGetFuncIndexOfMemId
,
5800 ITypeInfo2_fnGetVarIndexOfMemId
,
5801 ITypeInfo2_fnGetCustData
,
5802 ITypeInfo2_fnGetFuncCustData
,
5803 ITypeInfo2_fnGetParamCustData
,
5804 ITypeInfo2_fnGetVarCustData
,
5805 ITypeInfo2_fnGetImplTypeCustData
,
5806 ITypeInfo2_fnGetDocumentation2
,
5807 ITypeInfo2_fnGetAllCustData
,
5808 ITypeInfo2_fnGetAllFuncCustData
,
5809 ITypeInfo2_fnGetAllParamCustData
,
5810 ITypeInfo2_fnGetAllVarCustData
,
5811 ITypeInfo2_fnGetAllImplTypeCustData
,
5814 /******************************************************************************
5815 * CreateDispTypeInfo [OLEAUT32.31]
5817 * Build type information for an object so it can be called through an
5818 * IDispatch interface.
5821 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5822 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5825 * This call allows an objects methods to be accessed through IDispatch, by
5826 * building an ITypeInfo object that IDispatch can use to call through.
5828 HRESULT WINAPI
CreateDispTypeInfo(
5829 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
5830 LCID lcid
, /* [I] Locale Id */
5831 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
5833 ITypeInfoImpl
*pTIImpl
;
5835 TLBFuncDesc
**ppFuncDesc
;
5837 pTIImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
5838 pTIImpl
->pTypeLib
= NULL
;
5840 pTIImpl
->Name
= NULL
;
5841 pTIImpl
->dwHelpContext
= -1;
5842 memset(&pTIImpl
->TypeAttr
.guid
, 0, sizeof(GUID
));
5843 pTIImpl
->TypeAttr
.lcid
= lcid
;
5844 pTIImpl
->TypeAttr
.typekind
= TKIND_COCLASS
;
5845 pTIImpl
->TypeAttr
.wMajorVerNum
= 0;
5846 pTIImpl
->TypeAttr
.wMinorVerNum
= 0;
5847 pTIImpl
->TypeAttr
.cbAlignment
= 2;
5848 pTIImpl
->TypeAttr
.cbSizeInstance
= -1;
5849 pTIImpl
->TypeAttr
.cbSizeVft
= -1;
5850 pTIImpl
->TypeAttr
.cFuncs
= 0;
5851 pTIImpl
->TypeAttr
.cImplTypes
= 1;
5852 pTIImpl
->TypeAttr
.cVars
= 0;
5853 pTIImpl
->TypeAttr
.wTypeFlags
= 0;
5855 ppFuncDesc
= &pTIImpl
->funclist
;
5856 for(func
= 0; func
< pidata
->cMembers
; func
++) {
5857 METHODDATA
*md
= pidata
->pmethdata
+ func
;
5858 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
5859 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
5860 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
5861 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
5862 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
5863 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
5864 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
5865 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
;
5866 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0; /*??*/
5867 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
5868 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5869 md
->cArgs
* sizeof(ELEMDESC
));
5870 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5871 md
->cArgs
* sizeof(TLBParDesc
));
5872 for(param
= 0; param
< md
->cArgs
; param
++) {
5873 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
5874 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
5876 ppFuncDesc
= &(*ppFuncDesc
)->next
;
5878 *pptinfo
= (ITypeInfo
*)pTIImpl
;
5883 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5885 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5887 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
5890 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
5892 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5894 return ITypeInfo_AddRef((ITypeInfo
*)This
);
5897 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
5899 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5901 return ITypeInfo_Release((ITypeInfo
*)This
);
5904 static HRESULT WINAPI
ITypeComp_fnBind(
5909 ITypeInfo
** ppTInfo
,
5910 DESCKIND
* pDescKind
,
5913 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5914 TLBFuncDesc
* pFDesc
;
5915 TLBVarDesc
* pVDesc
;
5917 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5919 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
5920 if (pFDesc
->funcdesc
.invkind
& wFlags
)
5921 if (!strcmpW(pFDesc
->Name
, szName
)) {
5927 *pDescKind
= DESCKIND_FUNCDESC
;
5928 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
5929 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5932 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
5934 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
5935 if (!strcmpW(pVDesc
->Name
, szName
)) {
5936 *pDescKind
= DESCKIND_VARDESC
;
5937 pBindPtr
->lpvardesc
= &pVDesc
->vardesc
;
5938 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5944 /* not found, look for it in inherited interfaces */
5945 if (This
->TypeAttr
.cImplTypes
&&
5946 (This
->TypeAttr
.typekind
== TKIND_INTERFACE
|| This
->TypeAttr
.typekind
== TKIND_DISPATCH
)) {
5947 /* recursive search */
5951 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
5954 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
5955 ITypeInfo_Release(pTInfo
);
5959 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5960 ITypeComp_Release(pTComp
);
5963 WARN("Could not search inherited interface!\n");
5965 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
5966 *pDescKind
= DESCKIND_NONE
;
5967 pBindPtr
->lpfuncdesc
= NULL
;
5969 return DISP_E_MEMBERNOTFOUND
;
5972 static HRESULT WINAPI
ITypeComp_fnBindType(
5976 ITypeInfo
** ppTInfo
,
5977 ITypeComp
** ppTComp
)
5979 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5981 /* strange behaviour (does nothing) but like the
5984 if (!ppTInfo
|| !ppTComp
)
5993 static const ITypeCompVtbl tcompvt
=
5996 ITypeComp_fnQueryInterface
,
5998 ITypeComp_fnRelease
,
6001 ITypeComp_fnBindType