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"
79 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
85 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
86 const GUID CLSID_PSOAInterface
= { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
88 /****************************************************************************
91 * Takes p_iVal (which is in little endian) and returns it
92 * in the host machine's byte order.
94 #ifdef WORDS_BIGENDIAN
95 static WORD
FromLEWord(WORD p_iVal
)
97 return (((p_iVal
& 0x00FF) << 8) |
98 ((p_iVal
& 0xFF00) >> 8));
102 static DWORD
FromLEDWord(DWORD p_iVal
)
104 return (((p_iVal
& 0x000000FF) << 24) |
105 ((p_iVal
& 0x0000FF00) << 8) |
106 ((p_iVal
& 0x00FF0000) >> 8) |
107 ((p_iVal
& 0xFF000000) >> 24));
110 #define FromLEWord(X) (X)
111 #define FromLEDWord(X) (X)
115 /****************************************************************************
118 * Fix byte order in any structure if necessary
120 #ifdef WORDS_BIGENDIAN
121 static void FromLEWords(void *p_Val
, int p_iSize
)
125 p_iSize
/= sizeof(WORD
);
128 *Val
= FromLEWord(*Val
);
135 static void FromLEDWords(void *p_Val
, int p_iSize
)
139 p_iSize
/= sizeof(DWORD
);
142 *Val
= FromLEDWord(*Val
);
148 #define FromLEWords(X,Y) /*nothing*/
149 #define FromLEDWords(X,Y) /*nothing*/
152 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
153 /* buffer must be at least 60 characters long */
154 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
156 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
157 static const WCHAR VersionFormatW
[] = {'\\','%','u','.','%','u',0};
159 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
160 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
161 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
165 /* get the path of an interface key, in the form "Interface\\<guid>" */
166 /* buffer must be at least 50 characters long */
167 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
169 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
171 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
172 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
176 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
177 /* buffer must be at least 16 characters long */
178 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
180 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
181 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
182 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
184 sprintfW( buffer
, LcidFormatW
, lcid
);
187 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
188 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
190 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
197 /****************************************************************************
198 * QueryPathOfRegTypeLib [OLEAUT32.164]
203 QueryPathOfRegTypeLib(
204 REFGUID guid
, /* [in] referenced guid */
205 WORD wMaj
, /* [in] major version */
206 WORD wMin
, /* [in] minor version */
207 LCID lcid
, /* [in] locale id */
208 LPBSTR path
) /* [out] path of typelib */
214 WCHAR Path
[MAX_PATH
];
218 FIXME("(guid %p,%d,%d,0x%04lx,%p),stub!\n", guid
, wMaj
, wMin
, lcid
, path
);
222 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
224 if (RegOpenKeyW( HKEY_CLASSES_ROOT
, buffer
, &hkey
) != ERROR_SUCCESS
)
226 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
232 DWORD dwPathLen
= sizeof(Path
);
234 get_lcid_subkey( myLCID
, SYS_WIN32
, buffer
);
236 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
240 else if (myLCID
== lcid
)
242 /* try with sub-langid */
243 myLCID
= SUBLANGID(lcid
);
245 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
247 /* try with system langid */
257 *path
= SysAllocString( Path
);
265 /******************************************************************************
266 * CreateTypeLib [OLEAUT32.160] creates a typelib
272 HRESULT WINAPI
CreateTypeLib(
273 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
275 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
278 /******************************************************************************
279 * LoadTypeLib [OLEAUT32.161]
280 * Loads and registers a type library
282 * Docs: OLECHAR FAR* szFile
283 * Docs: iTypeLib FAR* FAR* pptLib
289 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
291 HRESULT WINAPI
LoadTypeLib(
292 const OLECHAR
*szFile
,/* [in] Name of file to load from */
293 ITypeLib
* *pptLib
) /* [out] Pointer to pointer to loaded type library */
296 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
299 /******************************************************************************
300 * LoadTypeLibEx [OLEAUT32.183]
301 * Loads and optionally registers a type library
307 HRESULT WINAPI
LoadTypeLibEx(
308 LPCOLESTR szFile
, /* [in] Name of file to load from */
309 REGKIND regkind
, /* [in] Specify kind of registration */
310 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
312 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
317 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
320 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
323 /* Look for a trailing '\\' followed by an index */
324 pIndexStr
= strrchrW(szFile
, '\\');
325 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
326 index
= atoiW(pIndexStr
);
327 memcpy(szFileCopy
, szFile
,
328 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
329 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
330 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
332 return TYPE_E_CANTLOADLIBRARY
;
333 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
334 return TYPE_E_CANTLOADLIBRARY
;
337 static const WCHAR stdole32tlb
[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
340 lstrcpyW(tstpath
,szFile
);
342 for (i
=0;i
<strlenW(tstpath
);i
++) {
343 if (tstpath
[i
] == 's') {
344 if (!strcmpW(tstpath
+i
,stdole32tlb
)) {
346 MESSAGE("**************************************************************************\n");
347 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
348 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
349 MESSAGE("on the Microsoft Download Pages.\n");
350 MESSAGE("**************************************************************************\n");
355 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile
));
356 return TYPE_E_CANTLOADLIBRARY
;
360 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
362 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
367 case REGKIND_DEFAULT
:
368 /* don't register typelibs supplied with full path. Experimentation confirms the following */
370 ((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
371 (szFile
[0] && (szFile
[1] == ':'))) break;
372 /* else fall-through */
374 case REGKIND_REGISTER
:
375 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szPath
, NULL
)))
377 IUnknown_Release(*pptLib
);
385 TRACE(" returns %08lx\n",res
);
389 /******************************************************************************
390 * LoadRegTypeLib [OLEAUT32.162]
392 HRESULT WINAPI
LoadRegTypeLib(
393 REFGUID rguid
, /* [in] referenced guid */
394 WORD wVerMajor
, /* [in] major version */
395 WORD wVerMinor
, /* [in] minor version */
396 LCID lcid
, /* [in] locale id */
397 ITypeLib
**ppTLib
) /* [out] path of typelib */
400 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
404 res
= LoadTypeLib(bstr
, ppTLib
);
408 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
414 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
415 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
416 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
417 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
418 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
419 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
421 /******************************************************************************
422 * RegisterTypeLib [OLEAUT32.163]
423 * Adds information about a type library to the System Registry
425 * Docs: ITypeLib FAR * ptlib
426 * Docs: OLECHAR FAR* szFullPath
427 * Docs: OLECHAR FAR* szHelpDir
433 HRESULT WINAPI
RegisterTypeLib(
434 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
435 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
436 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
439 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
440 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
441 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
451 if (ptlib
== NULL
|| szFullPath
== NULL
)
454 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
457 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
460 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
461 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
465 /* Set the human-readable name of the typelib */
466 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
468 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
469 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
477 /* Make up the name of the typelib path subkey */
478 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
480 /* Create the typelib path subkey */
481 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
482 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
484 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
485 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
493 /* Create the flags subkey */
494 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
495 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
497 /* FIXME: is %u correct? */
498 static const WCHAR formatW
[] = {'%','u',0};
500 sprintfW(buf
, formatW
, attr
->wLibFlags
);
501 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
502 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
510 /* create the helpdir subkey */
511 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
512 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
514 BOOL freeHelpDir
= FALSE
;
517 /* if we created a new key, and helpDir was null, set the helpdir
518 to the directory which contains the typelib. However,
519 if we just opened an existing key, we leave the helpdir alone */
520 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
521 szHelpDir
= SysAllocString(szFullPath
);
522 pIndexStr
= strrchrW(szHelpDir
, '\\');
529 /* if we have an szHelpDir, set it! */
530 if (szHelpDir
!= NULL
) {
531 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
532 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
538 if (freeHelpDir
) SysFreeString(szHelpDir
);
550 /* register OLE Automation-compatible interfaces for this typelib */
551 types
= ITypeLib_GetTypeInfoCount(ptlib
);
552 for (tidx
=0; tidx
<types
; tidx
++) {
553 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
554 LPOLESTR name
= NULL
;
555 ITypeInfo
*tinfo
= NULL
;
557 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
560 case TKIND_INTERFACE
:
561 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
562 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
566 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
567 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
571 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
576 TYPEATTR
*tattr
= NULL
;
577 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
580 TRACE_(typelib
)("guid=%s, flags=%04x (",
581 debugstr_guid(&tattr
->guid
),
584 if (TRACE_ON(typelib
)) {
585 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
606 * FIXME: The 1 is just here until we implement rpcrt4
607 * stub/proxy handling. Until then it helps IShield
610 if (1 || (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
))
612 if (!(tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) {
613 FIXME("Registering non-oleautomation interface!\n");
616 /* register interface<->typelib coupling */
617 get_interface_key( &tattr
->guid
, keyName
);
618 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
619 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
622 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
623 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
625 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
626 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
627 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
628 (BYTE
*)PSOA
, sizeof PSOA
);
632 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
633 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
634 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
635 (BYTE
*)PSOA
, sizeof PSOA
);
639 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
640 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
643 static const WCHAR fmtver
[] = {'%','u','.','%','u',0 };
644 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
646 StringFromGUID2(&attr
->guid
, buffer
, 40);
647 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
648 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
649 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
650 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
651 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
659 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
662 ITypeInfo_Release(tinfo
);
669 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
675 /******************************************************************************
676 * UnRegisterTypeLib [OLEAUT32.186]
677 * Removes information about a type library from the System Registry
684 HRESULT WINAPI
UnRegisterTypeLib(
685 REFGUID libid
, /* [in] Guid of the library */
686 WORD wVerMajor
, /* [in] major version */
687 WORD wVerMinor
, /* [in] minor version */
688 LCID lcid
, /* [in] locale id */
691 BSTR tlibPath
= NULL
;
694 WCHAR subKeyName
[50];
697 BOOL deleteOtherStuff
;
700 TYPEATTR
* typeAttr
= NULL
;
702 ITypeInfo
* typeInfo
= NULL
;
703 ITypeLib
* typeLib
= NULL
;
706 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
708 /* Create the path to the key */
709 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
711 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
)
713 TRACE("Unsupported syskind %i\n", syskind
);
714 result
= E_INVALIDARG
;
718 /* get the path to the typelib on disk */
719 if (QueryPathOfRegTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, &tlibPath
) != S_OK
) {
720 result
= E_INVALIDARG
;
724 /* Try and open the key to the type library. */
725 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != S_OK
) {
726 result
= E_INVALIDARG
;
730 /* Try and load the type library */
731 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
)) {
732 result
= TYPE_E_INVALIDSTATE
;
736 /* remove any types registered with this typelib */
737 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
738 for (i
=0; i
<numTypes
; i
++) {
739 /* get the kind of type */
740 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
744 /* skip non-interfaces, and get type info for the type */
745 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
748 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
751 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
755 /* the path to the type */
756 get_interface_key( &typeAttr
->guid
, subKeyName
);
758 /* Delete its bits */
759 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != S_OK
) {
762 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
763 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
764 RegDeleteKeyW(subKey
, TypeLibW
);
767 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
770 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
772 if (typeInfo
) ITypeInfo_Release(typeInfo
);
776 /* Now, delete the type library path subkey */
777 get_lcid_subkey( lcid
, syskind
, subKeyName
);
778 RegDeleteKeyW(key
, subKeyName
);
779 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
780 RegDeleteKeyW(key
, subKeyName
);
782 /* check if there is anything besides the FLAGS/HELPDIR keys.
783 If there is, we don't delete them */
784 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
785 deleteOtherStuff
= TRUE
;
787 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == S_OK
) {
788 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
790 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
791 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
792 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
793 deleteOtherStuff
= FALSE
;
797 /* only delete the other parts of the key if we're absolutely sure */
798 if (deleteOtherStuff
) {
799 RegDeleteKeyW(key
, FLAGSW
);
800 RegDeleteKeyW(key
, HELPDIRW
);
804 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
805 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
806 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
810 if (tlibPath
) SysFreeString(tlibPath
);
811 if (typeLib
) ITypeLib_Release(typeLib
);
812 if (subKey
) RegCloseKey(subKey
);
813 if (key
) RegCloseKey(key
);
817 /*======================= ITypeLib implementation =======================*/
819 typedef struct tagTLBCustData
823 struct tagTLBCustData
* next
;
826 /* data structure for import typelibs */
827 typedef struct tagTLBImpLib
829 int offset
; /* offset in the file (MSFT)
830 offset in nametable (SLTG)
831 just used to identify library while reading
833 GUID guid
; /* libid */
834 BSTR name
; /* name */
836 LCID lcid
; /* lcid of imported typelib */
838 WORD wVersionMajor
; /* major version number */
839 WORD wVersionMinor
; /* minor version number */
841 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
842 NULL if not yet loaded */
843 struct tagTLBImpLib
* next
;
846 /* internal ITypeLib data */
847 typedef struct tagITypeLibImpl
849 ITypeLib2Vtbl
*lpVtbl
;
850 ITypeCompVtbl
*lpVtblTypeComp
;
852 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
854 /* strings can be stored in tlb as multibyte strings BUT they are *always*
855 * exported to the application as a UNICODE string.
861 unsigned long dwHelpContext
;
862 int TypeInfoCount
; /* nr of typeinfo's in librarry */
863 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
864 int ctCustData
; /* number of items in cust data list */
865 TLBCustData
* pCustData
; /* linked list to cust data */
866 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
867 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
868 libary. Only used while read MSFT
871 /* typelibs are cached, keyed by path, so store the linked list info within them */
872 struct tagITypeLibImpl
*next
, *prev
;
876 static struct ITypeLib2Vtbl tlbvt
;
877 static struct ITypeCompVtbl tlbtcvt
;
879 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
880 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
882 /* ITypeLib methods */
883 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
884 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
886 /*======================= ITypeInfo implementation =======================*/
888 /* data for refernced types */
889 typedef struct tagTLBRefType
891 INT index
; /* Type index for internal ref or for external ref
892 it the format is SLTG. -2 indicates to
895 GUID guid
; /* guid of the referenced type */
896 /* if index == TLB_REF_USE_GUID */
898 HREFTYPE reference
; /* The href of this ref */
899 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
900 TLB_REF_INTERNAL for internal refs
901 TLB_REF_NOT_FOUND for broken refs */
903 struct tagTLBRefType
* next
;
906 #define TLB_REF_USE_GUID -2
908 #define TLB_REF_INTERNAL (void*)-2
909 #define TLB_REF_NOT_FOUND (void*)-1
911 /* internal Parameter data */
912 typedef struct tagTLBParDesc
916 TLBCustData
* pCustData
; /* linked list to cust data */
919 /* internal Function data */
920 typedef struct tagTLBFuncDesc
922 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
923 BSTR Name
; /* the name of this function */
924 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
926 int HelpStringContext
;
928 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
930 TLBCustData
* pCustData
; /* linked list to cust data; */
931 struct tagTLBFuncDesc
* next
;
934 /* internal Variable data */
935 typedef struct tagTLBVarDesc
937 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
938 BSTR Name
; /* the name of this variable */
940 int HelpStringContext
; /* FIXME: where? */
943 TLBCustData
* pCustData
;/* linked list to cust data; */
944 struct tagTLBVarDesc
* next
;
947 /* internal implemented interface data */
948 typedef struct tagTLBImplType
950 HREFTYPE hRef
; /* hRef of interface */
951 int implflags
; /* IMPLFLAG_*s */
953 TLBCustData
* pCustData
;/* linked list to custom data; */
954 struct tagTLBImplType
*next
;
957 /* internal TypeInfo data */
958 typedef struct tagITypeInfoImpl
960 ITypeInfo2Vtbl
*lpVtbl
;
961 ITypeCompVtbl
*lpVtblTypeComp
;
963 TYPEATTR TypeAttr
; /* _lots_ of type information. */
964 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
965 int index
; /* index in this typelib; */
966 /* type libs seem to store the doc strings in ascii
967 * so why should we do it in unicode?
971 unsigned long dwHelpContext
;
972 unsigned long dwHelpStringContext
;
975 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
978 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
980 /* Implemented Interfaces */
981 TLBImplType
* impltypelist
;
983 TLBRefType
* reflist
;
985 TLBCustData
* pCustData
; /* linked list to cust data; */
986 struct tagITypeInfoImpl
* next
;
989 static struct ITypeInfo2Vtbl tinfvt
;
990 static struct ITypeCompVtbl tcompvt
;
992 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor();
994 typedef struct tagTLBContext
996 unsigned int oStart
; /* start of TLB in file */
997 unsigned int pos
; /* current pos */
998 unsigned int length
; /* total length */
999 void *mapping
; /* memory mapping */
1000 MSFT_SegDir
* pTblDir
;
1001 ITypeLibImpl
* pLibInfo
;
1005 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
1010 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
1011 if (pTD
->vt
& VT_RESERVED
)
1012 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1013 if (pTD
->vt
& VT_BYREF
)
1014 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1015 if (pTD
->vt
& VT_ARRAY
)
1016 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1017 if (pTD
->vt
& VT_VECTOR
)
1018 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1019 switch(pTD
->vt
& VT_TYPEMASK
) {
1020 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1021 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1022 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1023 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1024 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1025 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1026 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1027 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1028 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1029 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1030 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1031 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1032 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1033 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1034 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1035 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1036 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1037 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1038 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1039 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1040 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
1041 pTD
->u
.hreftype
); break;
1042 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1043 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1045 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1046 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1048 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1049 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1050 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1053 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1057 void dump_ELEMDESC(ELEMDESC
*edesc
) {
1059 dump_TypeDesc(&edesc
->tdesc
,buf
);
1060 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1061 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
1062 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1064 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
1066 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
1067 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1068 MESSAGE("Param %d:\n",i
);
1069 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1071 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1072 switch (funcdesc
->funckind
) {
1073 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1074 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1075 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1076 case FUNC_STATIC
: MESSAGE("static");break;
1077 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1078 default: MESSAGE("unknown");break;
1080 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1081 switch (funcdesc
->invkind
) {
1082 case INVOKE_FUNC
: MESSAGE("func");break;
1083 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1084 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1085 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1087 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1088 switch (funcdesc
->callconv
) {
1089 case CC_CDECL
: MESSAGE("cdecl");break;
1090 case CC_PASCAL
: MESSAGE("pascal");break;
1091 case CC_STDCALL
: MESSAGE("stdcall");break;
1092 case CC_SYSCALL
: MESSAGE("syscall");break;
1095 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1096 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1097 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1099 MESSAGE("\telemdescFunc (return value type):\n");
1100 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1103 void dump_IDLDESC(IDLDESC
*idl
) {
1104 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
1107 static const char * typekind_desc
[] =
1120 void dump_TYPEATTR(TYPEATTR
*tattr
) {
1122 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
1123 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
1124 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
1125 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
1126 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
1127 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
1128 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
1129 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
1130 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
1131 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
1132 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
1133 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
1134 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
1135 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
1136 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
1137 MESSAGE("\ttypedesc: %s\n", buf
);
1138 dump_IDLDESC(&tattr
->idldescType
);
1141 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
1144 if (!TRACE_ON(typelib
))
1146 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1147 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1148 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1151 dump_FUNCDESC(&(pfd
->funcdesc
));
1153 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1154 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
1156 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
1160 dump_TLBFuncDescOne(pfd
);
1164 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
1168 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1173 static void dump_TLBImpLib(TLBImpLib
*import
)
1175 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1176 debugstr_w(import
->name
));
1177 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1178 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1181 static void dump_TLBRefType(TLBRefType
* prt
)
1185 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1186 if(prt
->index
== -1)
1187 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1189 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1191 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1192 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1193 TRACE_(typelib
)("in lib\n");
1194 dump_TLBImpLib(prt
->pImpTLInfo
);
1200 static void dump_TLBImplType(TLBImplType
* impl
)
1204 "implementing/inheriting interface hRef = %lx implflags %x\n",
1205 impl
->hRef
, impl
->implflags
);
1210 void dump_Variant(VARIANT
* pvar
)
1214 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1218 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1219 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1221 TRACE(",%p", V_BYREF(pvar
));
1223 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1227 else switch (V_TYPE(pvar
))
1229 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1230 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1231 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1232 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1234 case VT_I4
: TRACE(",%ld", V_I4(pvar
)); break;
1236 case VT_UI4
: TRACE(",%ld", V_UI4(pvar
)); break;
1237 case VT_I8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_I8(pvar
) >> 32),
1238 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1239 case VT_UI8
: TRACE(",0x%08lx,0x%08lx", (ULONG
)(V_UI8(pvar
) >> 32),
1240 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1241 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1242 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1243 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1244 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1245 case VT_CY
: TRACE(",0x%08lx,0x%08lx", V_CY(pvar
).s
.Hi
,
1246 V_CY(pvar
).s
.Lo
); break;
1248 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1249 TRACE(",<invalid>");
1251 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1252 st
.wHour
, st
.wMinute
, st
.wSecond
);
1256 case VT_USERDEFINED
:
1258 case VT_NULL
: break;
1259 default: TRACE(",?"); break;
1265 static void dump_DispParms(DISPPARAMS
* pdp
)
1269 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1271 while (index
< pdp
->cArgs
)
1273 dump_Variant( &pdp
->rgvarg
[index
] );
1278 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1280 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1281 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1282 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1283 TRACE("fct:%u var:%u impl:%u\n",
1284 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1285 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1286 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1287 dump_TLBFuncDesc(pty
->funclist
);
1288 dump_TLBVarDesc(pty
->varlist
);
1289 dump_TLBImplType(pty
->impltypelist
);
1292 void dump_VARDESC(VARDESC
*v
)
1294 MESSAGE("memid %ld\n",v
->memid
);
1295 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1296 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1297 dump_ELEMDESC(&(v
->elemdescVar
));
1298 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1299 MESSAGE("varkind %d\n",v
->varkind
);
1302 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1304 /* VT_LPWSTR is largest type that */
1305 /* may appear in type description*/
1306 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1307 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1308 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1309 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1310 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1311 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1315 static void TLB_abort()
1319 static void * TLB_Alloc(unsigned size
)
1322 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1324 ERR("cannot allocate memory\n");
1329 static void TLB_Free(void * ptr
)
1331 HeapFree(GetProcessHeap(), 0, ptr
);
1335 /**********************************************************************
1337 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1340 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1342 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1343 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1345 if (where
!= DO_NOT_SEEK
)
1347 where
+= pcx
->oStart
;
1348 if (where
> pcx
->length
)
1351 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1356 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1357 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1362 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1367 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1368 FromLEDWords(buffer
, ret
);
1373 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1378 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1379 FromLEWords(buffer
, ret
);
1384 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1386 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1387 memset(pGuid
,0, sizeof(GUID
));
1390 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1391 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1392 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1393 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1394 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1397 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1400 MSFT_NameIntro niName
;
1402 WCHAR
* pwstring
= NULL
;
1403 BSTR bstrName
= NULL
;
1405 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1406 pcx
->pTblDir
->pNametab
.offset
+offset
);
1407 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1408 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1409 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1410 name
[niName
.namelen
& 0xff]='\0';
1412 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1415 /* no invalid characters in string */
1418 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1420 /* don't check for invalid character since this has been done previously */
1421 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1423 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1424 lengthInChars
= SysStringLen(bstrName
);
1425 HeapFree(GetProcessHeap(), 0, pwstring
);
1428 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1432 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1439 if(offset
<0) return NULL
;
1440 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1441 if(length
<= 0) return 0;
1442 string
=TLB_Alloc(length
+1);
1443 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1444 string
[length
]='\0';
1446 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1447 string
, -1, NULL
, 0);
1449 /* no invalid characters in string */
1452 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1454 /* don't check for invalid character since this has been done previously */
1455 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1457 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1458 lengthInChars
= SysStringLen(bstr
);
1459 HeapFree(GetProcessHeap(), 0, pwstring
);
1462 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1466 * read a value and fill a VARIANT structure
1468 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1472 TRACE_(typelib
)("\n");
1474 if(offset
<0) { /* data are packed in here */
1475 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1476 V_UNION(pVar
, iVal
) = offset
& 0xffff;
1479 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1480 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1481 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1482 switch (V_VT(pVar
)){
1483 case VT_EMPTY
: /* FIXME: is this right? */
1484 case VT_NULL
: /* FIXME: is this right? */
1485 case VT_I2
: /* this should not happen */
1496 case VT_VOID
: /* FIXME: is this right? */
1504 case VT_DECIMAL
: /* FIXME: is this right? */
1507 /* pointer types with known behaviour */
1510 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1512 FIXME("BSTR length = %d?\n", size
);
1514 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1515 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1516 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1517 /* FIXME: do we need a AtoW conversion here? */
1518 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1519 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1524 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1531 case VT_USERDEFINED
:
1537 case VT_STREAMED_OBJECT
:
1538 case VT_STORED_OBJECT
:
1539 case VT_BLOB_OBJECT
:
1544 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1548 if(size
>0) /* (big|small) endian correct? */
1549 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1553 * create a linked list with custom data
1555 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1561 TRACE_(typelib
)("\n");
1565 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1566 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1567 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1568 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1569 /* add new custom data at head of the list */
1570 pNew
->next
=*ppCustData
;
1572 offset
= entry
.next
;
1577 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1581 pTd
->vt
=type
& VT_TYPEMASK
;
1583 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1585 if(pTd
->vt
== VT_USERDEFINED
)
1586 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1588 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1592 MSFT_DoFuncs(TLBContext
* pcx
,
1597 TLBFuncDesc
** pptfd
)
1600 * member information is stored in a data structure at offset
1601 * indicated by the memoffset field of the typeinfo structure
1602 * There are several distinctive parts.
1603 * the first part starts with a field that holds the total length
1604 * of this (first) part excluding this field. Then follow the records,
1605 * for each member there is one record.
1607 * First entry is always the length of the record (excluding this
1609 * Rest of the record depends on the type of the member. If there is
1610 * a field indicating the member type (function variable intereface etc)
1611 * I have not found it yet. At this time we depend on the information
1612 * in the type info and the usual order how things are stored.
1614 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1617 * Third is a equal sized array with file offsets to the name entry
1620 * Forth and last (?) part is an array with offsets to the records in the
1621 * first part of this file segment.
1624 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1625 int recoffset
= offset
+ sizeof(INT
);
1628 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1630 TRACE_(typelib
)("\n");
1632 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1634 for ( i
= 0; i
< cFuncs
; i
++ )
1636 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1638 /* name, eventually add to a hash table */
1639 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1640 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1642 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1644 /* read the function information record */
1645 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1649 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1651 /* do the attributes */
1652 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1655 if ( nrattributes
> 0 )
1657 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1659 if ( nrattributes
> 1 )
1661 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1662 pFuncRec
->OptAttr
[1]) ;
1664 if ( nrattributes
> 2 )
1666 if ( pFuncRec
->FKCCIC
& 0x2000 )
1668 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1672 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1673 pFuncRec
->OptAttr
[2]);
1675 if( nrattributes
> 5 )
1677 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1679 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1682 pFuncRec
->OptAttr
[6],
1683 &(*pptfd
)->pCustData
);
1690 /* fill the FuncDesc Structure */
1691 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1692 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1694 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1695 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1696 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1697 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1698 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1699 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1700 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1704 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1707 /* do the parameters/arguments */
1708 if(pFuncRec
->nrargs
)
1711 MSFT_ParameterInfo paraminfo
;
1713 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1714 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1716 (*pptfd
)->pParamDesc
=
1717 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1719 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1720 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1722 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1724 TYPEDESC
* lpArgTypeDesc
= 0;
1728 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1731 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1733 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1735 /* SEEK value = jump to offset,
1736 * from there jump to the end of record,
1737 * go back by (j-1) arguments
1739 MSFT_ReadLEDWords( ¶minfo
,
1740 sizeof(MSFT_ParameterInfo
), pcx
,
1741 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1742 * sizeof(MSFT_ParameterInfo
)));
1744 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1746 while ( lpArgTypeDesc
!= NULL
)
1748 switch ( lpArgTypeDesc
->vt
)
1751 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1755 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1758 case VT_USERDEFINED
:
1759 MSFT_DoRefType(pcx
, pTI
,
1760 lpArgTypeDesc
->u
.hreftype
);
1762 lpArgTypeDesc
= NULL
;
1766 lpArgTypeDesc
= NULL
;
1772 /* parameter is the return value! */
1773 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1775 TYPEDESC
* lpArgTypeDesc
;
1777 (*pptfd
)->funcdesc
.elemdescFunc
=
1778 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1780 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1782 while ( lpArgTypeDesc
!= NULL
)
1784 switch ( lpArgTypeDesc
->vt
)
1787 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1791 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1795 case VT_USERDEFINED
:
1798 lpArgTypeDesc
->u
.hreftype
);
1800 lpArgTypeDesc
= NULL
;
1804 lpArgTypeDesc
= NULL
;
1809 /* second time around */
1810 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1813 (*pptfd
)->pParamDesc
[j
].Name
=
1814 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1817 if ( (PARAMFLAG_FHASDEFAULT
&
1818 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1819 ((pFuncRec
->FKCCIC
) & 0x1000) )
1821 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1823 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1825 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1827 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1828 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1830 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1834 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1837 pFuncRec
->OptAttr
[7+j
],
1838 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1843 /* scode is not used: archaic win16 stuff FIXME: right? */
1844 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1845 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1847 pptfd
= & ((*pptfd
)->next
);
1848 recoffset
+= reclength
;
1852 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1853 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1855 int infolen
, nameoffset
, reclength
;
1857 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1861 TRACE_(typelib
)("\n");
1863 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1864 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1865 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1866 recoffset
+= offset
+sizeof(INT
);
1867 for(i
=0;i
<cVars
;i
++){
1868 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1869 /* name, eventually add to a hash table */
1870 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1871 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1872 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1873 /* read the variable information record */
1874 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1876 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1878 if(reclength
>(6*sizeof(INT
)) )
1879 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1880 if(reclength
>(7*sizeof(INT
)) )
1881 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1882 if(reclength
>(8*sizeof(INT
)) )
1883 if(reclength
>(9*sizeof(INT
)) )
1884 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1885 /* fill the VarDesc Structure */
1886 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1887 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1888 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1889 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1890 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1891 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1892 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1893 if(pVarRec
->VarKind
== VAR_CONST
){
1894 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1895 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1896 pVarRec
->OffsValue
, pcx
);
1898 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1899 pptvd
=&((*pptvd
)->next
);
1900 recoffset
+= reclength
;
1903 /* fill in data for a hreftype (offset). When the refernced type is contained
1904 * in the typelib, it's just an (file) offset in the type info base dir.
1905 * If comes from import, it's an offset+1 in the ImpInfo table
1907 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1911 TLBRefType
**ppRefType
= &pTI
->reflist
;
1913 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1916 if((*ppRefType
)->reference
== offset
)
1918 ppRefType
= &(*ppRefType
)->next
;
1921 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1922 sizeof(**ppRefType
));
1924 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1925 /* external typelib */
1926 MSFT_ImpInfo impinfo
;
1927 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1929 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1931 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1932 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1933 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1934 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1935 pImpLib
=pImpLib
->next
;
1938 (*ppRefType
)->reference
=offset
;
1939 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1940 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1941 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1943 ERR("Cannot find a reference\n");
1944 (*ppRefType
)->reference
=-1;
1945 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1948 /* in this typelib */
1949 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1950 (*ppRefType
)->reference
=offset
;
1951 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1955 /* process Implemented Interfaces of a com class */
1956 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1960 MSFT_RefRecord refrec
;
1961 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1963 TRACE_(typelib
)("\n");
1965 for(i
=0;i
<count
;i
++){
1966 if(offset
<0) break; /* paranoia */
1967 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1968 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1969 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1970 (*ppImpl
)->hRef
= refrec
.reftype
;
1971 (*ppImpl
)->implflags
=refrec
.flags
;
1972 (*ppImpl
)->ctCustData
=
1973 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1974 offset
=refrec
.onext
;
1975 ppImpl
=&((*ppImpl
)->next
);
1979 * process a typeinfo record
1981 ITypeInfoImpl
* MSFT_DoTypeInfo(
1984 ITypeLibImpl
* pLibInfo
)
1986 MSFT_TypeInfoBase tiBase
;
1987 ITypeInfoImpl
*ptiRet
;
1989 TRACE_(typelib
)("count=%u\n", count
);
1991 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
1992 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
1993 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
1994 /* this is where we are coming from */
1995 ptiRet
->pTypeLib
= pLibInfo
;
1996 ptiRet
->index
=count
;
1997 /* fill in the typeattr fields */
1998 WARN("Assign constructor/destructor memid\n");
2000 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2001 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2002 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
2003 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
2004 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2005 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2006 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2007 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2008 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2009 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2010 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2011 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2012 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2013 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2014 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2015 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2016 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2017 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2020 /* IDLDESC idldescType; *//* never saw this one != zero */
2022 /* name, eventually add to a hash table */
2023 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2024 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2026 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2027 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2028 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2029 /* note: InfoType's Help file and HelpStringDll come from the containing
2030 * library. Further HelpString and Docstring appear to be the same thing :(
2033 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2034 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2035 ptiRet
->TypeAttr
.cVars
,
2036 tiBase
.memoffset
, & ptiRet
->funclist
);
2038 if(ptiRet
->TypeAttr
.cVars
>0 )
2039 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2040 ptiRet
->TypeAttr
.cVars
,
2041 tiBase
.memoffset
, & ptiRet
->varlist
);
2042 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2043 switch(ptiRet
->TypeAttr
.typekind
)
2046 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2049 case TKIND_DISPATCH
:
2050 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2052 if (tiBase
.datatype1
!= -1)
2054 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2055 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2058 { /* FIXME: This is a really bad hack to add IDispatch */
2059 const char* szStdOle
= "stdole2.tlb\0";
2060 int nStdOleLen
= strlen(szStdOle
);
2061 TLBRefType
**ppRef
= &ptiRet
->reflist
;
2064 if((*ppRef
)->reference
== -1)
2066 ppRef
= &(*ppRef
)->next
;
2069 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
2070 (*ppRef
)->guid
= IID_IDispatch
;
2071 (*ppRef
)->reference
= -1;
2072 (*ppRef
)->index
= TLB_REF_USE_GUID
;
2073 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
2074 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
2075 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
2078 MultiByteToWideChar(CP_ACP
,
2082 (*ppRef
)->pImpTLInfo
->name
,
2083 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
2085 (*ppRef
)->pImpTLInfo
->lcid
= 0;
2086 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
2087 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
2092 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
2093 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
2094 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
2099 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
2101 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2102 debugstr_w(ptiRet
->Name
),
2103 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2104 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2109 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2110 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2111 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2114 static ITypeLibImpl
*tlb_cache_first
;
2115 static CRITICAL_SECTION cache_section
;
2116 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2118 0, 0, &cache_section
,
2119 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2120 0, 0, { 0, (DWORD
)(__FILE__
": typelib loader cache") }
2122 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2125 /****************************************************************************
2128 * find the type of the typelib file and map the typelib resource into
2131 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2132 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2133 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2135 ITypeLibImpl
*entry
;
2136 int ret
= TYPE_E_CANTLOADLIBRARY
;
2137 DWORD dwSignature
= 0;
2140 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2144 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2145 EnterCriticalSection(&cache_section
);
2146 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2148 if (!strcmpiW(entry
->path
, pszFileName
))
2150 TRACE("cache hit\n");
2151 *ppTypeLib
= (ITypeLib2
*)entry
;
2152 ITypeLib_AddRef(*ppTypeLib
);
2153 LeaveCriticalSection(&cache_section
);
2157 LeaveCriticalSection(&cache_section
);
2159 /* check the signature of the file */
2160 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2161 if (INVALID_HANDLE_VALUE
!= hFile
)
2163 HANDLE hMapping
= CreateFileMappingW( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2166 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2169 /* retrieve file size */
2170 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2172 /* first try to load as *.tlb */
2173 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2174 if ( dwSignature
== MSFT_SIGNATURE
)
2176 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2178 else if ( dwSignature
== SLTG_SIGNATURE
)
2180 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2182 UnmapViewOfFile(pBase
);
2184 CloseHandle(hMapping
);
2189 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
2191 /* find the typelibrary resource*/
2192 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2193 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2196 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2197 HRSRC hrsrc
= FindResourceW(hinstDLL
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2200 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2203 LPVOID pBase
= LockResource(hGlobal
);
2204 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2208 /* try to load as incore resource */
2209 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2210 if ( dwSignature
== MSFT_SIGNATURE
)
2212 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2214 else if ( dwSignature
== SLTG_SIGNATURE
)
2216 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2220 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2223 FreeResource( hGlobal
);
2226 FreeLibrary(hinstDLL
);
2231 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2233 TRACE("adding to cache\n");
2234 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2235 lstrcpyW(impl
->path
, pszFileName
);
2236 /* We should really canonicalise the path here. */
2238 /* FIXME: check if it has added already in the meantime */
2239 EnterCriticalSection(&cache_section
);
2240 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2242 tlb_cache_first
= impl
;
2243 LeaveCriticalSection(&cache_section
);
2246 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2251 /*================== ITypeLib(2) Methods ===================================*/
2253 /****************************************************************************
2254 * ITypeLib2_Constructor_MSFT
2256 * loading an MSFT typelib from an in-memory image
2258 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2262 MSFT_Header tlbHeader
;
2263 MSFT_SegDir tlbSegDir
;
2264 ITypeLibImpl
* pTypeLibImpl
;
2266 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2268 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2269 if (!pTypeLibImpl
) return NULL
;
2271 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2272 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2273 pTypeLibImpl
->ref
= 1;
2275 /* get pointer to beginning of typelib data */
2279 cx
.pLibInfo
= pTypeLibImpl
;
2280 cx
.length
= dwTLBLength
;
2283 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2285 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2286 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2287 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2290 /* there is a small amount of information here until the next important
2292 * the segment directory . Try to calculate the amount of data */
2293 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2295 /* now read the segment directory */
2296 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2297 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2298 cx
.pTblDir
= &tlbSegDir
;
2300 /* just check two entries */
2301 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2303 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2304 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2308 /* now fill our internal data */
2309 /* TLIBATTR fields */
2310 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2312 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2313 /* Windows seems to have zero here, is this correct? */
2314 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2315 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2317 pTypeLibImpl
->LibAttr
.lcid
= 0;
2319 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2320 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2321 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2322 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2324 /* name, eventually add to a hash table */
2325 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2328 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2329 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2331 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2334 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2335 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2338 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2341 if(tlbHeader
.CustomDataOffset
>= 0)
2343 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2346 /* fill in typedescriptions */
2347 if(tlbSegDir
.pTypdescTab
.length
> 0)
2349 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2351 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2352 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2355 /* FIXME: add several sanity checks here */
2356 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2357 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2359 /* FIXME: check safearray */
2361 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2363 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2365 else if(td
[0] == VT_CARRAY
)
2367 /* array descr table here */
2368 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2370 else if(td
[0] == VT_USERDEFINED
)
2372 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2374 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2377 /* second time around to fill the array subscript info */
2380 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2381 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2383 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2384 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2387 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2389 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2391 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2393 for(j
= 0; j
<td
[2]; j
++)
2395 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2396 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2397 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2398 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2403 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2404 ERR("didn't find array description data\n");
2409 /* imported type libs */
2410 if(tlbSegDir
.pImpFiles
.offset
>0)
2412 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2413 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2416 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2421 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2422 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2423 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2425 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2426 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2427 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2428 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2431 name
= TLB_Alloc(size
+1);
2432 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2433 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2434 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2435 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2438 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2439 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2441 ppImpLib
= &(*ppImpLib
)->next
;
2446 if(tlbHeader
.nrtypeinfos
>= 0 )
2448 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2449 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2452 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2454 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2456 ppTI
= &((*ppTI
)->next
);
2457 (pTypeLibImpl
->TypeInfoCount
)++;
2461 TRACE("(%p)\n", pTypeLibImpl
);
2462 return (ITypeLib2
*) pTypeLibImpl
;
2466 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2472 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2473 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2474 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2475 ret
= SysAllocString(nameW
);
2476 HeapFree(GetProcessHeap(), 0, nameW
);
2480 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2486 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2487 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2491 guid
->Data4
[0] = s
>> 8;
2492 guid
->Data4
[1] = s
& 0xff;
2495 for(i
= 0; i
< 6; i
++) {
2496 memcpy(b
, str
+ 24 + 2 * i
, 2);
2497 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2502 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2509 bytelen
= *(WORD
*)ptr
;
2510 if(bytelen
== 0xffff) return 2;
2511 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2512 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2513 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2514 *pBstr
= SysAllocStringLen(nameW
, len
);
2515 HeapFree(GetProcessHeap(), 0, nameW
);
2519 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2524 bytelen
= *(WORD
*)ptr
;
2525 if(bytelen
== 0xffff) return 2;
2526 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2527 memcpy(*str
, ptr
+ 2, bytelen
);
2528 (*str
)[bytelen
] = '\0';
2532 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2534 char *ptr
= pLibBlk
;
2537 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2538 FIXME("libblk magic = %04x\n", w
);
2543 if((w
= *(WORD
*)ptr
) != 0xffff) {
2544 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2549 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2551 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2553 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2556 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2559 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2560 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2562 pTypeLibImpl
->LibAttr
.lcid
= 0;
2565 ptr
+= 4; /* skip res12 */
2567 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2570 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2573 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2576 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2577 ptr
+= sizeof(GUID
);
2579 return ptr
- (char*)pLibBlk
;
2582 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2585 TYPEDESC
*pTD
= &pElem
->tdesc
;
2587 /* Handle [in/out] first */
2588 if((*pType
& 0xc000) == 0xc000)
2589 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2590 else if(*pType
& 0x8000)
2591 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2592 else if(*pType
& 0x4000)
2593 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2595 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2598 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2601 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2604 if((*pType
& 0xe00) == 0xe00) {
2606 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2608 pTD
= pTD
->u
.lptdesc
;
2610 switch(*pType
& 0x7f) {
2613 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2615 pTD
= pTD
->u
.lptdesc
;
2618 case VT_USERDEFINED
:
2619 pTD
->vt
= VT_USERDEFINED
;
2620 pTD
->u
.hreftype
= *(++pType
) / 4;
2626 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2629 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2631 pTD
->vt
= VT_CARRAY
;
2632 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2634 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2635 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2636 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2637 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2639 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2645 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2649 pTD
->vt
= VT_SAFEARRAY
;
2650 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2652 pTD
= pTD
->u
.lptdesc
;
2656 pTD
->vt
= *pType
& 0x7f;
2666 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2671 TLBRefType
**ppRefType
;
2673 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2674 FIXME("Ref magic = %x\n", pRef
->magic
);
2677 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2679 ppRefType
= &pTI
->reflist
;
2680 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2682 unsigned int lib_offs
, type_num
;
2684 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2685 sizeof(**ppRefType
));
2687 name
+= SLTG_ReadStringA(name
, &refname
);
2688 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2689 FIXME("Can't sscanf ref\n");
2690 if(lib_offs
!= 0xffff) {
2691 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2694 if((*import
)->offset
== lib_offs
)
2696 import
= &(*import
)->next
;
2699 char fname
[MAX_PATH
+1];
2702 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2704 (*import
)->offset
= lib_offs
;
2705 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2707 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2708 &(*import
)->wVersionMajor
,
2709 &(*import
)->wVersionMinor
,
2710 &(*import
)->lcid
, fname
) != 4) {
2711 FIXME("can't sscanf ref %s\n",
2712 pNameTable
+ lib_offs
+ 40);
2714 len
= strlen(fname
);
2715 if(fname
[len
-1] != '#')
2716 FIXME("fname = %s\n", fname
);
2717 fname
[len
-1] = '\0';
2718 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2720 (*ppRefType
)->pImpTLInfo
= *import
;
2721 } else { /* internal ref */
2722 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2724 (*ppRefType
)->reference
= ref
;
2725 (*ppRefType
)->index
= type_num
;
2727 HeapFree(GetProcessHeap(), 0, refname
);
2728 ppRefType
= &(*ppRefType
)->next
;
2730 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2731 FIXME("End of ref block magic = %x\n", *name
);
2732 dump_TLBRefType(pTI
->reflist
);
2735 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2738 SLTG_ImplInfo
*info
;
2739 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2740 /* I don't really get this structure, usually it's 0x16 bytes
2741 long, but iuser.tlb contains some that are 0x18 bytes long.
2742 That's ok because we can use the next ptr to jump to the next
2743 one. But how do we know the length of the last one? The WORD
2744 at offs 0x8 might be the clue. For now I'm just assuming that
2745 the last one is the regular 0x16 bytes. */
2747 info
= (SLTG_ImplInfo
*)pBlk
;
2749 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2750 sizeof(**ppImplType
));
2751 (*ppImplType
)->hRef
= info
->ref
;
2752 (*ppImplType
)->implflags
= info
->impltypeflags
;
2753 pTI
->TypeAttr
.cImplTypes
++;
2754 ppImplType
= &(*ppImplType
)->next
;
2756 if(info
->next
== 0xffff)
2759 FIXME("Interface inheriting more than one interface\n");
2760 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2762 info
++; /* see comment at top of function */
2766 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2769 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2770 SLTG_MemberHeader
*pMemHeader
;
2771 char *pFirstItem
, *pNextItem
;
2773 if(pTIHeader
->href_table
!= 0xffffffff) {
2774 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2779 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2781 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2783 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2784 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2787 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2791 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2794 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2795 SLTG_MemberHeader
*pMemHeader
;
2796 SLTG_Function
*pFunc
;
2797 char *pFirstItem
, *pNextItem
;
2798 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2801 if(pTIHeader
->href_table
!= 0xffffffff) {
2802 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2806 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2808 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2810 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2811 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2814 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2815 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2820 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2821 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2822 FIXME("func magic = %02x\n", pFunc
->magic
);
2825 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2826 sizeof(**ppFuncDesc
));
2827 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2829 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2830 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2831 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2832 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2833 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2834 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2836 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2837 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2839 if(pFunc
->retnextopt
& 0x80)
2840 pType
= &pFunc
->rettype
;
2842 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2845 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2847 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2848 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2849 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2850 (*ppFuncDesc
)->pParamDesc
=
2851 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2852 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2854 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2856 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2857 char *paramName
= pNameTable
+ *pArg
;
2859 /* If arg type follows then paramName points to the 2nd
2860 letter of the name, else the next WORD is an offset to
2861 the arg type and paramName points to the first letter.
2862 So let's take one char off paramName and see if we're
2863 pointing at an alpha-numeric char. However if *pArg is
2864 0xffff or 0xfffe then the param has no name, the former
2865 meaning that the next WORD is the type, the latter
2866 meaning the the next WORD is an offset to the type. */
2871 else if(*pArg
== 0xfffe) {
2875 else if(!isalnum(*(paramName
-1)))
2880 if(HaveOffs
) { /* the next word is an offset to type */
2881 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2882 SLTG_DoType(pType
, pFirstItem
,
2883 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2888 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2889 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2892 /* Are we an optional param ? */
2893 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2894 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2895 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2898 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2899 TLB_MultiByteToBSTR(paramName
);
2903 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2904 if(pFunc
->next
== 0xffff) break;
2906 pTI
->TypeAttr
.cFuncs
= num
;
2907 dump_TLBFuncDesc(pTI
->funclist
);
2908 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2911 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2914 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2915 SLTG_MemberHeader
*pMemHeader
;
2916 SLTG_RecordItem
*pItem
;
2918 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2923 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2925 pFirstItem
= (char*)(pMemHeader
+ 1);
2926 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2927 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2928 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2929 FIXME("record magic = %02x\n", pItem
->magic
);
2932 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2933 sizeof(**ppVarDesc
));
2934 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2935 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2936 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2937 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2939 if(pItem
->typepos
== 0x02)
2940 pType
= &pItem
->type
;
2941 else if(pItem
->typepos
== 0x00)
2942 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2944 FIXME("typepos = %02x\n", pItem
->typepos
);
2948 SLTG_DoType(pType
, pFirstItem
,
2949 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2951 /* FIXME("helpcontext, helpstring\n"); */
2953 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2955 ppVarDesc
= &((*ppVarDesc
)->next
);
2956 if(pItem
->next
== 0xffff) break;
2958 pTI
->TypeAttr
.cVars
= num
;
2959 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2962 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
2965 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2966 SLTG_MemberHeader
*pMemHeader
;
2967 SLTG_AliasItem
*pItem
;
2970 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2971 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
2974 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2975 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
2976 if (pItem
->vt
== 0xffff) {
2977 if (i
<(pMemHeader
->cbExtra
/4-1))
2978 FIXME("Endmarker too early in process alias data!\n");
2982 FIXME("Chain extends over last entry?\n");
2985 if (pItem
->vt
== VT_USERDEFINED
) {
2986 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
2987 /* guessing here ... */
2988 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
2989 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
2992 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
2993 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
2997 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3000 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3003 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3004 SLTG_MemberHeader
*pMemHeader
;
3005 SLTG_AliasItem
*pItem
;
3007 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3008 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
3009 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
3010 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
3011 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
3014 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3017 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
3018 SLTG_MemberHeader
*pMemHeader
;
3019 SLTG_EnumItem
*pItem
;
3021 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
3024 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
3026 pFirstItem
= (char*)(pMemHeader
+ 1);
3027 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
3028 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
3029 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
3030 FIXME("enumitem magic = %04x\n", pItem
->magic
);
3033 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3034 sizeof(**ppVarDesc
));
3035 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3036 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
3037 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
3039 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
3040 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
3041 *(INT
*)(pItem
->value
+ pFirstItem
);
3042 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
3043 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
3044 /* FIXME("helpcontext, helpstring\n"); */
3046 ppVarDesc
= &((*ppVarDesc
)->next
);
3047 if(pItem
->next
== 0xffff) break;
3049 pTI
->TypeAttr
.cVars
= num
;
3050 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
3053 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3054 managable copy of it into this */
3067 } SLTG_InternalOtherTypeInfo
;
3069 /****************************************************************************
3070 * ITypeLib2_Constructor_SLTG
3072 * loading a SLTG typelib from an in-memory image
3074 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3076 ITypeLibImpl
*pTypeLibImpl
;
3077 SLTG_Header
*pHeader
;
3078 SLTG_BlkEntry
*pBlkEntry
;
3082 LPVOID pBlk
, pFirstBlk
;
3083 SLTG_LibBlk
*pLibBlk
;
3084 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3085 char *pAfterOTIBlks
= NULL
;
3086 char *pNameTable
, *ptr
;
3089 ITypeInfoImpl
**ppTypeInfoImpl
;
3091 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3093 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
3094 if (!pTypeLibImpl
) return NULL
;
3096 pTypeLibImpl
->lpVtbl
= &tlbvt
;
3097 pTypeLibImpl
->ref
= 1;
3102 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
3103 pHeader
->nrOfFileBlks
);
3104 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3105 FIXME("Header type magic 0x%08lx not supported.\n",
3106 pHeader
->SLTG_magic
);
3110 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3111 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3113 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3114 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3116 /* Next we have a magic block */
3117 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3119 /* Let's see if we're still in sync */
3120 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3121 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3122 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3125 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3126 sizeof(SLTG_DIR_MAGIC
))) {
3127 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3131 pIndex
= (SLTG_Index
*)(pMagic
+1);
3133 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3135 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3137 /* We'll set up a ptr to the main library block, which is the last one. */
3139 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3140 pBlkEntry
[order
].next
!= 0;
3141 order
= pBlkEntry
[order
].next
- 1, i
++) {
3142 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3146 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3148 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3153 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3155 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3156 sizeof(*pOtherTypeInfoBlks
) *
3157 pTypeLibImpl
->TypeInfoCount
);
3160 ptr
= (char*)pLibBlk
+ len
;
3162 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3166 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3168 w
= *(WORD
*)(ptr
+ 2);
3171 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3173 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3174 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3176 w
= *(WORD
*)(ptr
+ 4 + len
);
3178 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3180 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3182 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3183 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3185 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3186 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3187 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3189 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3191 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3194 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3195 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3196 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3197 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3198 len
+= sizeof(SLTG_OtherTypeInfo
);
3202 pAfterOTIBlks
= ptr
;
3204 /* Skip this WORD and get the next DWORD */
3205 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3207 /* Now add this to pLibBLk look at what we're pointing at and
3208 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3209 dust and we should be pointing at the beginning of the name
3212 pNameTable
= (char*)pLibBlk
+ len
;
3214 switch(*(WORD
*)pNameTable
) {
3221 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3225 pNameTable
+= 0x216;
3229 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3231 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3234 /* Hopefully we now have enough ptrs set up to actually read in
3235 some TypeInfos. It's not clear which order to do them in, so
3236 I'll just follow the links along the BlkEntry chain and read
3237 them in in the order in which they're in the file */
3239 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3241 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3242 pBlkEntry
[order
].next
!= 0;
3243 order
= pBlkEntry
[order
].next
- 1, i
++) {
3245 SLTG_TypeInfoHeader
*pTIHeader
;
3246 SLTG_TypeInfoTail
*pTITail
;
3248 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3249 pOtherTypeInfoBlks
[i
].index_name
)) {
3250 FIXME("Index strings don't match\n");
3255 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3256 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3259 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3260 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3261 (*ppTypeInfoImpl
)->index
= i
;
3262 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3263 pOtherTypeInfoBlks
[i
].name_offs
+
3265 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3266 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3268 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3269 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3270 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3271 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3272 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3274 if((pTIHeader
->typeflags1
& 7) != 2)
3275 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3276 if(pTIHeader
->typeflags3
!= 2)
3277 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3279 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3280 debugstr_w((*ppTypeInfoImpl
)->Name
),
3281 typekind_desc
[pTIHeader
->typekind
],
3282 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3283 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3285 switch(pTIHeader
->typekind
) {
3287 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3291 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3294 case TKIND_INTERFACE
:
3295 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3299 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3303 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3304 if (pTITail
->tdescalias_vt
)
3305 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3308 case TKIND_DISPATCH
:
3309 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3313 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3319 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3320 but we've already set those */
3321 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3322 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3323 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3325 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3347 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3348 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3351 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3352 FIXME("Somehow processed %d TypeInfos\n", i
);
3356 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3357 return (ITypeLib2
*)pTypeLibImpl
;
3360 /* ITypeLib::QueryInterface
3362 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3367 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3369 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3372 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3373 IsEqualIID(riid
,&IID_ITypeLib
)||
3374 IsEqualIID(riid
,&IID_ITypeLib2
))
3381 ITypeLib2_AddRef(iface
);
3382 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3385 TRACE("-- Interface: E_NOINTERFACE\n");
3386 return E_NOINTERFACE
;
3391 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3393 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3395 TRACE("(%p)->ref was %u\n",This
, This
->ref
);
3397 return ++(This
->ref
);
3400 /* ITypeLib::Release
3402 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3404 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3408 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3412 /* remove cache entry */
3413 TRACE("removing from cache list\n");
3414 EnterCriticalSection(&cache_section
);
3415 if (This
->next
) This
->next
->prev
= This
->prev
;
3416 if (This
->prev
) This
->prev
->next
= This
->next
;
3417 else tlb_cache_first
= This
->next
;
3418 LeaveCriticalSection(&cache_section
);
3420 /* FIXME destroy child objects */
3421 TRACE(" destroying ITypeLib(%p)\n",This
);
3425 SysFreeString(This
->Name
);
3429 if (This
->DocString
)
3431 SysFreeString(This
->DocString
);
3432 This
->DocString
= NULL
;
3437 SysFreeString(This
->HelpFile
);
3438 This
->HelpFile
= NULL
;
3441 if (This
->HelpStringDll
)
3443 SysFreeString(This
->HelpStringDll
);
3444 This
->HelpStringDll
= NULL
;
3447 if (This
->pTypeInfo
) /* can be NULL */
3448 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3449 HeapFree(GetProcessHeap(),0,This
);
3456 /* ITypeLib::GetTypeInfoCount
3458 * Returns the number of type descriptions in the type library
3460 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3462 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3463 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3464 return This
->TypeInfoCount
;
3467 /* ITypeLib::GetTypeInfo
3469 * retrieves the specified type description in the library.
3471 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3474 ITypeInfo
**ppTInfo
)
3478 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3479 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3481 TRACE("(%p)->(index=%d) \n", This
, index
);
3483 if (!ppTInfo
) return E_INVALIDARG
;
3485 /* search element n in list */
3486 for(i
=0; i
< index
; i
++)
3488 pTypeInfo
= pTypeInfo
->next
;
3491 TRACE("-- element not found\n");
3492 return TYPE_E_ELEMENTNOTFOUND
;
3496 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3498 ITypeInfo_AddRef(*ppTInfo
);
3499 TRACE("-- found (%p)\n",*ppTInfo
);
3504 /* ITypeLibs::GetTypeInfoType
3506 * Retrieves the type of a type description.
3508 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3513 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3515 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3517 TRACE("(%p) index %d \n",This
, index
);
3519 if(!pTKind
) return E_INVALIDARG
;
3521 /* search element n in list */
3522 for(i
=0; i
< index
; i
++)
3526 TRACE("-- element not found\n");
3527 return TYPE_E_ELEMENTNOTFOUND
;
3529 pTInfo
= pTInfo
->next
;
3532 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3533 TRACE("-- found Type (%d)\n", *pTKind
);
3537 /* ITypeLib::GetTypeInfoOfGuid
3539 * Retrieves the type description that corresponds to the specified GUID.
3542 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3545 ITypeInfo
**ppTInfo
)
3547 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3548 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3550 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3552 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3554 /* search linked list for guid */
3555 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3557 pTypeInfo
= pTypeInfo
->next
;
3561 /* end of list reached */
3562 TRACE("-- element not found\n");
3563 return TYPE_E_ELEMENTNOTFOUND
;
3567 TRACE("-- found (%p, %s)\n",
3569 debugstr_w(pTypeInfo
->Name
));
3571 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3572 ITypeInfo_AddRef(*ppTInfo
);
3576 /* ITypeLib::GetLibAttr
3578 * Retrieves the structure that contains the library's attributes.
3581 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3583 LPTLIBATTR
*ppTLibAttr
)
3585 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3586 TRACE("(%p)\n",This
);
3587 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3588 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3592 /* ITypeLib::GetTypeComp
3594 * Enables a client compiler to bind to a library's types, variables,
3595 * constants, and global functions.
3598 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3600 ITypeComp
**ppTComp
)
3602 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3604 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3605 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3606 ITypeComp_AddRef(*ppTComp
);
3611 /* ITypeLib::GetDocumentation
3613 * Retrieves the library's documentation string, the complete Help file name
3614 * and path, and the context identifier for the library Help topic in the Help
3617 * On a successful return all non-null BSTR pointers will have been set,
3620 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3624 BSTR
*pBstrDocString
,
3625 DWORD
*pdwHelpContext
,
3626 BSTR
*pBstrHelpFile
)
3628 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3630 HRESULT result
= E_INVALIDARG
;
3635 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3637 pBstrName
, pBstrDocString
,
3638 pdwHelpContext
, pBstrHelpFile
);
3642 /* documentation for the typelib */
3646 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3652 if (This
->DocString
)
3653 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3654 else if (This
->Name
)
3655 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3657 *pBstrDocString
= NULL
;
3661 *pdwHelpContext
= This
->dwHelpContext
;
3666 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3668 *pBstrHelpFile
= NULL
;
3675 /* for a typeinfo */
3676 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3678 if(SUCCEEDED(result
))
3680 result
= ITypeInfo_GetDocumentation(pTInfo
,
3684 pdwHelpContext
, pBstrHelpFile
);
3686 ITypeInfo_Release(pTInfo
);
3691 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3693 if (pBstrName
) SysFreeString (*pBstrName
);
3695 return STG_E_INSUFFICIENTMEMORY
;
3700 * Indicates whether a passed-in string contains the name of a type or member
3701 * described in the library.
3704 static HRESULT WINAPI
ITypeLib2_fnIsName(
3710 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3711 ITypeInfoImpl
*pTInfo
;
3712 TLBFuncDesc
*pFInfo
;
3715 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3717 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3721 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3722 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3723 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3724 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3725 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3726 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3727 goto ITypeLib2_fnIsName_exit
;
3729 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3730 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3735 ITypeLib2_fnIsName_exit
:
3736 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3737 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3742 /* ITypeLib::FindName
3744 * Finds occurrences of a type description in a type library. This may be used
3745 * to quickly verify that a name exists in a type library.
3748 static HRESULT WINAPI
ITypeLib2_fnFindName(
3752 ITypeInfo
**ppTInfo
,
3756 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3757 ITypeInfoImpl
*pTInfo
;
3758 TLBFuncDesc
*pFInfo
;
3762 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3764 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3765 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3766 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3767 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3768 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3769 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3770 goto ITypeLib2_fnFindName_exit
;
3772 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3773 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3775 ITypeLib2_fnFindName_exit
:
3776 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3777 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3780 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3781 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3788 /* ITypeLib::ReleaseTLibAttr
3790 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3793 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3795 TLIBATTR
*pTLibAttr
)
3797 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3798 TRACE("freeing (%p)\n",This
);
3799 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3803 /* ITypeLib2::GetCustData
3805 * gets the custom data
3807 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3812 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3813 TLBCustData
*pCData
;
3815 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3817 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3820 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3824 VariantInit( pVarVal
);
3825 VariantCopy( pVarVal
, &pCData
->data
);
3828 return E_INVALIDARG
; /* FIXME: correct? */
3831 /* ITypeLib2::GetLibStatistics
3833 * Returns statistics about a type library that are required for efficient
3834 * sizing of hash tables.
3837 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3839 ULONG
*pcUniqueNames
,
3840 ULONG
*pcchUniqueNames
)
3842 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3844 FIXME("(%p): stub!\n", This
);
3846 if(pcUniqueNames
) *pcUniqueNames
=1;
3847 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3851 /* ITypeLib2::GetDocumentation2
3853 * Retrieves the library's documentation string, the complete Help file name
3854 * and path, the localization context to use, and the context ID for the
3855 * library Help topic in the Help file.
3858 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3862 BSTR
*pbstrHelpString
,
3863 DWORD
*pdwHelpStringContext
,
3864 BSTR
*pbstrHelpStringDll
)
3866 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3870 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3872 /* the help string should be obtained from the helpstringdll,
3873 * using the _DLLGetDocumentation function, based on the supplied
3874 * lcid. Nice to do sometime...
3878 /* documentation for the typelib */
3880 *pbstrHelpString
=SysAllocString(This
->DocString
);
3881 if(pdwHelpStringContext
)
3882 *pdwHelpStringContext
=This
->dwHelpContext
;
3883 if(pbstrHelpStringDll
)
3884 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3890 /* for a typeinfo */
3891 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3893 if(SUCCEEDED(result
))
3895 ITypeInfo2
* pTInfo2
;
3896 result
= ITypeInfo_QueryInterface(pTInfo
,
3898 (LPVOID
*) &pTInfo2
);
3900 if(SUCCEEDED(result
))
3902 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3906 pdwHelpStringContext
,
3907 pbstrHelpStringDll
);
3909 ITypeInfo2_Release(pTInfo2
);
3912 ITypeInfo_Release(pTInfo
);
3918 /* ITypeLib2::GetAllCustData
3920 * Gets all custom data items for the library.
3923 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3925 CUSTDATA
*pCustData
)
3927 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
3928 TLBCustData
*pCData
;
3930 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3931 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3932 if(pCustData
->prgCustData
){
3933 pCustData
->cCustData
=This
->ctCustData
;
3934 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3935 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3936 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3939 ERR(" OUT OF MEMORY! \n");
3940 return E_OUTOFMEMORY
;
3945 static ITypeLib2Vtbl tlbvt
= {
3946 ITypeLib2_fnQueryInterface
,
3948 ITypeLib2_fnRelease
,
3949 ITypeLib2_fnGetTypeInfoCount
,
3950 ITypeLib2_fnGetTypeInfo
,
3951 ITypeLib2_fnGetTypeInfoType
,
3952 ITypeLib2_fnGetTypeInfoOfGuid
,
3953 ITypeLib2_fnGetLibAttr
,
3954 ITypeLib2_fnGetTypeComp
,
3955 ITypeLib2_fnGetDocumentation
,
3957 ITypeLib2_fnFindName
,
3958 ITypeLib2_fnReleaseTLibAttr
,
3960 ITypeLib2_fnGetCustData
,
3961 ITypeLib2_fnGetLibStatistics
,
3962 ITypeLib2_fnGetDocumentation2
,
3963 ITypeLib2_fnGetAllCustData
3967 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
3969 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3971 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
3974 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
3976 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3978 return ITypeInfo_AddRef((ITypeInfo
*)This
);
3981 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
3983 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3985 return ITypeInfo_Release((ITypeInfo
*)This
);
3988 static HRESULT WINAPI
ITypeLibComp_fnBind(
3993 ITypeInfo
** ppTInfo
,
3994 DESCKIND
* pDescKind
,
3997 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4001 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4005 ITypeInfo
** ppTInfo
,
4006 ITypeComp
** ppTComp
)
4008 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4012 static ITypeCompVtbl tlbtcvt
=
4015 ITypeLibComp_fnQueryInterface
,
4016 ITypeLibComp_fnAddRef
,
4017 ITypeLibComp_fnRelease
,
4019 ITypeLibComp_fnBind
,
4020 ITypeLibComp_fnBindType
4023 /*================== ITypeInfo(2) Methods ===================================*/
4024 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
4026 ITypeInfoImpl
* pTypeInfoImpl
;
4028 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
4031 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
4032 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
4033 pTypeInfoImpl
->ref
=1;
4035 TRACE("(%p)\n", pTypeInfoImpl
);
4036 return (ITypeInfo2
*) pTypeInfoImpl
;
4039 /* ITypeInfo::QueryInterface
4041 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
4046 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4048 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4051 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4052 IsEqualIID(riid
,&IID_ITypeInfo
)||
4053 IsEqualIID(riid
,&IID_ITypeInfo2
))
4057 ITypeInfo_AddRef(iface
);
4058 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4061 TRACE("-- Interface: E_NOINTERFACE\n");
4062 return E_NOINTERFACE
;
4065 /* ITypeInfo::AddRef
4067 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
4069 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4072 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
4074 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
4078 /* ITypeInfo::Release
4080 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
4082 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4086 TRACE("(%p)->(%u)\n",This
, This
->ref
);
4089 /* We don't release ITypeLib when ref=0 becouse
4090 it means that funtion is called by ITypeLi2_Release */
4091 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
4093 FIXME("destroy child objects\n");
4095 TRACE("destroying ITypeInfo(%p)\n",This
);
4098 SysFreeString(This
->Name
);
4102 if (This
->DocString
)
4104 SysFreeString(This
->DocString
);
4105 This
->DocString
= 0;
4110 ITypeInfo_Release((ITypeInfo
*)This
->next
);
4113 HeapFree(GetProcessHeap(),0,This
);
4119 /* ITypeInfo::GetTypeAttr
4121 * Retrieves a TYPEATTR structure that contains the attributes of the type
4125 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
4126 LPTYPEATTR
*ppTypeAttr
)
4128 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4129 TRACE("(%p)\n",This
);
4130 /* FIXME: must do a copy here */
4131 *ppTypeAttr
=&This
->TypeAttr
;
4135 /* ITypeInfo::GetTypeComp
4137 * Retrieves the ITypeComp interface for the type description, which enables a
4138 * client compiler to bind to the type description's members.
4141 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4142 ITypeComp
* *ppTComp
)
4144 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4146 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4148 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4149 ITypeComp_AddRef(*ppTComp
);
4153 /* ITypeInfo::GetFuncDesc
4155 * Retrieves the FUNCDESC structure that contains information about a
4156 * specified function.
4159 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4160 LPFUNCDESC
*ppFuncDesc
)
4162 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4164 TLBFuncDesc
* pFDesc
;
4165 TRACE("(%p) index %d\n", This
, index
);
4166 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4169 /* FIXME: must do a copy here */
4170 *ppFuncDesc
=&pFDesc
->funcdesc
;
4173 return E_INVALIDARG
;
4176 /* ITypeInfo::GetVarDesc
4178 * Retrieves a VARDESC structure that describes the specified variable.
4181 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4182 LPVARDESC
*ppVarDesc
)
4184 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4186 TLBVarDesc
* pVDesc
;
4187 TRACE("(%p) index %d\n", This
, index
);
4188 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4191 /* FIXME: must do a copy here */
4192 *ppVarDesc
=&pVDesc
->vardesc
;
4195 return E_INVALIDARG
;
4198 /* ITypeInfo_GetNames
4200 * Retrieves the variable with the specified member ID (or the name of the
4201 * property or method and its parameters) that correspond to the specified
4204 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4205 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4207 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4208 TLBFuncDesc
* pFDesc
;
4209 TLBVarDesc
* pVDesc
;
4211 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4212 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4215 /* function found, now return function and parameter names */
4216 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4219 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4221 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4227 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4230 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4235 if(This
->TypeAttr
.cImplTypes
&&
4236 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4237 /* recursive search */
4240 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4242 if(SUCCEEDED(result
))
4244 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4245 ITypeInfo_Release(pTInfo
);
4248 WARN("Could not search inherited interface!\n");
4252 WARN("no names found\n");
4255 return TYPE_E_ELEMENTNOTFOUND
;
4262 /* ITypeInfo::GetRefTypeOfImplType
4264 * If a type description describes a COM class, it retrieves the type
4265 * description of the implemented interface types. For an interface,
4266 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4270 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4275 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4277 TLBImplType
*pImpl
= This
->impltypelist
;
4279 TRACE("(%p) index %d\n", This
, index
);
4280 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4284 /* only valid on dual interfaces;
4285 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4287 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4289 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4290 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4296 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4297 *pRefType
= pImpl
->hRef
;
4302 /* get element n from linked list */
4303 for(i
=0; pImpl
&& i
<index
; i
++)
4305 pImpl
= pImpl
->next
;
4308 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4310 *pRefType
= pImpl
->hRef
;
4312 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4319 /* ITypeInfo::GetImplTypeFlags
4321 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4322 * or base interface in a type description.
4324 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4325 UINT index
, INT
*pImplTypeFlags
)
4327 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4331 TRACE("(%p) index %d\n", This
, index
);
4332 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4333 i
++, pImpl
=pImpl
->next
)
4335 if(i
==index
&& pImpl
){
4336 *pImplTypeFlags
=pImpl
->implflags
;
4340 return TYPE_E_ELEMENTNOTFOUND
;
4344 * Maps between member names and member IDs, and parameter names and
4347 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4348 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4350 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4351 TLBFuncDesc
* pFDesc
;
4352 TLBVarDesc
* pVDesc
;
4355 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4357 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4359 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4360 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4361 for(i
=1; i
< cNames
; i
++){
4362 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4363 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4365 if( j
<pFDesc
->funcdesc
.cParams
)
4368 ret
=DISP_E_UNKNOWNNAME
;
4373 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4374 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4375 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4379 /* not found, see if this is and interface with an inheritance */
4380 if(This
->TypeAttr
.cImplTypes
&&
4381 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4382 /* recursive search */
4384 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4385 This
->impltypelist
->hRef
, &pTInfo
);
4387 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4388 ITypeInfo_Release(pTInfo
);
4391 WARN("Could not search inherited interface!\n");
4393 WARN("no names found\n");
4394 return DISP_E_UNKNOWNNAME
;
4397 /* ITypeInfo::Invoke
4399 * Invokes a method, or accesses a property of an object, that implements the
4400 * interface described by the type description.
4403 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4406 if (TRACE_ON(ole
)) {
4408 TRACE("Calling %p(",func
);
4409 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4421 res
= func(args
[0]);
4424 res
= func(args
[0],args
[1]);
4427 res
= func(args
[0],args
[1],args
[2]);
4430 res
= func(args
[0],args
[1],args
[2],args
[3]);
4433 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4436 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4439 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4442 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4445 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4448 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9]);
4451 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8],args
[9],args
[10]);
4454 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4460 FIXME("unsupported calling convention %d\n",callconv
);
4464 TRACE("returns %08lx\n",res
);
4468 extern int _argsize(DWORD vt
);
4470 /****************************************************************************
4471 * Helper functions for Dispcall / Invoke, which copies one variant
4472 * with target type onto the argument stack.
4475 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4476 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4478 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4482 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4483 memcpy(argpos
,&arg
,sizeof(void*));
4487 if (V_VT(arg
) == vt
) {
4488 memcpy(argpos
, &V_UNION(arg
,lVal
), arglen
);
4492 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4493 memcpy(argpos
, &V_UNION(arg
,parray
), sizeof(SAFEARRAY
*));
4497 if (vt
== VT_VARIANT
) {
4498 memcpy(argpos
, arg
, arglen
);
4501 /* Deref BYREF vars if there is need */
4502 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4503 memcpy(argpos
,(void*)V_UNION(arg
,lVal
), arglen
);
4506 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4507 /* in this context, if the type lib specifies IUnknown*, giving an
4508 IDispatch* is correct; so, don't invoke VariantChangeType */
4509 memcpy(argpos
,&V_UNION(arg
,lVal
), arglen
);
4512 if ((vt
== VT_PTR
) && tdesc
)
4513 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4515 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4516 ITypeInfo
*tinfo2
= NULL
;
4517 TYPEATTR
*tattr
= NULL
;
4520 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4522 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4523 "while coercing from vt 0x%x. Copying 4 byte.\n",
4524 tdesc
->u
.hreftype
,V_VT(arg
));
4525 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4528 hres
= ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4531 ERR("GetTypeAttr failed\n");
4532 ITypeInfo_Release(tinfo2
);
4535 switch (tattr
->typekind
) {
4537 switch ( V_VT( arg
) ) {
4539 *argpos
= V_UNION(arg
,iVal
);
4543 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4547 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4554 tdesc
= &(tattr
->tdescAlias
);
4555 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4558 case TKIND_INTERFACE
:
4559 if (V_VT(arg
) == VT_DISPATCH
) {
4561 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4562 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4566 hres
=IUnknown_QueryInterface(V_UNION(arg
,pdispVal
),
4567 &IID_IDispatch
,(LPVOID
*)&disp
);
4568 if (SUCCEEDED(hres
)) {
4569 memcpy(argpos
,&disp
,4);
4570 IUnknown_Release(V_UNION(arg
,pdispVal
));
4574 FIXME("Failed to query IDispatch interface from %s while "
4575 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4579 if (V_VT(arg
) == VT_UNKNOWN
) {
4580 memcpy(argpos
, &V_UNION(arg
,punkVal
), 4);
4584 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4585 V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4589 case TKIND_DISPATCH
:
4590 if (V_VT(arg
) == VT_DISPATCH
) {
4591 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4596 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4600 FIXME("TKIND_RECORD unhandled.\n");
4604 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4608 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
4609 ITypeInfo_Release(tinfo2
);
4615 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4616 memcpy(argpos
,&V_UNION(&va
,lVal
), arglen
);
4617 FIXME("Should not use VariantChangeType here."
4618 " (conversion from 0x%x -> 0x%x) %08lx\n",
4619 V_VT(arg
), vt
, *argpos
4623 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4627 /***********************************************************************
4628 * DispCallFunc (OLEAUT32.@)
4632 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4633 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4635 int i
, argsize
, argspos
;
4639 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4640 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4642 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4643 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4645 for (i
=0;i
<cActuals
;i
++) {
4646 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4647 dump_Variant(prgpvarg
[i
]);
4648 argsize
+= _argsize(prgvt
[i
]);
4650 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4651 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4653 for (i
=0;i
<cActuals
;i
++) {
4654 VARIANT
*arg
= prgpvarg
[i
];
4655 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4656 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4657 argspos
+= _argsize(prgvt
[i
]);
4660 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4662 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4667 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4668 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4669 FIXME("Method returned %lx\n",hres
);
4671 HeapFree(GetProcessHeap(),0,args
);
4675 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4680 DISPPARAMS
*pDispParams
,
4681 VARIANT
*pVarResult
,
4682 EXCEPINFO
*pExcepInfo
,
4685 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4686 TLBFuncDesc
* pFDesc
;
4687 TLBVarDesc
* pVDesc
;
4691 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4692 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4694 dump_DispParms(pDispParams
);
4696 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4697 if (pFDesc
->funcdesc
.memid
== memid
) {
4698 if (pFDesc
->funcdesc
.invkind
& dwFlags
)
4703 if (TRACE_ON(typelib
)) dump_TLBFuncDescOne(pFDesc
);
4704 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4705 switch (pFDesc
->funcdesc
.funckind
) {
4706 case FUNC_PUREVIRTUAL
:
4707 case FUNC_VIRTUAL
: {
4709 int numargs
, numargs2
, argspos
, args2pos
;
4710 DWORD
*args
, *args2
;
4711 VARIANT
*rgvarg
= HeapAlloc(GetProcessHeap(),0,sizeof(VARIANT
)*pFDesc
->funcdesc
.cParams
);
4712 memcpy(rgvarg
,pDispParams
->rgvarg
,sizeof(VARIANT
)*pDispParams
->cArgs
);
4714 numargs
= 1; numargs2
= 0;
4715 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4716 if (i
<pDispParams
->cArgs
)
4717 numargs
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4719 numargs
+= 1; /* sizeof(lpvoid) */
4720 numargs2
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4724 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4725 args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4727 args
[0] = (DWORD
)pIUnk
;
4728 argspos
= 1; args2pos
= 0;
4729 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4730 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4731 if (i
<pDispParams
->cArgs
) {
4732 VARIANT
*arg
= &rgvarg
[pDispParams
->cArgs
-i
-1];
4733 TYPEDESC
*tdesc
= &pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
;
4734 USHORT paramFlags
= pFDesc
->funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
4735 if (paramFlags
& PARAMFLAG_FOPT
) {
4736 if(i
< pFDesc
->funcdesc
.cParams
-pFDesc
->funcdesc
.cParamsOpt
)
4737 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4738 if(V_VT(arg
) == VT_EMPTY
4739 || ((V_VT(arg
) & VT_BYREF
) && !V_BYREF(arg
))) {
4740 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4741 How to determine it? */
4743 if(paramFlags
& PARAMFLAG_FHASDEFAULT
)
4744 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4745 V_VT(arg
) = VT_ERROR
;
4746 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4747 arglen
= _argsize(VT_ERROR
);
4750 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4751 if (FAILED(hres
)) return hres
;
4753 } else if(pFDesc
->funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FOPT
) {
4754 VARIANT
*arg
= &rgvarg
[i
];
4755 TYPEDESC
*tdesc
= &pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
;
4756 if(i
< pFDesc
->funcdesc
.cParams
-pFDesc
->funcdesc
.cParamsOpt
)
4757 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4758 if(pFDesc
->funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
4759 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4760 V_VT(arg
) = VT_ERROR
;
4761 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
4762 arglen
= _argsize(VT_ERROR
);
4763 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4764 if (FAILED(hres
)) return hres
;
4767 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
4768 if (tdesc
->vt
!= VT_PTR
)
4769 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4770 /*FIXME: give pointers for the rest, so propertyget works*/
4771 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4773 /* If pointer to variant, pass reference it. */
4774 if ((tdesc
->vt
== VT_PTR
) &&
4775 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4778 args
[argspos
]= (DWORD
)pVarResult
;
4783 if (pFDesc
->funcdesc
.cParamsOpt
< 0)
4784 FIXME("Does not support optional parameters (%d)\n",
4785 pFDesc
->funcdesc
.cParamsOpt
4788 res
= _invoke((*(FARPROC
**)pIUnk
)[pFDesc
->funcdesc
.oVft
/4],
4789 pFDesc
->funcdesc
.callconv
,
4794 HeapFree(GetProcessHeap(), 0, rgvarg
);
4796 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4798 for (i
=0;i
<pFDesc
->funcdesc
.cParams
-pDispParams
->cArgs
;i
++) {
4799 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4800 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
+pDispParams
->cArgs
].tdesc
);
4802 i4_tdesc
.vt
= VT_I4
;
4804 /* If we are a pointer to a variant, we are done already */
4805 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4808 VariantInit(pVarResult
);
4809 memcpy(&V_UNION(pVarResult
,intVal
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4811 if (tdesc
->vt
== VT_PTR
)
4812 tdesc
= tdesc
->u
.lptdesc
;
4813 if (tdesc
->vt
== VT_USERDEFINED
) {
4817 hres
= ITypeInfo_GetRefTypeInfo(iface
,tdesc
->u
.hreftype
,&tinfo2
);
4819 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc
->u
.hreftype
);
4822 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4823 switch (tattr
->typekind
) {
4825 /* force the return type to be VT_I4 */
4829 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr
->tdescAlias
.vt
);
4830 tdesc
= &(tattr
->tdescAlias
);
4833 case TKIND_INTERFACE
:
4834 FIXME("TKIND_INTERFACE unhandled.\n");
4836 case TKIND_DISPATCH
:
4837 FIXME("TKIND_DISPATCH unhandled.\n");
4840 FIXME("TKIND_RECORD unhandled.\n");
4843 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4846 ITypeInfo_Release(tinfo2
);
4848 V_VT(pVarResult
) = tdesc
->vt
;
4850 /* HACK: VB5 likes this.
4851 * I do not know why. There is 1 example in MSDN which uses
4852 * this which appears broken (mixes int vals and
4855 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4856 V_VT(pVarResult
) = VT_DISPATCH
;
4857 TRACE("storing into variant:\n");
4858 dump_Variant(pVarResult
);
4862 HeapFree(GetProcessHeap(),0,args2
);
4863 HeapFree(GetProcessHeap(),0,args
);
4866 case FUNC_DISPATCH
: {
4870 hr
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4872 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4875 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4876 hr
= IDispatch_Invoke(
4877 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4878 pVarResult
,pExcepInfo
,pArgErr
4881 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr
);
4882 IDispatch_Release(disp
);
4886 FIXME("Unknown function invocation type %d\n",pFDesc
->funcdesc
.funckind
);
4890 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4891 if (pVDesc
->vardesc
.memid
== memid
) {
4892 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR
)pVDesc
->Name
)));
4893 dump_TLBVarDesc(pVDesc
);
4898 /* not found, look for it in inherited interfaces */
4899 if (This
->TypeAttr
.cImplTypes
&&
4900 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
4901 /* recursive search */
4904 hr
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
4906 hr
=ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4907 ITypeInfo_Release(pTInfo
);
4910 WARN("Could not search inherited interface!\n");
4912 ERR("did not find member id %d, flags %d!\n", (int)memid
, dwFlags
);
4913 return DISP_E_MEMBERNOTFOUND
;
4916 /* ITypeInfo::GetDocumentation
4918 * Retrieves the documentation string, the complete Help file name and path,
4919 * and the context ID for the Help topic for a specified type description.
4921 * (Can be tested by the Visual Basic Editor in Word for instance.)
4923 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4924 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4925 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4927 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4928 TLBFuncDesc
* pFDesc
;
4929 TLBVarDesc
* pVDesc
;
4930 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4931 " HelpContext(%p) HelpFile(%p)\n",
4932 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4933 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4935 *pBstrName
=SysAllocString(This
->Name
);
4937 *pBstrDocString
=SysAllocString(This
->DocString
);
4939 *pdwHelpContext
=This
->dwHelpContext
;
4941 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4943 }else {/* for a member */
4944 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4945 if(pFDesc
->funcdesc
.memid
==memid
){
4947 *pBstrName
= SysAllocString(pFDesc
->Name
);
4949 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4951 *pdwHelpContext
=pFDesc
->helpcontext
;
4954 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4955 if(pVDesc
->vardesc
.memid
==memid
){
4957 *pBstrName
= SysAllocString(pVDesc
->Name
);
4959 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
4961 *pdwHelpContext
=pVDesc
->HelpContext
;
4965 return TYPE_E_ELEMENTNOTFOUND
;
4968 /* ITypeInfo::GetDllEntry
4970 * Retrieves a description or specification of an entry point for a function
4973 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
4974 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
4977 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
4978 TLBFuncDesc
*pFDesc
;
4980 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
4982 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4983 if(pFDesc
->funcdesc
.memid
==memid
){
4984 dump_TypeInfo(This
);
4985 dump_TLBFuncDescOne(pFDesc
);
4987 /* FIXME: This is wrong, but how do you find that out? */
4989 static const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4990 *pBstrDllName
= SysAllocString(oleaut32W
);
4993 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
4995 *pBstrName
= SysAllocString(pFDesc
->Entry
);
5003 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
5009 /* ITypeInfo::GetRefTypeInfo
5011 * If a type description references other type descriptions, it retrieves
5012 * the referenced type descriptions.
5014 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
5017 ITypeInfo
**ppTInfo
)
5019 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5020 HRESULT result
= E_FAIL
;
5023 if (hRefType
== -1 &&
5024 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
5025 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
5027 /* when we meet a DUAL dispinterface, we must create the interface
5030 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
5033 /* the interface version contains the same information as the dispinterface
5034 * copy the contents of the structs.
5036 *pTypeInfoImpl
= *This
;
5037 pTypeInfoImpl
->ref
= 1;
5039 /* change the type to interface */
5040 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
5042 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
5044 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
5049 TLBRefType
*pRefType
;
5050 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
5051 if(pRefType
->reference
== hRefType
)
5055 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
5056 if(pRefType
&& hRefType
!= -1) {
5057 ITypeLib
*pTLib
= NULL
;
5059 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
5061 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
5063 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
5064 TRACE("typeinfo in imported typelib that is already loaded\n");
5065 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
5066 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
5069 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5070 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
5071 pRefType
->pImpTLInfo
->wVersionMajor
,
5072 pRefType
->pImpTLInfo
->wVersionMinor
,
5073 pRefType
->pImpTLInfo
->lcid
,
5076 if(!SUCCEEDED(result
)) {
5077 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
5078 result
=LoadTypeLib(libnam
, &pTLib
);
5079 SysFreeString(libnam
);
5081 if(SUCCEEDED(result
)) {
5082 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
5083 ITypeLib2_AddRef(pTLib
);
5087 if(SUCCEEDED(result
)) {
5088 if(pRefType
->index
== TLB_REF_USE_GUID
)
5089 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
5093 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
5097 ITypeLib2_Release(pTLib
);
5101 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
5102 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
5106 /* ITypeInfo::AddressOfMember
5108 * Retrieves the addresses of static functions or variables, such as those
5111 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
5112 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
5114 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5115 FIXME("(%p) stub!\n", This
);
5119 /* ITypeInfo::CreateInstance
5121 * Creates a new instance of a type that describes a component object class
5124 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
5125 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
5127 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5128 FIXME("(%p) stub!\n", This
);
5132 /* ITypeInfo::GetMops
5134 * Retrieves marshalling information.
5136 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
5139 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5140 FIXME("(%p) stub!\n", This
);
5144 /* ITypeInfo::GetContainingTypeLib
5146 * Retrieves the containing type library and the index of the type description
5147 * within that type library.
5149 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
5150 ITypeLib
* *ppTLib
, UINT
*pIndex
)
5152 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5154 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5156 *pIndex
=This
->index
;
5157 TRACE("returning pIndex=%d\n", *pIndex
);
5161 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
5162 ITypeLib2_AddRef(*ppTLib
);
5163 TRACE("returning ppTLib=%p\n", *ppTLib
);
5169 /* ITypeInfo::ReleaseTypeAttr
5171 * Releases a TYPEATTR previously returned by GetTypeAttr.
5174 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
5175 TYPEATTR
* pTypeAttr
)
5177 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5178 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
5181 /* ITypeInfo::ReleaseFuncDesc
5183 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5185 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
5187 FUNCDESC
*pFuncDesc
)
5189 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5190 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
5193 /* ITypeInfo::ReleaseVarDesc
5195 * Releases a VARDESC previously returned by GetVarDesc.
5197 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5200 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5201 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5204 /* ITypeInfo2::GetTypeKind
5206 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5209 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5210 TYPEKIND
*pTypeKind
)
5212 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5213 *pTypeKind
=This
->TypeAttr
.typekind
;
5214 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5218 /* ITypeInfo2::GetTypeFlags
5220 * Returns the type flags without any allocations. This returns a DWORD type
5221 * flag, which expands the type flags without growing the TYPEATTR (type
5225 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5227 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5228 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5229 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5233 /* ITypeInfo2::GetFuncIndexOfMemId
5234 * Binds to a specific member based on a known DISPID, where the member name
5235 * is not known (for example, when binding to a default member).
5238 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5239 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5241 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5242 TLBFuncDesc
*pFuncInfo
;
5245 /* FIXME: should check for invKind??? */
5246 for(i
=0, pFuncInfo
=This
->funclist
;pFuncInfo
&&
5247 memid
!= pFuncInfo
->funcdesc
.memid
; i
++, pFuncInfo
=pFuncInfo
->next
);
5253 result
=E_INVALIDARG
;
5255 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5256 memid
, invKind
, SUCCEEDED(result
)? "SUCCES":"FAILED");
5260 /* TypeInfo2::GetVarIndexOfMemId
5262 * Binds to a specific member based on a known DISPID, where the member name
5263 * is not known (for example, when binding to a default member).
5266 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5267 MEMBERID memid
, UINT
*pVarIndex
)
5269 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5270 TLBVarDesc
*pVarInfo
;
5273 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5274 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5281 result
=E_INVALIDARG
;
5283 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5284 memid
, SUCCEEDED(result
)? "SUCCES":"FAILED");
5288 /* ITypeInfo2::GetCustData
5290 * Gets the custom data
5292 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5297 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5298 TLBCustData
*pCData
;
5300 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5301 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5303 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5307 VariantInit( pVarVal
);
5308 VariantCopy( pVarVal
, &pCData
->data
);
5311 return E_INVALIDARG
; /* FIXME: correct? */
5314 /* ITypeInfo2::GetFuncCustData
5316 * Gets the custom data
5318 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5324 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5325 TLBCustData
*pCData
=NULL
;
5326 TLBFuncDesc
* pFDesc
;
5328 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5329 pFDesc
=pFDesc
->next
);
5332 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5333 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5335 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5338 VariantInit( pVarVal
);
5339 VariantCopy( pVarVal
, &pCData
->data
);
5342 return E_INVALIDARG
; /* FIXME: correct? */
5345 /* ITypeInfo2::GetParamCustData
5347 * Gets the custom data
5349 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5356 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5357 TLBCustData
*pCData
=NULL
;
5358 TLBFuncDesc
* pFDesc
;
5361 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5363 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5364 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5365 pCData
= pCData
->next
)
5366 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5368 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5372 VariantInit( pVarVal
);
5373 VariantCopy( pVarVal
, &pCData
->data
);
5376 return E_INVALIDARG
; /* FIXME: correct? */
5379 /* ITypeInfo2::GetVarCustData
5381 * Gets the custom data
5383 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5389 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5390 TLBCustData
*pCData
=NULL
;
5391 TLBVarDesc
* pVDesc
;
5394 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5398 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5400 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5404 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5408 VariantInit( pVarVal
);
5409 VariantCopy( pVarVal
, &pCData
->data
);
5412 return E_INVALIDARG
; /* FIXME: correct? */
5415 /* ITypeInfo2::GetImplCustData
5417 * Gets the custom data
5419 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5425 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5426 TLBCustData
*pCData
=NULL
;
5427 TLBImplType
* pRDesc
;
5430 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5434 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5436 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5440 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5444 VariantInit( pVarVal
);
5445 VariantCopy( pVarVal
, &pCData
->data
);
5448 return E_INVALIDARG
; /* FIXME: correct? */
5451 /* ITypeInfo2::GetDocumentation2
5453 * Retrieves the documentation string, the complete Help file name and path,
5454 * the localization context to use, and the context ID for the library Help
5455 * topic in the Help file.
5458 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5462 BSTR
*pbstrHelpString
,
5463 DWORD
*pdwHelpStringContext
,
5464 BSTR
*pbstrHelpStringDll
)
5466 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5467 TLBFuncDesc
* pFDesc
;
5468 TLBVarDesc
* pVDesc
;
5469 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5470 "HelpStringContext(%p) HelpStringDll(%p)\n",
5471 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5472 pbstrHelpStringDll
);
5473 /* the help string should be obtained from the helpstringdll,
5474 * using the _DLLGetDocumentation function, based on the supplied
5475 * lcid. Nice to do sometime...
5477 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5479 *pbstrHelpString
=SysAllocString(This
->Name
);
5480 if(pdwHelpStringContext
)
5481 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5482 if(pbstrHelpStringDll
)
5483 *pbstrHelpStringDll
=
5484 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5486 }else {/* for a member */
5487 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5488 if(pFDesc
->funcdesc
.memid
==memid
){
5490 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5491 if(pdwHelpStringContext
)
5492 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5493 if(pbstrHelpStringDll
)
5494 *pbstrHelpStringDll
=
5495 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5498 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5499 if(pVDesc
->vardesc
.memid
==memid
){
5501 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5502 if(pdwHelpStringContext
)
5503 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5504 if(pbstrHelpStringDll
)
5505 *pbstrHelpStringDll
=
5506 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5510 return TYPE_E_ELEMENTNOTFOUND
;
5513 /* ITypeInfo2::GetAllCustData
5515 * Gets all custom data items for the Type info.
5518 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5520 CUSTDATA
*pCustData
)
5522 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5523 TLBCustData
*pCData
;
5526 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5528 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5529 if(pCustData
->prgCustData
){
5530 pCustData
->cCustData
=This
->ctCustData
;
5531 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5532 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5533 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5536 ERR(" OUT OF MEMORY! \n");
5537 return E_OUTOFMEMORY
;
5542 /* ITypeInfo2::GetAllFuncCustData
5544 * Gets all custom data items for the specified Function
5547 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5550 CUSTDATA
*pCustData
)
5552 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5553 TLBCustData
*pCData
;
5554 TLBFuncDesc
* pFDesc
;
5556 TRACE("(%p) index %d\n", This
, index
);
5557 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5558 pFDesc
=pFDesc
->next
)
5561 pCustData
->prgCustData
=
5562 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5563 if(pCustData
->prgCustData
){
5564 pCustData
->cCustData
=pFDesc
->ctCustData
;
5565 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5566 pCData
= pCData
->next
){
5567 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5568 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5572 ERR(" OUT OF MEMORY! \n");
5573 return E_OUTOFMEMORY
;
5577 return TYPE_E_ELEMENTNOTFOUND
;
5580 /* ITypeInfo2::GetAllParamCustData
5582 * Gets all custom data items for the Functions
5585 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5586 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5588 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5589 TLBCustData
*pCData
=NULL
;
5590 TLBFuncDesc
* pFDesc
;
5592 TRACE("(%p) index %d\n", This
, indexFunc
);
5593 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5594 pFDesc
=pFDesc
->next
)
5596 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5597 pCustData
->prgCustData
=
5598 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5599 sizeof(CUSTDATAITEM
));
5600 if(pCustData
->prgCustData
){
5601 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5602 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5603 pCData
; i
++, pCData
= pCData
->next
){
5604 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5605 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5609 ERR(" OUT OF MEMORY! \n");
5610 return E_OUTOFMEMORY
;
5614 return TYPE_E_ELEMENTNOTFOUND
;
5617 /* ITypeInfo2::GetAllVarCustData
5619 * Gets all custom data items for the specified Variable
5622 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5623 UINT index
, CUSTDATA
*pCustData
)
5625 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5626 TLBCustData
*pCData
;
5627 TLBVarDesc
* pVDesc
;
5629 TRACE("(%p) index %d\n", This
, index
);
5630 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5631 pVDesc
=pVDesc
->next
)
5634 pCustData
->prgCustData
=
5635 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5636 if(pCustData
->prgCustData
){
5637 pCustData
->cCustData
=pVDesc
->ctCustData
;
5638 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5639 pCData
= pCData
->next
){
5640 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5641 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5645 ERR(" OUT OF MEMORY! \n");
5646 return E_OUTOFMEMORY
;
5650 return TYPE_E_ELEMENTNOTFOUND
;
5653 /* ITypeInfo2::GetAllImplCustData
5655 * Gets all custom data items for the specified implementation type
5658 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5661 CUSTDATA
*pCustData
)
5663 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5664 TLBCustData
*pCData
;
5665 TLBImplType
* pRDesc
;
5667 TRACE("(%p) index %d\n", This
, index
);
5668 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5669 pRDesc
=pRDesc
->next
)
5672 pCustData
->prgCustData
=
5673 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5674 if(pCustData
->prgCustData
){
5675 pCustData
->cCustData
=pRDesc
->ctCustData
;
5676 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5677 pCData
= pCData
->next
){
5678 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5679 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5683 ERR(" OUT OF MEMORY! \n");
5684 return E_OUTOFMEMORY
;
5688 return TYPE_E_ELEMENTNOTFOUND
;
5691 static ITypeInfo2Vtbl tinfvt
=
5694 ITypeInfo_fnQueryInterface
,
5696 ITypeInfo_fnRelease
,
5698 ITypeInfo_fnGetTypeAttr
,
5699 ITypeInfo_fnGetTypeComp
,
5700 ITypeInfo_fnGetFuncDesc
,
5701 ITypeInfo_fnGetVarDesc
,
5702 ITypeInfo_fnGetNames
,
5703 ITypeInfo_fnGetRefTypeOfImplType
,
5704 ITypeInfo_fnGetImplTypeFlags
,
5705 ITypeInfo_fnGetIDsOfNames
,
5707 ITypeInfo_fnGetDocumentation
,
5708 ITypeInfo_fnGetDllEntry
,
5709 ITypeInfo_fnGetRefTypeInfo
,
5710 ITypeInfo_fnAddressOfMember
,
5711 ITypeInfo_fnCreateInstance
,
5712 ITypeInfo_fnGetMops
,
5713 ITypeInfo_fnGetContainingTypeLib
,
5714 ITypeInfo_fnReleaseTypeAttr
,
5715 ITypeInfo_fnReleaseFuncDesc
,
5716 ITypeInfo_fnReleaseVarDesc
,
5718 ITypeInfo2_fnGetTypeKind
,
5719 ITypeInfo2_fnGetTypeFlags
,
5720 ITypeInfo2_fnGetFuncIndexOfMemId
,
5721 ITypeInfo2_fnGetVarIndexOfMemId
,
5722 ITypeInfo2_fnGetCustData
,
5723 ITypeInfo2_fnGetFuncCustData
,
5724 ITypeInfo2_fnGetParamCustData
,
5725 ITypeInfo2_fnGetVarCustData
,
5726 ITypeInfo2_fnGetImplTypeCustData
,
5727 ITypeInfo2_fnGetDocumentation2
,
5728 ITypeInfo2_fnGetAllCustData
,
5729 ITypeInfo2_fnGetAllFuncCustData
,
5730 ITypeInfo2_fnGetAllParamCustData
,
5731 ITypeInfo2_fnGetAllVarCustData
,
5732 ITypeInfo2_fnGetAllImplTypeCustData
,
5735 /******************************************************************************
5736 * CreateDispTypeInfo [OLEAUT32.31]
5738 * Build type information for an object so it can be called through an
5739 * IDispatch interface.
5742 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5743 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5746 * This call allows an objects methods to be accessed through IDispatch, by
5747 * building an ITypeInfo object that IDispatch can use to call through.
5749 HRESULT WINAPI
CreateDispTypeInfo(
5750 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
5751 LCID lcid
, /* [I] Locale Id */
5752 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
5754 ITypeInfoImpl
*pTIImpl
;
5756 TLBFuncDesc
**ppFuncDesc
;
5758 pTIImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
5759 pTIImpl
->pTypeLib
= NULL
;
5761 pTIImpl
->Name
= NULL
;
5762 pTIImpl
->dwHelpContext
= -1;
5763 memset(&pTIImpl
->TypeAttr
.guid
, 0, sizeof(GUID
));
5764 pTIImpl
->TypeAttr
.lcid
= lcid
;
5765 pTIImpl
->TypeAttr
.typekind
= TKIND_COCLASS
;
5766 pTIImpl
->TypeAttr
.wMajorVerNum
= 0;
5767 pTIImpl
->TypeAttr
.wMinorVerNum
= 0;
5768 pTIImpl
->TypeAttr
.cbAlignment
= 2;
5769 pTIImpl
->TypeAttr
.cbSizeInstance
= -1;
5770 pTIImpl
->TypeAttr
.cbSizeVft
= -1;
5771 pTIImpl
->TypeAttr
.cFuncs
= 0;
5772 pTIImpl
->TypeAttr
.cImplTypes
= 1;
5773 pTIImpl
->TypeAttr
.cVars
= 0;
5774 pTIImpl
->TypeAttr
.wTypeFlags
= 0;
5776 ppFuncDesc
= &pTIImpl
->funclist
;
5777 for(func
= 0; func
< pidata
->cMembers
; func
++) {
5778 METHODDATA
*md
= pidata
->pmethdata
+ func
;
5779 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc
));
5780 (*ppFuncDesc
)->Name
= SysAllocString(md
->szName
);
5781 (*ppFuncDesc
)->funcdesc
.memid
= md
->dispid
;
5782 (*ppFuncDesc
)->funcdesc
.invkind
= md
->wFlags
;
5783 (*ppFuncDesc
)->funcdesc
.callconv
= md
->cc
;
5784 (*ppFuncDesc
)->funcdesc
.cParams
= md
->cArgs
;
5785 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= 0;
5786 (*ppFuncDesc
)->funcdesc
.oVft
= md
->iMeth
;
5787 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= 0; /*??*/
5788 (*ppFuncDesc
)->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
5789 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5790 md
->cArgs
* sizeof(ELEMDESC
));
5791 (*ppFuncDesc
)->pParamDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
5792 md
->cArgs
* sizeof(TLBParDesc
));
5793 for(param
= 0; param
< md
->cArgs
; param
++) {
5794 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
5795 (*ppFuncDesc
)->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
5797 ppFuncDesc
= &(*ppFuncDesc
)->next
;
5799 *pptinfo
= (ITypeInfo
*)pTIImpl
;
5804 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5806 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5808 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
5811 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
5813 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5815 return ITypeInfo_AddRef((ITypeInfo
*)This
);
5818 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
5820 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5822 return ITypeInfo_Release((ITypeInfo
*)This
);
5825 static HRESULT WINAPI
ITypeComp_fnBind(
5830 ITypeInfo
** ppTInfo
,
5831 DESCKIND
* pDescKind
,
5834 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5835 TLBFuncDesc
* pFDesc
;
5836 TLBVarDesc
* pVDesc
;
5838 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5840 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
5841 if (pFDesc
->funcdesc
.invkind
& wFlags
)
5842 if (!strcmpW(pFDesc
->Name
, szName
)) {
5848 *pDescKind
= DESCKIND_FUNCDESC
;
5849 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
5850 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5853 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
5855 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
5856 if (!strcmpW(pVDesc
->Name
, szName
)) {
5857 *pDescKind
= DESCKIND_VARDESC
;
5858 pBindPtr
->lpvardesc
= &pVDesc
->vardesc
;
5859 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5865 /* not found, look for it in inherited interfaces */
5866 if (This
->TypeAttr
.cImplTypes
&&
5867 (This
->TypeAttr
.typekind
== TKIND_INTERFACE
|| This
->TypeAttr
.typekind
== TKIND_DISPATCH
)) {
5868 /* recursive search */
5872 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
5875 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
5876 ITypeInfo_Release(pTInfo
);
5880 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5881 ITypeComp_Release(pTComp
);
5884 WARN("Could not search inherited interface!\n");
5886 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
5887 *pDescKind
= DESCKIND_NONE
;
5888 pBindPtr
->lpfuncdesc
= NULL
;
5890 return DISP_E_MEMBERNOTFOUND
;
5893 static HRESULT WINAPI
ITypeComp_fnBindType(
5897 ITypeInfo
** ppTInfo
,
5898 ITypeComp
** ppTComp
)
5900 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5902 /* strange behaviour (does nothing) but like the
5905 if (!ppTInfo
|| !ppTComp
)
5914 static ITypeCompVtbl tcompvt
=
5917 ITypeComp_fnQueryInterface
,
5919 ITypeComp_fnRelease
,
5922 ITypeComp_fnBindType