4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
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 * -. Most error return values are just guessed not checked with windows
46 * -. lousy fatal error handling
51 #include "wine/port.h"
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
71 #include "wine/unicode.h"
74 #include "wine/debug.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
93 WORD type_id
; /* Type identifier */
94 WORD count
; /* Number of resources of this type */
95 DWORD resloader
; /* SetResourceHandler() */
101 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
102 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
104 /****************************************************************************
107 * Takes p_iVal (which is in little endian) and returns it
108 * in the host machine's byte order.
110 #ifdef WORDS_BIGENDIAN
111 static WORD
FromLEWord(WORD p_iVal
)
113 return (((p_iVal
& 0x00FF) << 8) |
114 ((p_iVal
& 0xFF00) >> 8));
118 static DWORD
FromLEDWord(DWORD p_iVal
)
120 return (((p_iVal
& 0x000000FF) << 24) |
121 ((p_iVal
& 0x0000FF00) << 8) |
122 ((p_iVal
& 0x00FF0000) >> 8) |
123 ((p_iVal
& 0xFF000000) >> 24));
126 #define FromLEWord(X) (X)
127 #define FromLEDWord(X) (X)
130 #define DISPATCH_HREF_OFFSET 0x01000000
131 #define DISPATCH_HREF_MASK 0xff000000
133 /****************************************************************************
136 * Fix byte order in any structure if necessary
138 #ifdef WORDS_BIGENDIAN
139 static void FromLEWords(void *p_Val
, int p_iSize
)
143 p_iSize
/= sizeof(WORD
);
146 *Val
= FromLEWord(*Val
);
153 static void FromLEDWords(void *p_Val
, int p_iSize
)
157 p_iSize
/= sizeof(DWORD
);
160 *Val
= FromLEDWord(*Val
);
166 #define FromLEWords(X,Y) /*nothing*/
167 #define FromLEDWords(X,Y) /*nothing*/
171 * Find a typelib key which matches a requested maj.min version.
173 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
175 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
179 INT best_maj
= -1, best_min
= -1;
182 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
183 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
185 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
188 len
= sizeof(key_name
);
190 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
194 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
196 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
198 if (*wMaj
== 0xffff && *wMin
== 0xffff)
200 if (v_maj
> best_maj
) best_maj
= v_maj
;
201 if (v_min
> best_min
) best_min
= v_min
;
203 else if (*wMaj
== v_maj
)
210 break; /* exact match */
212 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
215 len
= sizeof(key_name
);
219 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
221 if (*wMaj
== 0xffff && *wMin
== 0xffff)
223 if (best_maj
>= 0 && best_min
>= 0)
231 if (*wMaj
== best_maj
&& best_min
>= 0)
239 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
240 /* buffer must be at least 60 characters long */
241 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
243 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
244 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
246 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
247 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
248 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
252 /* get the path of an interface key, in the form "Interface\\<guid>" */
253 /* buffer must be at least 50 characters long */
254 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
256 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
258 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
259 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
263 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
264 /* buffer must be at least 16 characters long */
265 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
267 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
268 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
269 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
270 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
272 sprintfW( buffer
, LcidFormatW
, lcid
);
275 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
276 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
277 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
279 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
285 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
288 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
289 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
290 SYSKIND syskind
, LCID lcid
, LPBSTR path
)
292 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
296 WCHAR Path
[MAX_PATH
];
299 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
301 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
302 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
304 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
305 if (res
== ERROR_FILE_NOT_FOUND
)
307 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
308 return TYPE_E_LIBNOTREGISTERED
;
310 else if (res
!= ERROR_SUCCESS
)
312 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
313 return TYPE_E_REGISTRYACCESS
;
318 LONG dwPathLen
= sizeof(Path
);
320 get_lcid_subkey( myLCID
, syskind
, buffer
);
322 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
326 else if (myLCID
== lcid
)
328 /* try with sub-langid */
329 myLCID
= SUBLANGID(lcid
);
331 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
333 /* try with system langid */
343 *path
= SysAllocString( Path
);
348 TRACE_(typelib
)("-- 0x%08x\n", hr
);
352 /****************************************************************************
353 * QueryPathOfRegTypeLib [OLEAUT32.164]
355 * Gets the path to a registered type library.
358 * guid [I] referenced guid
359 * wMaj [I] major version
360 * wMin [I] minor version
362 * path [O] path of typelib
366 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
367 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
370 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
373 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
);
377 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
);
380 /******************************************************************************
381 * CreateTypeLib [OLEAUT32.160] creates a typelib
387 HRESULT WINAPI
CreateTypeLib(
388 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
390 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
394 /******************************************************************************
395 * LoadTypeLib [OLEAUT32.161]
397 * Loads a type library
400 * szFile [I] Name of file to load from.
401 * pptLib [O] Pointer that receives ITypeLib object on success.
408 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
410 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
412 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
413 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
416 /******************************************************************************
417 * LoadTypeLibEx [OLEAUT32.183]
419 * Loads and optionally registers a type library
425 HRESULT WINAPI
LoadTypeLibEx(
426 LPCOLESTR szFile
, /* [in] Name of file to load from */
427 REGKIND regkind
, /* [in] Specify kind of registration */
428 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
430 WCHAR szPath
[MAX_PATH
+1];
433 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
437 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
442 case REGKIND_DEFAULT
:
443 /* don't register typelibs supplied with full path. Experimentation confirms the following */
444 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
445 (szFile
[0] && (szFile
[1] == ':'))) break;
446 /* else fall-through */
448 case REGKIND_REGISTER
:
449 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
451 ITypeLib_Release(*pptLib
);
459 TRACE(" returns %08x\n",res
);
463 /******************************************************************************
464 * LoadRegTypeLib [OLEAUT32.162]
466 * Loads a registered type library.
469 * rguid [I] GUID of the registered type library.
470 * wVerMajor [I] major version.
471 * wVerMinor [I] minor version.
472 * lcid [I] locale ID.
473 * ppTLib [O] pointer that receives an ITypeLib object on success.
477 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
480 HRESULT WINAPI
LoadRegTypeLib(
492 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
496 res
= LoadTypeLib(bstr
, ppTLib
);
500 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
506 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
507 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
508 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
509 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
510 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
511 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
513 /******************************************************************************
514 * RegisterTypeLib [OLEAUT32.163]
515 * Adds information about a type library to the System Registry
517 * Docs: ITypeLib FAR * ptlib
518 * Docs: OLECHAR FAR* szFullPath
519 * Docs: OLECHAR FAR* szHelpDir
525 HRESULT WINAPI
RegisterTypeLib(
526 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
527 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
528 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
531 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
532 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
533 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
543 if (ptlib
== NULL
|| szFullPath
== NULL
)
546 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
550 if (attr
->syskind
!= SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
552 if (attr
->syskind
!= SYS_WIN32
&& attr
->syskind
!= SYS_WIN16
) return TYPE_E_BADMODULEKIND
;
555 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
558 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
559 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
563 /* Set the human-readable name of the typelib */
564 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
568 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
569 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
575 /* Make up the name of the typelib path subkey */
576 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
578 /* Create the typelib path subkey */
579 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
580 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
582 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
583 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
591 /* Create the flags subkey */
592 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
593 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
595 /* FIXME: is %u correct? */
596 static const WCHAR formatW
[] = {'%','u',0};
598 sprintfW(buf
, formatW
, attr
->wLibFlags
);
599 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
600 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
608 /* create the helpdir subkey */
609 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
610 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
612 BOOL freeHelpDir
= FALSE
;
615 /* if we created a new key, and helpDir was null, set the helpdir
616 to the directory which contains the typelib. However,
617 if we just opened an existing key, we leave the helpdir alone */
618 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
619 szHelpDir
= SysAllocString(szFullPath
);
620 pIndexStr
= strrchrW(szHelpDir
, '\\');
627 /* if we have an szHelpDir, set it! */
628 if (szHelpDir
!= NULL
) {
629 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
630 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
636 if (freeHelpDir
) SysFreeString(szHelpDir
);
648 /* register OLE Automation-compatible interfaces for this typelib */
649 types
= ITypeLib_GetTypeInfoCount(ptlib
);
650 for (tidx
=0; tidx
<types
; tidx
++) {
651 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
652 LPOLESTR name
= NULL
;
653 ITypeInfo
*tinfo
= NULL
;
655 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
658 case TKIND_INTERFACE
:
659 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
660 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
664 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
665 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
669 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
674 TYPEATTR
*tattr
= NULL
;
675 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
678 TRACE_(typelib
)("guid=%s, flags=%04x (",
679 debugstr_guid(&tattr
->guid
),
682 if (TRACE_ON(typelib
)) {
683 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
703 /* Register all dispinterfaces (which includes dual interfaces) and
704 oleautomation interfaces */
705 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
706 kind
== TKIND_DISPATCH
)
708 /* register interface<->typelib coupling */
709 get_interface_key( &tattr
->guid
, keyName
);
710 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
711 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
714 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
715 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
717 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
718 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
719 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
720 (const BYTE
*)PSOA
, sizeof PSOA
);
724 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
725 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
726 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
727 (const BYTE
*)PSOA
, sizeof PSOA
);
731 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
732 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
735 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
736 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
738 StringFromGUID2(&attr
->guid
, buffer
, 40);
739 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
740 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
741 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
742 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
743 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
751 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
754 ITypeInfo_Release(tinfo
);
761 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
767 /******************************************************************************
768 * UnRegisterTypeLib [OLEAUT32.186]
769 * Removes information about a type library from the System Registry
776 HRESULT WINAPI
UnRegisterTypeLib(
777 REFGUID libid
, /* [in] Guid of the library */
778 WORD wVerMajor
, /* [in] major version */
779 WORD wVerMinor
, /* [in] minor version */
780 LCID lcid
, /* [in] locale id */
783 BSTR tlibPath
= NULL
;
786 WCHAR subKeyName
[50];
789 BOOL deleteOtherStuff
;
792 TYPEATTR
* typeAttr
= NULL
;
794 ITypeInfo
* typeInfo
= NULL
;
795 ITypeLib
* typeLib
= NULL
;
798 TRACE("(IID: %s)\n",debugstr_guid(libid
));
800 /* Create the path to the key */
801 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
803 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
805 TRACE("Unsupported syskind %i\n", syskind
);
806 result
= E_INVALIDARG
;
810 /* get the path to the typelib on disk */
811 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
) != S_OK
) {
812 result
= E_INVALIDARG
;
816 /* Try and open the key to the type library. */
817 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
818 result
= E_INVALIDARG
;
822 /* Try and load the type library */
823 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
824 result
= TYPE_E_INVALIDSTATE
;
828 /* remove any types registered with this typelib */
829 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
830 for (i
=0; i
<numTypes
; i
++) {
831 /* get the kind of type */
832 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
836 /* skip non-interfaces, and get type info for the type */
837 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
840 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
843 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
847 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
848 kind
== TKIND_DISPATCH
)
850 /* the path to the type */
851 get_interface_key( &typeAttr
->guid
, subKeyName
);
853 /* Delete its bits */
854 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
)
857 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
858 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
859 RegDeleteKeyW(subKey
, TypeLibW
);
862 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
866 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
868 if (typeInfo
) ITypeInfo_Release(typeInfo
);
872 /* Now, delete the type library path subkey */
873 get_lcid_subkey( lcid
, syskind
, subKeyName
);
874 RegDeleteKeyW(key
, subKeyName
);
875 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
876 RegDeleteKeyW(key
, subKeyName
);
878 /* check if there is anything besides the FLAGS/HELPDIR keys.
879 If there is, we don't delete them */
880 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
881 deleteOtherStuff
= TRUE
;
883 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
884 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
886 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
887 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
888 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
889 deleteOtherStuff
= FALSE
;
893 /* only delete the other parts of the key if we're absolutely sure */
894 if (deleteOtherStuff
) {
895 RegDeleteKeyW(key
, FLAGSW
);
896 RegDeleteKeyW(key
, HELPDIRW
);
900 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
901 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
902 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
906 SysFreeString(tlibPath
);
907 if (typeLib
) ITypeLib_Release(typeLib
);
908 if (subKey
) RegCloseKey(subKey
);
909 if (key
) RegCloseKey(key
);
913 /******************************************************************************
914 * RegisterTypeLibForUser [OLEAUT32.442]
915 * Adds information about a type library to the user registry
917 * Docs: ITypeLib FAR * ptlib
918 * Docs: OLECHAR FAR* szFullPath
919 * Docs: OLECHAR FAR* szHelpDir
925 HRESULT WINAPI
RegisterTypeLibForUser(
926 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
927 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
928 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
931 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
932 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
933 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
936 /******************************************************************************
937 * UnRegisterTypeLibForUser [OLEAUT32.443]
938 * Removes information about a type library from the user registry
944 HRESULT WINAPI
UnRegisterTypeLibForUser(
945 REFGUID libid
, /* [in] GUID of the library */
946 WORD wVerMajor
, /* [in] major version */
947 WORD wVerMinor
, /* [in] minor version */
948 LCID lcid
, /* [in] locale id */
951 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
952 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
953 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
956 /*======================= ITypeLib implementation =======================*/
958 typedef struct tagTLBCustData
965 /* data structure for import typelibs */
966 typedef struct tagTLBImpLib
968 int offset
; /* offset in the file (MSFT)
969 offset in nametable (SLTG)
970 just used to identify library while reading
972 GUID guid
; /* libid */
973 BSTR name
; /* name */
975 LCID lcid
; /* lcid of imported typelib */
977 WORD wVersionMajor
; /* major version number */
978 WORD wVersionMinor
; /* minor version number */
980 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
981 NULL if not yet loaded */
985 /* internal ITypeLib data */
986 typedef struct tagITypeLibImpl
988 ITypeLib2 ITypeLib2_iface
;
989 ITypeComp ITypeComp_iface
;
990 ICreateTypeLib2 ICreateTypeLib2_iface
;
992 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
995 /* strings can be stored in tlb as multibyte strings BUT they are *always*
996 * exported to the application as a UNICODE string.
1002 DWORD dwHelpContext
;
1003 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1004 struct tagITypeInfoImpl
**typeinfos
;
1005 struct list custdata_list
;
1006 struct list implib_list
;
1007 int ctTypeDesc
; /* number of items in type desc array */
1008 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1009 library. Only used while reading MSFT
1011 struct list ref_list
; /* list of ref types in this typelib */
1012 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1015 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1021 static const ITypeLib2Vtbl tlbvt
;
1022 static const ITypeCompVtbl tlbtcvt
;
1023 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1025 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1027 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1030 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1032 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1035 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1037 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1040 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1042 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1045 /* ITypeLib methods */
1046 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1047 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1049 /*======================= ITypeInfo implementation =======================*/
1051 /* data for referenced types */
1052 typedef struct tagTLBRefType
1054 INT index
; /* Type index for internal ref or for external ref
1055 it the format is SLTG. -2 indicates to
1058 GUID guid
; /* guid of the referenced type */
1059 /* if index == TLB_REF_USE_GUID */
1061 HREFTYPE reference
; /* The href of this ref */
1062 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1063 TLB_REF_INTERNAL for internal refs
1064 TLB_REF_NOT_FOUND for broken refs */
1069 #define TLB_REF_USE_GUID -2
1071 #define TLB_REF_INTERNAL (void*)-2
1072 #define TLB_REF_NOT_FOUND (void*)-1
1074 /* internal Parameter data */
1075 typedef struct tagTLBParDesc
1078 struct list custdata_list
;
1081 /* internal Function data */
1082 typedef struct tagTLBFuncDesc
1084 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1085 BSTR Name
; /* the name of this function */
1086 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1088 int HelpStringContext
;
1090 BSTR Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1091 struct list custdata_list
;
1094 /* internal Variable data */
1095 typedef struct tagTLBVarDesc
1097 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1098 BSTR Name
; /* the name of this variable */
1100 int HelpStringContext
;
1102 struct list custdata_list
;
1105 /* internal implemented interface data */
1106 typedef struct tagTLBImplType
1108 HREFTYPE hRef
; /* hRef of interface */
1109 int implflags
; /* IMPLFLAG_*s */
1110 struct list custdata_list
;
1113 /* internal TypeInfo data */
1114 typedef struct tagITypeInfoImpl
1116 ITypeInfo2 ITypeInfo2_iface
;
1117 ITypeComp ITypeComp_iface
;
1118 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1120 BOOL not_attached_to_typelib
;
1121 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1122 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1123 int index
; /* index in this typelib; */
1124 HREFTYPE hreftype
; /* hreftype for app object binding */
1125 /* type libs seem to store the doc strings in ascii
1126 * so why should we do it in unicode?
1131 DWORD dwHelpContext
;
1132 DWORD dwHelpStringContext
;
1135 TLBFuncDesc
*funcdescs
;
1138 TLBVarDesc
*vardescs
;
1140 /* Implemented Interfaces */
1141 TLBImplType
*impltypes
;
1143 struct list custdata_list
;
1146 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1148 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1151 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1153 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1156 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1158 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1161 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1163 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1166 static const ITypeInfo2Vtbl tinfvt
;
1167 static const ITypeCompVtbl tcompvt
;
1168 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1170 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1171 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1173 typedef struct tagTLBContext
1175 unsigned int oStart
; /* start of TLB in file */
1176 unsigned int pos
; /* current pos */
1177 unsigned int length
; /* total length */
1178 void *mapping
; /* memory mapping */
1179 MSFT_SegDir
* pTblDir
;
1180 ITypeLibImpl
* pLibInfo
;
1184 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1189 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1190 if (pTD
->vt
& VT_RESERVED
)
1191 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1192 if (pTD
->vt
& VT_BYREF
)
1193 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1194 if (pTD
->vt
& VT_ARRAY
)
1195 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1196 if (pTD
->vt
& VT_VECTOR
)
1197 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1198 switch(pTD
->vt
& VT_TYPEMASK
) {
1199 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1200 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1201 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1202 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1203 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1204 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1205 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1206 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1207 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1208 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1209 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1210 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1211 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1212 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1213 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1214 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1215 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1216 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1217 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1218 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1219 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1220 pTD
->u
.hreftype
); break;
1221 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1222 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1223 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1224 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1226 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1227 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1229 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1230 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1231 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1234 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1238 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1240 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1241 dump_TypeDesc(&edesc
->tdesc
,buf
);
1242 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1243 MESSAGE("\t\tu.paramdesc.wParamFlags");
1244 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1245 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1246 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1247 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1248 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1249 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1250 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1251 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1252 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1254 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1256 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1257 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1258 MESSAGE("Param %d:\n",i
);
1259 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1261 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1262 switch (funcdesc
->funckind
) {
1263 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1264 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1265 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1266 case FUNC_STATIC
: MESSAGE("static");break;
1267 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1268 default: MESSAGE("unknown");break;
1270 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1271 switch (funcdesc
->invkind
) {
1272 case INVOKE_FUNC
: MESSAGE("func");break;
1273 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1274 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1275 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1277 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1278 switch (funcdesc
->callconv
) {
1279 case CC_CDECL
: MESSAGE("cdecl");break;
1280 case CC_PASCAL
: MESSAGE("pascal");break;
1281 case CC_STDCALL
: MESSAGE("stdcall");break;
1282 case CC_SYSCALL
: MESSAGE("syscall");break;
1285 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1286 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1287 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1289 MESSAGE("\telemdescFunc (return value type):\n");
1290 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1293 static const char * const typekind_desc
[] =
1306 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1309 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1310 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1311 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1314 dump_FUNCDESC(&(pfd
->funcdesc
));
1316 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1317 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1319 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1323 dump_TLBFuncDescOne(pfd
);
1328 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1332 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1338 static void dump_TLBImpLib(const TLBImpLib
*import
)
1340 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1341 debugstr_w(import
->name
));
1342 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1343 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1346 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1350 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1352 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1353 if(ref
->index
== -1)
1354 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1356 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1358 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1360 TRACE_(typelib
)("in lib\n");
1361 dump_TLBImpLib(ref
->pImpTLInfo
);
1366 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1371 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1372 impl
->hRef
, impl
->implflags
);
1378 static void dump_Variant(const VARIANT
* pvar
)
1382 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1386 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1387 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1389 TRACE(",%p", V_BYREF(pvar
));
1391 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1393 TRACE(",%p", V_ARRAY(pvar
));
1395 else switch (V_TYPE(pvar
))
1397 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1398 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1399 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1400 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1402 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1404 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1405 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1406 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1407 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1408 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1409 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1410 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1411 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1412 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1413 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1414 V_CY(pvar
).s
.Lo
); break;
1416 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1417 TRACE(",<invalid>");
1419 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1420 st
.wHour
, st
.wMinute
, st
.wSecond
);
1424 case VT_USERDEFINED
:
1426 case VT_NULL
: break;
1427 default: TRACE(",?"); break;
1433 static void dump_DispParms(const DISPPARAMS
* pdp
)
1437 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1439 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1441 TRACE("named args:\n");
1442 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1443 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1446 if (pdp
->cArgs
&& pdp
->rgvarg
)
1449 for (index
= 0; index
< pdp
->cArgs
; index
++)
1450 dump_Variant( &pdp
->rgvarg
[index
] );
1454 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1456 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1457 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1458 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1459 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1460 TRACE("fct:%u var:%u impl:%u\n",
1461 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1462 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1463 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1464 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1466 dump_TLBFuncDesc(pty
->funcdescs
, pty
->TypeAttr
.cFuncs
);
1467 dump_TLBVarDesc(pty
->vardescs
, pty
->TypeAttr
.cVars
);
1468 dump_TLBImplType(pty
->impltypes
, pty
->TypeAttr
.cImplTypes
);
1471 static void dump_VARDESC(const VARDESC
*v
)
1473 MESSAGE("memid %d\n",v
->memid
);
1474 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1475 MESSAGE("oInst %d\n",v
->u
.oInst
);
1476 dump_ELEMDESC(&(v
->elemdescVar
));
1477 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1478 MESSAGE("varkind %d\n",v
->varkind
);
1481 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1483 /* VT_LPWSTR is largest type that, may appear in type description */
1484 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1485 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1486 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1487 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1488 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1489 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1490 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1491 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1494 static void TLB_abort(void)
1499 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1501 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1502 if (!ret
) ERR("cannot allocate memory\n");
1506 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1508 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1509 if (!ret
) ERR("cannot allocate memory\n");
1513 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1515 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1518 void heap_free(void *ptr
)
1520 HeapFree(GetProcessHeap(), 0, ptr
);
1523 /* returns the size required for a deep copy of a typedesc into a
1525 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1529 if (alloc_initial_space
)
1530 size
+= sizeof(TYPEDESC
);
1536 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1539 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1540 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1546 /* deep copy a typedesc into a flat buffer */
1547 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1552 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1561 dest
->u
.lptdesc
= buffer
;
1562 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1565 dest
->u
.lpadesc
= buffer
;
1566 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1567 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1568 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1574 /* free custom data allocated by MSFT_CustData */
1575 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1577 TLBCustData
*cd
, *cdn
;
1578 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1580 list_remove(&cd
->entry
);
1581 VariantClear(&cd
->data
);
1586 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1591 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1592 ret
= SysAllocStringLen(NULL
, len
- 1);
1593 if (!ret
) return ret
;
1594 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1598 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1599 UINT n
, MEMBERID memid
)
1602 if(funcdescs
->funcdesc
.memid
== memid
)
1610 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1611 UINT n
, const OLECHAR
*name
)
1614 if(!lstrcmpiW(funcdescs
->Name
, name
))
1622 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1623 UINT n
, MEMBERID memid
)
1626 if(vardescs
->vardesc
.memid
== memid
)
1634 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1635 UINT n
, const OLECHAR
*name
)
1638 if(!lstrcmpiW(vardescs
->Name
, name
))
1646 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1648 TLBCustData
*cust_data
;
1649 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1650 if(IsEqualIID(&cust_data
->guid
, guid
))
1655 static TLBVarDesc
*TLBVarDesc_Constructor(UINT n
)
1659 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1664 list_init(&ret
[n
-1].custdata_list
);
1671 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1675 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1680 list_init(&ret
[n
-1].custdata_list
);
1687 static TLBFuncDesc
*TLBFuncDesc_Constructor(UINT n
)
1691 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1696 list_init(&ret
[n
-1].custdata_list
);
1703 static TLBImplType
*TLBImplType_Constructor(UINT n
)
1707 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1712 list_init(&ret
[n
-1].custdata_list
);
1719 /**********************************************************************
1721 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1723 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1728 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
1730 if (where
!= DO_NOT_SEEK
)
1732 where
+= pcx
->oStart
;
1733 if (where
> pcx
->length
)
1736 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
1744 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
1746 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1747 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1749 MSFT_Seek(pcx
, where
);
1750 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1751 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1756 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1761 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1762 FromLEDWords(buffer
, ret
);
1767 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1772 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1773 FromLEWords(buffer
, ret
);
1778 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1780 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1781 memset(pGuid
,0, sizeof(GUID
));
1784 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1785 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1786 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1787 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1788 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1791 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1793 MSFT_NameIntro niName
;
1797 ERR_(typelib
)("bad offset %d\n", offset
);
1801 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1802 pcx
->pTblDir
->pNametab
.offset
+offset
);
1804 return niName
.hreftype
;
1807 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1810 MSFT_NameIntro niName
;
1812 BSTR bstrName
= NULL
;
1816 ERR_(typelib
)("bad offset %d\n", offset
);
1819 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1820 pcx
->pTblDir
->pNametab
.offset
+offset
);
1821 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1822 name
= heap_alloc_zero((niName
.namelen
& 0xff) +1);
1823 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1824 name
[niName
.namelen
& 0xff]='\0';
1826 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1829 /* no invalid characters in string */
1832 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1834 /* don't check for invalid character since this has been done previously */
1835 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1839 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1843 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1850 if(offset
<0) return NULL
;
1851 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1852 if(length
<= 0) return 0;
1853 string
= heap_alloc_zero(length
+1);
1854 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1855 string
[length
]='\0';
1857 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1858 string
, -1, NULL
, 0);
1860 /* no invalid characters in string */
1863 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1865 /* don't check for invalid character since this has been done previously */
1866 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1870 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1874 * read a value and fill a VARIANT structure
1876 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1880 TRACE_(typelib
)("\n");
1882 if(offset
<0) { /* data are packed in here */
1883 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1884 V_I4(pVar
) = offset
& 0x3ffffff;
1887 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1888 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1889 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1890 switch (V_VT(pVar
)){
1891 case VT_EMPTY
: /* FIXME: is this right? */
1892 case VT_NULL
: /* FIXME: is this right? */
1893 case VT_I2
: /* this should not happen */
1904 case VT_VOID
: /* FIXME: is this right? */
1912 case VT_DECIMAL
: /* FIXME: is this right? */
1915 /* pointer types with known behaviour */
1918 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1921 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1924 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1926 nullPos
= MSFT_Tell(pcx
);
1927 size
= nullPos
- origPos
;
1928 MSFT_Seek(pcx
, origPos
);
1930 ptr
= heap_alloc_zero(size
);/* allocate temp buffer */
1931 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1932 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1933 /* FIXME: do we need a AtoW conversion here? */
1934 V_UNION(pVar
, bstrVal
[size
])='\0';
1935 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1939 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1946 case VT_USERDEFINED
:
1952 case VT_STREAMED_OBJECT
:
1953 case VT_STORED_OBJECT
:
1954 case VT_BLOB_OBJECT
:
1959 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1963 if(size
>0) /* (big|small) endian correct? */
1964 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1968 * create a linked list with custom data
1970 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
1976 TRACE_(typelib
)("\n");
1978 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
1982 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
1983 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1984 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1985 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1986 list_add_head(custdata_list
, &pNew
->entry
);
1987 offset
= entry
.next
;
1992 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1996 pTd
->vt
=type
& VT_TYPEMASK
;
1998 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2000 if(pTd
->vt
== VT_USERDEFINED
)
2001 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
2003 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2006 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
2008 /* resolve referenced type if any */
2011 switch (lpTypeDesc
->vt
)
2014 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
2018 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
2021 case VT_USERDEFINED
:
2022 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
2023 lpTypeDesc
->u
.hreftype
);
2035 MSFT_DoFuncs(TLBContext
* pcx
,
2040 TLBFuncDesc
** pptfd
)
2043 * member information is stored in a data structure at offset
2044 * indicated by the memoffset field of the typeinfo structure
2045 * There are several distinctive parts.
2046 * The first part starts with a field that holds the total length
2047 * of this (first) part excluding this field. Then follow the records,
2048 * for each member there is one record.
2050 * The first entry is always the length of the record (including this
2052 * The rest of the record depends on the type of the member. If there is
2053 * a field indicating the member type (function, variable, interface, etc)
2054 * I have not found it yet. At this time we depend on the information
2055 * in the type info and the usual order how things are stored.
2057 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2060 * Third is an equal sized array with file offsets to the name entry
2063 * The fourth and last (?) part is an array with offsets to the records
2064 * in the first part of this file segment.
2067 int infolen
, nameoffset
, reclength
, i
;
2068 int recoffset
= offset
+ sizeof(INT
);
2070 char *recbuf
= heap_alloc(0xffff);
2071 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2072 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2074 TRACE_(typelib
)("\n");
2076 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2078 *pptfd
= TLBFuncDesc_Constructor(cFuncs
);
2080 for ( i
= 0; i
< cFuncs
; i
++ )
2084 /* name, eventually add to a hash table */
2085 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2086 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2088 /* nameoffset is sometimes -1 on the second half of a propget/propput
2089 * pair of functions */
2090 if ((nameoffset
== -1) && (i
> 0))
2091 ptfd
->Name
= SysAllocString(ptfd_prev
->Name
);
2093 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2095 /* read the function information record */
2096 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2098 reclength
&= 0xffff;
2100 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2102 /* size without argument data */
2103 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2105 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2106 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2108 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2109 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2111 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2113 if (pFuncRec
->FKCCIC
& 0x2000 )
2115 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2116 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2117 ptfd
->Entry
= (BSTR
)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2120 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2123 ptfd
->Entry
= (BSTR
)-1;
2125 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2126 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2128 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2129 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2131 /* fill the FuncDesc Structure */
2132 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2133 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2135 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2136 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2137 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2138 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2139 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2140 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2141 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2145 &ptfd
->funcdesc
.elemdescFunc
.tdesc
,
2147 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2149 /* do the parameters/arguments */
2150 if(pFuncRec
->nrargs
)
2153 MSFT_ParameterInfo paraminfo
;
2155 ptfd
->funcdesc
.lprgelemdescParam
=
2156 heap_alloc_zero(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
2158 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2160 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2161 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2163 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2165 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2172 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2175 if (paraminfo
.oName
== -1)
2176 /* this occurs for [propput] or [propget] methods, so
2177 * we should just set the name of the parameter to the
2178 * name of the method. */
2179 ptfd
->pParamDesc
[j
].Name
= SysAllocString(ptfd
->Name
);
2181 ptfd
->pParamDesc
[j
].Name
=
2182 MSFT_ReadName( pcx
, paraminfo
.oName
);
2183 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(ptfd
->pParamDesc
[j
].Name
));
2185 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
2188 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2189 (pFuncRec
->FKCCIC
& 0x1000) )
2191 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2193 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2195 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2197 pParamDesc
->pparamdescex
= heap_alloc_zero(sizeof(PARAMDESCEX
));
2198 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2200 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2204 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2207 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2208 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2209 pFuncRec
->FKCCIC
& 0x80 )
2212 pFuncRec
->oArgCustData
[j
],
2213 &ptfd
->pParamDesc
[j
].custdata_list
);
2216 /* SEEK value = jump to offset,
2217 * from there jump to the end of record,
2218 * go back by (j-1) arguments
2220 MSFT_ReadLEDWords( ¶minfo
,
2221 sizeof(MSFT_ParameterInfo
), pcx
,
2222 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2223 * sizeof(MSFT_ParameterInfo
)));
2227 /* scode is not used: archaic win16 stuff FIXME: right? */
2228 ptfd
->funcdesc
.cScodes
= 0 ;
2229 ptfd
->funcdesc
.lprgscode
= NULL
;
2233 recoffset
+= reclength
;
2238 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2239 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2241 int infolen
, nameoffset
, reclength
;
2243 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2248 TRACE_(typelib
)("\n");
2250 ptvd
= *pptvd
= TLBVarDesc_Constructor(cVars
);
2251 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2252 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2253 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2254 recoffset
+= offset
+sizeof(INT
);
2255 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2256 /* name, eventually add to a hash table */
2257 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2258 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2259 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2260 /* read the variable information record */
2261 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2263 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2266 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2267 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2269 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2270 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2272 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2273 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2275 /* fill the VarDesc Structure */
2276 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2277 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2278 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2279 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2280 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2281 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2282 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2283 if(pVarRec
->VarKind
== VAR_CONST
){
2284 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2285 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2286 pVarRec
->OffsValue
, pcx
);
2288 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2289 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptvd
->vardesc
.elemdescVar
.tdesc
);
2290 recoffset
+= reclength
;
2294 /* fill in data for a hreftype (offset). When the referenced type is contained
2295 * in the typelib, it's just an (file) offset in the type info base dir.
2296 * If comes from import, it's an offset+1 in the ImpInfo table
2298 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2303 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2305 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2307 if(ref
->reference
== offset
) return;
2310 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2311 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2313 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2314 /* external typelib */
2315 MSFT_ImpInfo impinfo
;
2318 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2320 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2321 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2323 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2324 if(pImpLib
->offset
==impinfo
.oImpFile
)
2327 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2328 ref
->reference
= offset
;
2329 ref
->pImpTLInfo
= pImpLib
;
2330 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2331 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2332 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2333 ref
->index
= TLB_REF_USE_GUID
;
2335 ref
->index
= impinfo
.oGuid
;
2337 ERR("Cannot find a reference\n");
2338 ref
->reference
= -1;
2339 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2342 /* in this typelib */
2343 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2344 ref
->reference
= offset
;
2345 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2349 /* process Implemented Interfaces of a com class */
2350 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2354 MSFT_RefRecord refrec
;
2357 TRACE_(typelib
)("\n");
2359 pTI
->impltypes
= TLBImplType_Constructor(count
);
2360 pImpl
= pTI
->impltypes
;
2361 for(i
=0;i
<count
;i
++){
2362 if(offset
<0) break; /* paranoia */
2363 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2364 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2365 pImpl
->hRef
= refrec
.reftype
;
2366 pImpl
->implflags
=refrec
.flags
;
2367 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2368 offset
=refrec
.onext
;
2373 * process a typeinfo record
2375 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2378 ITypeLibImpl
* pLibInfo
)
2380 MSFT_TypeInfoBase tiBase
;
2381 ITypeInfoImpl
*ptiRet
;
2383 TRACE_(typelib
)("count=%u\n", count
);
2385 ptiRet
= ITypeInfoImpl_Constructor();
2386 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2387 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2389 /* this is where we are coming from */
2390 ptiRet
->pTypeLib
= pLibInfo
;
2391 ptiRet
->index
=count
;
2392 /* fill in the typeattr fields */
2394 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2395 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2396 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2397 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2398 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2399 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2400 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2401 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2402 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2403 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2404 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2405 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2406 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2407 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2408 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2409 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2412 /* IDLDESC idldescType; *//* never saw this one != zero */
2414 /* name, eventually add to a hash table */
2415 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2416 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2417 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2419 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2420 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2421 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2423 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2424 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2426 /* note: InfoType's Help file and HelpStringDll come from the containing
2427 * library. Further HelpString and Docstring appear to be the same thing :(
2430 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2431 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2432 ptiRet
->TypeAttr
.cVars
,
2433 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2435 if(ptiRet
->TypeAttr
.cVars
>0 )
2436 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2437 ptiRet
->TypeAttr
.cVars
,
2438 tiBase
.memoffset
, &ptiRet
->vardescs
);
2439 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2440 switch(ptiRet
->TypeAttr
.typekind
)
2443 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2446 case TKIND_DISPATCH
:
2447 /* This is not -1 when the interface is a non-base dual interface or
2448 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2449 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2453 if (tiBase
.datatype1
!= -1)
2455 ptiRet
->impltypes
= TLBImplType_Constructor(1);
2456 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2457 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2461 ptiRet
->impltypes
= TLBImplType_Constructor(1);
2462 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2463 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2467 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->custdata_list
);
2469 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2470 debugstr_w(ptiRet
->Name
),
2471 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2472 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2473 if (TRACE_ON(typelib
))
2474 dump_TypeInfo(ptiRet
);
2479 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2480 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2481 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2484 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2485 static CRITICAL_SECTION cache_section
;
2486 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2488 0, 0, &cache_section
,
2489 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2490 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2492 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2495 typedef struct TLB_PEFile
2497 IUnknown IUnknown_iface
;
2500 HRSRC typelib_resource
;
2501 HGLOBAL typelib_global
;
2502 LPVOID typelib_base
;
2505 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2507 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2510 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2512 if (IsEqualIID(riid
, &IID_IUnknown
))
2515 IUnknown_AddRef(iface
);
2519 return E_NOINTERFACE
;
2522 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2524 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2525 return InterlockedIncrement(&This
->refs
);
2528 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2530 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2531 ULONG refs
= InterlockedDecrement(&This
->refs
);
2534 if (This
->typelib_global
)
2535 FreeResource(This
->typelib_global
);
2537 FreeLibrary(This
->dll
);
2543 static const IUnknownVtbl TLB_PEFile_Vtable
=
2545 TLB_PEFile_QueryInterface
,
2550 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2553 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2555 This
= heap_alloc(sizeof(TLB_PEFile
));
2557 return E_OUTOFMEMORY
;
2559 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2562 This
->typelib_resource
= NULL
;
2563 This
->typelib_global
= NULL
;
2564 This
->typelib_base
= NULL
;
2566 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2567 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2571 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2572 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2573 if (This
->typelib_resource
)
2575 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2576 if (This
->typelib_global
)
2578 This
->typelib_base
= LockResource(This
->typelib_global
);
2580 if (This
->typelib_base
)
2582 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2583 *ppBase
= This
->typelib_base
;
2584 *ppFile
= &This
->IUnknown_iface
;
2590 TRACE("No TYPELIB resource found\n");
2594 TLB_PEFile_Release(&This
->IUnknown_iface
);
2598 typedef struct TLB_NEFile
2600 IUnknown IUnknown_iface
;
2602 LPVOID typelib_base
;
2605 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2607 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2610 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2612 if (IsEqualIID(riid
, &IID_IUnknown
))
2615 IUnknown_AddRef(iface
);
2619 return E_NOINTERFACE
;
2622 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2624 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2625 return InterlockedIncrement(&This
->refs
);
2628 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2630 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2631 ULONG refs
= InterlockedDecrement(&This
->refs
);
2634 heap_free(This
->typelib_base
);
2640 static const IUnknownVtbl TLB_NEFile_Vtable
=
2642 TLB_NEFile_QueryInterface
,
2647 /***********************************************************************
2648 * read_xx_header [internal]
2650 static int read_xx_header( HFILE lzfd
)
2652 IMAGE_DOS_HEADER mzh
;
2655 LZSeek( lzfd
, 0, SEEK_SET
);
2656 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2658 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2661 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2662 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2665 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2667 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2668 return IMAGE_OS2_SIGNATURE
;
2669 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2670 return IMAGE_NT_SIGNATURE
;
2673 WARN("Can't handle %s files.\n", magic
);
2678 /***********************************************************************
2679 * find_ne_resource [internal]
2681 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2682 DWORD
*resLen
, DWORD
*resOff
)
2684 IMAGE_OS2_HEADER nehd
;
2685 NE_TYPEINFO
*typeInfo
;
2686 NE_NAMEINFO
*nameInfo
;
2692 /* Read in NE header */
2693 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2694 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2696 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2699 TRACE("No resources in NE dll\n" );
2703 /* Read in resource table */
2704 resTab
= heap_alloc( resTabSize
);
2705 if ( !resTab
) return FALSE
;
2707 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2708 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2710 heap_free( resTab
);
2715 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2717 if (!IS_INTRESOURCE(typeid)) /* named type */
2719 BYTE len
= strlen( typeid );
2720 while (typeInfo
->type_id
)
2722 if (!(typeInfo
->type_id
& 0x8000))
2724 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2725 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2727 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2728 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2731 else /* numeric type id */
2733 WORD id
= LOWORD(typeid) | 0x8000;
2734 while (typeInfo
->type_id
)
2736 if (typeInfo
->type_id
== id
) goto found_type
;
2737 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2738 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2741 TRACE("No typeid entry found for %p\n", typeid );
2742 heap_free( resTab
);
2746 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2748 if (!IS_INTRESOURCE(resid
)) /* named resource */
2750 BYTE len
= strlen( resid
);
2751 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2753 BYTE
*p
= resTab
+ nameInfo
->id
;
2754 if (nameInfo
->id
& 0x8000) continue;
2755 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2758 else /* numeric resource id */
2760 WORD id
= LOWORD(resid
) | 0x8000;
2761 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2762 if (nameInfo
->id
== id
) goto found_name
;
2764 TRACE("No resid entry found for %p\n", typeid );
2765 heap_free( resTab
);
2769 /* Return resource data */
2770 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2771 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2773 heap_free( resTab
);
2777 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
2781 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2784 This
= heap_alloc(sizeof(TLB_NEFile
));
2785 if (!This
) return E_OUTOFMEMORY
;
2787 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
2789 This
->typelib_base
= NULL
;
2791 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
2792 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
2794 DWORD reslen
, offset
;
2795 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
2797 This
->typelib_base
= heap_alloc(reslen
);
2798 if( !This
->typelib_base
)
2802 LZSeek( lzfd
, offset
, SEEK_SET
);
2803 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
2805 *ppBase
= This
->typelib_base
;
2806 *pdwTLBLength
= reslen
;
2807 *ppFile
= &This
->IUnknown_iface
;
2813 if( lzfd
>= 0) LZClose( lzfd
);
2814 TLB_NEFile_Release(&This
->IUnknown_iface
);
2818 typedef struct TLB_Mapping
2820 IUnknown IUnknown_iface
;
2824 LPVOID typelib_base
;
2827 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
2829 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
2832 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2834 if (IsEqualIID(riid
, &IID_IUnknown
))
2837 IUnknown_AddRef(iface
);
2841 return E_NOINTERFACE
;
2844 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
2846 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
2847 return InterlockedIncrement(&This
->refs
);
2850 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
2852 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
2853 ULONG refs
= InterlockedDecrement(&This
->refs
);
2856 if (This
->typelib_base
)
2857 UnmapViewOfFile(This
->typelib_base
);
2859 CloseHandle(This
->mapping
);
2860 if (This
->file
!= INVALID_HANDLE_VALUE
)
2861 CloseHandle(This
->file
);
2867 static const IUnknownVtbl TLB_Mapping_Vtable
=
2869 TLB_Mapping_QueryInterface
,
2874 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2878 This
= heap_alloc(sizeof(TLB_Mapping
));
2880 return E_OUTOFMEMORY
;
2882 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
2884 This
->file
= INVALID_HANDLE_VALUE
;
2885 This
->mapping
= NULL
;
2886 This
->typelib_base
= NULL
;
2888 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
2889 if (INVALID_HANDLE_VALUE
!= This
->file
)
2891 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2894 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
2895 if(This
->typelib_base
)
2897 /* retrieve file size */
2898 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
2899 *ppBase
= This
->typelib_base
;
2900 *ppFile
= &This
->IUnknown_iface
;
2906 IUnknown_Release(&This
->IUnknown_iface
);
2907 return TYPE_E_CANTLOADLIBRARY
;
2910 /****************************************************************************
2913 * find the type of the typelib file and map the typelib resource into
2917 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2918 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2920 ITypeLibImpl
*entry
;
2923 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2924 LPVOID pBase
= NULL
;
2925 DWORD dwTLBLength
= 0;
2926 IUnknown
*pFile
= NULL
;
2930 index_str
= strrchrW(pszFileName
, '\\');
2931 if(index_str
&& *++index_str
!= '\0')
2934 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
2935 if(*end_ptr
== '\0')
2937 int str_len
= index_str
- pszFileName
- 1;
2939 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
2940 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2945 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2947 if(strchrW(file
, '\\'))
2949 lstrcpyW(pszPath
, file
);
2953 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2954 pszPath
[len
] = '\\';
2955 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2959 if(file
!= pszFileName
) heap_free(file
);
2961 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2963 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2964 EnterCriticalSection(&cache_section
);
2965 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
2967 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2969 TRACE("cache hit\n");
2970 *ppTypeLib
= &entry
->ITypeLib2_iface
;
2971 ITypeLib2_AddRef(*ppTypeLib
);
2972 LeaveCriticalSection(&cache_section
);
2976 LeaveCriticalSection(&cache_section
);
2978 /* now actually load and parse the typelib */
2980 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2981 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2982 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2983 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2984 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
2987 if (dwTLBLength
>= 4)
2989 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2990 if (dwSignature
== MSFT_SIGNATURE
)
2991 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2992 else if (dwSignature
== SLTG_SIGNATURE
)
2993 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2996 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2997 ret
= TYPE_E_CANTLOADLIBRARY
;
3001 ret
= TYPE_E_CANTLOADLIBRARY
;
3002 IUnknown_Release(pFile
);
3006 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3008 TRACE("adding to cache\n");
3009 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3010 lstrcpyW(impl
->path
, pszPath
);
3011 /* We should really canonicalise the path here. */
3012 impl
->index
= index
;
3014 /* FIXME: check if it has added already in the meantime */
3015 EnterCriticalSection(&cache_section
);
3016 list_add_head(&tlb_cache
, &impl
->entry
);
3017 LeaveCriticalSection(&cache_section
);
3023 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3025 ret
= TYPE_E_CANTLOADLIBRARY
;
3032 /*================== ITypeLib(2) Methods ===================================*/
3034 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3036 ITypeLibImpl
* pTypeLibImpl
;
3038 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3039 if (!pTypeLibImpl
) return NULL
;
3041 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3042 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3043 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3044 pTypeLibImpl
->ref
= 1;
3046 list_init(&pTypeLibImpl
->implib_list
);
3047 list_init(&pTypeLibImpl
->custdata_list
);
3048 list_init(&pTypeLibImpl
->ref_list
);
3049 pTypeLibImpl
->dispatch_href
= -1;
3051 return pTypeLibImpl
;
3054 /****************************************************************************
3055 * ITypeLib2_Constructor_MSFT
3057 * loading an MSFT typelib from an in-memory image
3059 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3063 MSFT_Header tlbHeader
;
3064 MSFT_SegDir tlbSegDir
;
3065 ITypeLibImpl
* pTypeLibImpl
;
3067 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3069 pTypeLibImpl
= TypeLibImpl_Constructor();
3070 if (!pTypeLibImpl
) return NULL
;
3072 /* get pointer to beginning of typelib data */
3076 cx
.pLibInfo
= pTypeLibImpl
;
3077 cx
.length
= dwTLBLength
;
3080 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3081 TRACE_(typelib
)("header:\n");
3082 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3083 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3084 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3087 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3089 /* there is a small amount of information here until the next important
3091 * the segment directory . Try to calculate the amount of data */
3092 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3094 /* now read the segment directory */
3095 TRACE("read segment directory (at %d)\n",lPSegDir
);
3096 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3097 cx
.pTblDir
= &tlbSegDir
;
3099 /* just check two entries */
3100 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3102 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3103 heap_free(pTypeLibImpl
);
3107 /* now fill our internal data */
3108 /* TLIBATTR fields */
3109 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
3111 pTypeLibImpl
->LibAttr
.lcid
= tlbHeader
.lcid2
;
3112 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3113 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
3114 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
3115 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3117 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3119 /* name, eventually add to a hash table */
3120 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3123 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3124 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3126 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3129 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3130 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3133 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3136 if(tlbHeader
.CustomDataOffset
>= 0)
3138 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3141 /* fill in type descriptions */
3142 if(tlbSegDir
.pTypdescTab
.length
> 0)
3144 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3146 pTypeLibImpl
->ctTypeDesc
= cTD
;
3147 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3148 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3151 /* FIXME: add several sanity checks here */
3152 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3153 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3155 /* FIXME: check safearray */
3157 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3159 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3161 else if(td
[0] == VT_CARRAY
)
3163 /* array descr table here */
3164 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3166 else if(td
[0] == VT_USERDEFINED
)
3168 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3170 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3173 /* second time around to fill the array subscript info */
3176 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3177 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3179 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3180 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3183 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3185 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3187 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3189 for(j
= 0; j
<td
[2]; j
++)
3191 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3192 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3193 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3194 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3199 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3200 ERR("didn't find array description data\n");
3205 /* imported type libs */
3206 if(tlbSegDir
.pImpFiles
.offset
>0)
3209 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3212 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3216 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3217 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3218 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3220 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3221 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3222 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3223 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3226 name
= heap_alloc_zero(size
+1);
3227 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3228 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3231 MSFT_ReadGuid(&pImpLib
->guid
, oGuid
, &cx
);
3232 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3234 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3238 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3239 if(pTypeLibImpl
->dispatch_href
!= -1)
3240 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3243 if(tlbHeader
.nrtypeinfos
>= 0 )
3245 ITypeInfoImpl
**ppTI
;
3248 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3250 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3252 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3255 (pTypeLibImpl
->TypeInfoCount
)++;
3259 TRACE("(%p)\n", pTypeLibImpl
);
3260 return &pTypeLibImpl
->ITypeLib2_iface
;
3264 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3270 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3271 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3275 guid
->Data4
[0] = s
>> 8;
3276 guid
->Data4
[1] = s
& 0xff;
3279 for(i
= 0; i
< 6; i
++) {
3280 memcpy(b
, str
+ 24 + 2 * i
, 2);
3281 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3286 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
3292 bytelen
= *(const WORD
*)ptr
;
3293 if(bytelen
== 0xffff) return 2;
3294 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3295 *pBstr
= SysAllocStringLen(NULL
, len
);
3297 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, *pBstr
, len
);
3301 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3306 bytelen
= *(const WORD
*)ptr
;
3307 if(bytelen
== 0xffff) return 2;
3308 *str
= heap_alloc(bytelen
+ 1);
3309 memcpy(*str
, ptr
+ 2, bytelen
);
3310 (*str
)[bytelen
] = '\0';
3314 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3316 char *ptr
= pLibBlk
;
3319 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3320 FIXME("libblk magic = %04x\n", w
);
3325 if((w
= *(WORD
*)ptr
) != 0xffff) {
3326 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3331 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
3333 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
3335 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3338 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
3341 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3342 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3344 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= 0;
3347 ptr
+= 4; /* skip res12 */
3349 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
3352 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
3355 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
3358 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
3359 ptr
+= sizeof(GUID
);
3361 return ptr
- (char*)pLibBlk
;
3364 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3369 } sltg_ref_lookup_t
;
3371 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3372 HREFTYPE
*typelib_ref
)
3374 if(table
&& typeinfo_ref
< table
->num
)
3376 *typelib_ref
= table
->refs
[typeinfo_ref
];
3380 ERR_(typelib
)("Unable to find reference\n");
3385 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3390 if((*pType
& 0xe00) == 0xe00) {
3392 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3393 pTD
= pTD
->u
.lptdesc
;
3395 switch(*pType
& 0x3f) {
3398 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3399 pTD
= pTD
->u
.lptdesc
;
3402 case VT_USERDEFINED
:
3403 pTD
->vt
= VT_USERDEFINED
;
3404 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3410 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3413 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3415 pTD
->vt
= VT_CARRAY
;
3416 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3417 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3418 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3419 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3421 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3427 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3431 pTD
->vt
= VT_SAFEARRAY
;
3432 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3433 pTD
= pTD
->u
.lptdesc
;
3437 pTD
->vt
= *pType
& 0x3f;
3446 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3447 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3449 /* Handle [in/out] first */
3450 if((*pType
& 0xc000) == 0xc000)
3451 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3452 else if(*pType
& 0x8000)
3453 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3454 else if(*pType
& 0x4000)
3455 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3457 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3460 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3463 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3465 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3469 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3474 TLBRefType
*ref_type
;
3475 sltg_ref_lookup_t
*table
;
3476 HREFTYPE typelib_ref
;
3478 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3479 FIXME("Ref magic = %x\n", pRef
->magic
);
3482 name
= ( (char*)pRef
->names
+ pRef
->number
);
3484 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3485 table
->num
= pRef
->number
>> 3;
3487 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3489 /* We don't want the first href to be 0 */
3490 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3492 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3494 unsigned int lib_offs
, type_num
;
3496 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3498 name
+= SLTG_ReadStringA(name
, &refname
);
3499 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3500 FIXME_(typelib
)("Can't sscanf ref\n");
3501 if(lib_offs
!= 0xffff) {
3504 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3505 if(import
->offset
== lib_offs
)
3508 if(&import
->entry
== &pTL
->implib_list
) {
3509 char fname
[MAX_PATH
+1];
3512 import
= heap_alloc_zero(sizeof(*import
));
3513 import
->offset
= lib_offs
;
3514 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3516 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3517 &import
->wVersionMajor
,
3518 &import
->wVersionMinor
,
3519 &import
->lcid
, fname
) != 4) {
3520 FIXME_(typelib
)("can't sscanf ref %s\n",
3521 pNameTable
+ lib_offs
+ 40);
3523 len
= strlen(fname
);
3524 if(fname
[len
-1] != '#')
3525 FIXME("fname = %s\n", fname
);
3526 fname
[len
-1] = '\0';
3527 import
->name
= TLB_MultiByteToBSTR(fname
);
3528 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3530 ref_type
->pImpTLInfo
= import
;
3532 /* Store a reference to IDispatch */
3533 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
, &IID_StdOle
) && type_num
== 4)
3534 pTL
->dispatch_href
= typelib_ref
;
3536 } else { /* internal ref */
3537 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3539 ref_type
->reference
= typelib_ref
;
3540 ref_type
->index
= type_num
;
3543 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3545 table
->refs
[ref
] = typelib_ref
;
3548 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3549 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3550 dump_TLBRefType(pTL
);
3554 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3555 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3557 SLTG_ImplInfo
*info
;
3558 TLBImplType
*pImplType
;
3559 /* I don't really get this structure, usually it's 0x16 bytes
3560 long, but iuser.tlb contains some that are 0x18 bytes long.
3561 That's ok because we can use the next ptr to jump to the next
3562 one. But how do we know the length of the last one? The WORD
3563 at offs 0x8 might be the clue. For now I'm just assuming that
3564 the last one is the regular 0x16 bytes. */
3566 info
= (SLTG_ImplInfo
*)pBlk
;
3568 pTI
->TypeAttr
.cImplTypes
++;
3569 if(info
->next
== 0xffff)
3571 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3574 info
= (SLTG_ImplInfo
*)pBlk
;
3575 pTI
->impltypes
= TLBImplType_Constructor(pTI
->TypeAttr
.cImplTypes
);
3576 pImplType
= pTI
->impltypes
;
3578 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3579 pImplType
->implflags
= info
->impltypeflags
;
3582 if(info
->next
== 0xffff)
3585 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3586 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3588 info
++; /* see comment at top of function */
3592 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3593 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3595 TLBVarDesc
*pVarDesc
;
3596 BSTR bstrPrevName
= NULL
;
3597 SLTG_Variable
*pItem
;
3601 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Constructor(cVars
);
3603 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3604 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3606 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3608 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3609 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3610 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3614 if (pItem
->name
== 0xfffe)
3615 pVarDesc
->Name
= SysAllocString(bstrPrevName
);
3617 pVarDesc
->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3619 TRACE_(typelib
)("name: %s\n", debugstr_w(pVarDesc
->Name
));
3620 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3621 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3623 if(pItem
->flags
& 0x02)
3624 pType
= &pItem
->type
;
3626 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3628 if (pItem
->flags
& ~0xda)
3629 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3631 SLTG_DoElem(pType
, pBlk
,
3632 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3634 if (TRACE_ON(typelib
)) {
3636 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3637 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3640 if (pItem
->flags
& 0x40) {
3641 TRACE_(typelib
)("VAR_DISPATCH\n");
3642 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3644 else if (pItem
->flags
& 0x10) {
3645 TRACE_(typelib
)("VAR_CONST\n");
3646 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3647 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3648 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3649 if (pItem
->flags
& 0x08)
3650 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3652 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3658 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3660 TRACE_(typelib
)("len = %u\n", len
);
3661 if (len
== 0xffff) {
3664 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3665 str
= SysAllocStringLen(NULL
, alloc_len
);
3666 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3668 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3669 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3678 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3679 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3682 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3687 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3688 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3689 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3692 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3693 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3695 if (pItem
->flags
& 0x80)
3696 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3698 bstrPrevName
= pVarDesc
->Name
;
3700 pTI
->TypeAttr
.cVars
= cVars
;
3703 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3704 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3706 SLTG_Function
*pFunc
;
3708 TLBFuncDesc
*pFuncDesc
;
3710 pTI
->funcdescs
= TLBFuncDesc_Constructor(cFuncs
);
3712 pFuncDesc
= pTI
->funcdescs
;
3713 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
3714 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
3719 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3720 case SLTG_FUNCTION_MAGIC
:
3721 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3723 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3724 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
3726 case SLTG_STATIC_FUNCTION_MAGIC
:
3727 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
3730 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3733 pFuncDesc
->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3735 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
3736 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
3737 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3738 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3739 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3740 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
3742 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3743 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3745 if(pFunc
->retnextopt
& 0x80)
3746 pType
= &pFunc
->rettype
;
3748 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3750 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
3752 pFuncDesc
->funcdesc
.lprgelemdescParam
=
3753 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
3754 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
3756 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3758 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
3759 char *paramName
= pNameTable
+ *pArg
;
3761 /* If arg type follows then paramName points to the 2nd
3762 letter of the name, else the next WORD is an offset to
3763 the arg type and paramName points to the first letter.
3764 So let's take one char off paramName and see if we're
3765 pointing at an alpha-numeric char. However if *pArg is
3766 0xffff or 0xfffe then the param has no name, the former
3767 meaning that the next WORD is the type, the latter
3768 meaning that the next WORD is an offset to the type. */
3773 else if(*pArg
== 0xfffe) {
3777 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3782 if(HaveOffs
) { /* the next word is an offset to type */
3783 pType
= (WORD
*)(pBlk
+ *pArg
);
3784 SLTG_DoElem(pType
, pBlk
,
3785 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3790 pArg
= SLTG_DoElem(pArg
, pBlk
,
3791 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3794 /* Are we an optional param ? */
3795 if(pFuncDesc
->funcdesc
.cParams
- param
<=
3796 pFuncDesc
->funcdesc
.cParamsOpt
)
3797 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3800 pFuncDesc
->pParamDesc
[param
].Name
=
3801 TLB_MultiByteToBSTR(paramName
);
3803 pFuncDesc
->pParamDesc
[param
].Name
=
3804 SysAllocString(pFuncDesc
->Name
);
3808 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3811 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3812 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3813 SLTG_TypeInfoTail
*pTITail
)
3816 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3818 if(pTIHeader
->href_table
!= 0xffffffff) {
3819 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3825 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3826 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3828 heap_free(ref_lookup
);
3832 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3833 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3834 const SLTG_TypeInfoTail
*pTITail
)
3837 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3839 if(pTIHeader
->href_table
!= 0xffffffff) {
3840 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3846 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3847 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3850 if (pTITail
->funcs_off
!= 0xffff)
3851 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3853 heap_free(ref_lookup
);
3855 if (TRACE_ON(typelib
))
3856 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
3859 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3860 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3861 const SLTG_TypeInfoTail
*pTITail
)
3863 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3866 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3867 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3868 const SLTG_TypeInfoTail
*pTITail
)
3871 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3873 if (pTITail
->simple_alias
) {
3874 /* if simple alias, no more processing required */
3875 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3879 if(pTIHeader
->href_table
!= 0xffffffff) {
3880 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3884 /* otherwise it is an offset to a type */
3885 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3887 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3889 heap_free(ref_lookup
);
3892 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3893 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3894 const SLTG_TypeInfoTail
*pTITail
)
3896 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3897 if (pTIHeader
->href_table
!= 0xffffffff)
3898 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3901 if (pTITail
->vars_off
!= 0xffff)
3902 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3904 if (pTITail
->funcs_off
!= 0xffff)
3905 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3907 if (pTITail
->impls_off
!= 0xffff)
3908 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
3910 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3911 * of dispinterface functions including the IDispatch ones, so
3912 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3913 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3915 heap_free(ref_lookup
);
3916 if (TRACE_ON(typelib
))
3917 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
3920 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3921 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3922 const SLTG_TypeInfoTail
*pTITail
)
3924 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3927 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3928 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3929 const SLTG_TypeInfoTail
*pTITail
)
3931 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3932 if (pTIHeader
->href_table
!= 0xffffffff)
3933 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3936 if (pTITail
->vars_off
!= 0xffff)
3937 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3939 if (pTITail
->funcs_off
!= 0xffff)
3940 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3941 heap_free(ref_lookup
);
3942 if (TRACE_ON(typelib
))
3946 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3947 manageable copy of it into this */
3960 } SLTG_InternalOtherTypeInfo
;
3962 /****************************************************************************
3963 * ITypeLib2_Constructor_SLTG
3965 * loading a SLTG typelib from an in-memory image
3967 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3969 ITypeLibImpl
*pTypeLibImpl
;
3970 SLTG_Header
*pHeader
;
3971 SLTG_BlkEntry
*pBlkEntry
;
3975 LPVOID pBlk
, pFirstBlk
;
3976 SLTG_LibBlk
*pLibBlk
;
3977 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3978 char *pAfterOTIBlks
= NULL
;
3979 char *pNameTable
, *ptr
;
3982 ITypeInfoImpl
**ppTypeInfoImpl
;
3984 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3987 pTypeLibImpl
= TypeLibImpl_Constructor();
3988 if (!pTypeLibImpl
) return NULL
;
3992 TRACE_(typelib
)("header:\n");
3993 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3994 pHeader
->nrOfFileBlks
);
3995 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3996 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
3997 pHeader
->SLTG_magic
);
4001 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4002 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4004 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4005 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4007 /* Next we have a magic block */
4008 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4010 /* Let's see if we're still in sync */
4011 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4012 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4013 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4016 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4017 sizeof(SLTG_DIR_MAGIC
))) {
4018 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4022 pIndex
= (SLTG_Index
*)(pMagic
+1);
4024 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4026 pFirstBlk
= pPad9
+ 1;
4028 /* We'll set up a ptr to the main library block, which is the last one. */
4030 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4031 pBlkEntry
[order
].next
!= 0;
4032 order
= pBlkEntry
[order
].next
- 1, i
++) {
4033 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4037 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4039 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4044 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4046 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4049 ptr
= (char*)pLibBlk
+ len
;
4051 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4055 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4057 w
= *(WORD
*)(ptr
+ 2);
4060 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4061 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4062 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4064 w
= *(WORD
*)(ptr
+ 4 + len
);
4066 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4068 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4069 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4070 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4072 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4073 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4074 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4076 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4077 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4080 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4081 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4082 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4083 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4084 len
+= sizeof(SLTG_OtherTypeInfo
);
4088 pAfterOTIBlks
= ptr
;
4090 /* Skip this WORD and get the next DWORD */
4091 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4093 /* Now add this to pLibBLk look at what we're pointing at and
4094 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4095 dust and we should be pointing at the beginning of the name
4098 pNameTable
= (char*)pLibBlk
+ len
;
4100 switch(*(WORD
*)pNameTable
) {
4107 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4111 pNameTable
+= 0x216;
4115 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4117 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
4120 /* Hopefully we now have enough ptrs set up to actually read in
4121 some TypeInfos. It's not clear which order to do them in, so
4122 I'll just follow the links along the BlkEntry chain and read
4123 them in the order in which they are in the file */
4125 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4126 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4128 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4129 pBlkEntry
[order
].next
!= 0;
4130 order
= pBlkEntry
[order
].next
- 1, i
++) {
4132 SLTG_TypeInfoHeader
*pTIHeader
;
4133 SLTG_TypeInfoTail
*pTITail
;
4134 SLTG_MemberHeader
*pMemHeader
;
4136 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4137 FIXME_(typelib
)("Index strings don't match\n");
4138 heap_free(pOtherTypeInfoBlks
);
4143 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4144 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4145 heap_free(pOtherTypeInfoBlks
);
4148 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4149 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4150 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4152 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4153 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4154 (*ppTypeInfoImpl
)->index
= i
;
4155 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
4156 pOtherTypeInfoBlks
[i
].name_offs
+
4158 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4159 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
4160 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
4161 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
4162 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
4163 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
4164 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4166 if((*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4167 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= TKIND_DISPATCH
;
4169 if((pTIHeader
->typeflags1
& 7) != 2)
4170 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4171 if(pTIHeader
->typeflags3
!= 2)
4172 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4174 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4175 debugstr_w((*ppTypeInfoImpl
)->Name
),
4176 typekind_desc
[pTIHeader
->typekind
],
4177 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
4178 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
4180 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4182 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4184 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
4185 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4186 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
4188 switch(pTIHeader
->typekind
) {
4190 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4191 pTIHeader
, pTITail
);
4195 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4196 pTIHeader
, pTITail
);
4199 case TKIND_INTERFACE
:
4200 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4201 pTIHeader
, pTITail
);
4205 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4206 pTIHeader
, pTITail
);
4210 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4211 pTIHeader
, pTITail
);
4214 case TKIND_DISPATCH
:
4215 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4216 pTIHeader
, pTITail
);
4220 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4221 pTIHeader
, pTITail
);
4225 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4230 /* could get cFuncs, cVars and cImplTypes from here
4231 but we've already set those */
4232 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4248 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4251 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4252 FIXME("Somehow processed %d TypeInfos\n", i
);
4253 heap_free(pOtherTypeInfoBlks
);
4257 heap_free(pOtherTypeInfoBlks
);
4258 return &pTypeLibImpl
->ITypeLib2_iface
;
4261 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4263 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4265 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4267 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4268 IsEqualIID(riid
,&IID_ITypeLib
)||
4269 IsEqualIID(riid
,&IID_ITypeLib2
))
4271 *ppv
= &This
->ITypeLib2_iface
;
4273 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4274 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4276 *ppv
= &This
->ICreateTypeLib2_iface
;
4281 TRACE("-- Interface: E_NOINTERFACE\n");
4282 return E_NOINTERFACE
;
4285 IUnknown_AddRef((IUnknown
*)*ppv
);
4289 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4291 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4292 ULONG ref
= InterlockedIncrement(&This
->ref
);
4294 TRACE("(%p) ref=%u\n", This
, ref
);
4299 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4301 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4302 ULONG ref
= InterlockedDecrement(&This
->ref
);
4304 TRACE("(%p) ref=%u\n",This
, ref
);
4308 TLBImpLib
*pImpLib
, *pImpLibNext
;
4309 TLBRefType
*ref_type
;
4313 /* remove cache entry */
4316 TRACE("removing from cache list\n");
4317 EnterCriticalSection(&cache_section
);
4318 if(This
->entry
.next
)
4319 list_remove(&This
->entry
);
4320 LeaveCriticalSection(&cache_section
);
4321 heap_free(This
->path
);
4323 TRACE(" destroying ITypeLib(%p)\n",This
);
4325 SysFreeString(This
->Name
);
4328 SysFreeString(This
->DocString
);
4329 This
->DocString
= NULL
;
4331 SysFreeString(This
->HelpFile
);
4332 This
->HelpFile
= NULL
;
4334 SysFreeString(This
->HelpStringDll
);
4335 This
->HelpStringDll
= NULL
;
4337 TLB_FreeCustData(&This
->custdata_list
);
4339 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4340 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4341 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4343 heap_free(This
->pTypeDesc
);
4345 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4347 if (pImpLib
->pImpTypeLib
)
4348 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4349 SysFreeString(pImpLib
->name
);
4351 list_remove(&pImpLib
->entry
);
4355 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4357 list_remove(&ref_type
->entry
);
4358 heap_free(ref_type
);
4361 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4362 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4363 heap_free(This
->typeinfos
);
4371 /* ITypeLib::GetTypeInfoCount
4373 * Returns the number of type descriptions in the type library
4375 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4377 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4378 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4379 return This
->TypeInfoCount
;
4382 /* ITypeLib::GetTypeInfo
4384 * retrieves the specified type description in the library.
4386 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4389 ITypeInfo
**ppTInfo
)
4391 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4393 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4396 return E_INVALIDARG
;
4398 if(index
>= This
->TypeInfoCount
)
4399 return TYPE_E_ELEMENTNOTFOUND
;
4401 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[index
];
4402 ITypeInfo_AddRef(*ppTInfo
);
4408 /* ITypeLibs::GetTypeInfoType
4410 * Retrieves the type of a type description.
4412 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4417 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4419 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4422 return E_INVALIDARG
;
4424 if(index
>= This
->TypeInfoCount
)
4425 return TYPE_E_ELEMENTNOTFOUND
;
4427 *pTKind
= This
->typeinfos
[index
]->TypeAttr
.typekind
;
4432 /* ITypeLib::GetTypeInfoOfGuid
4434 * Retrieves the type description that corresponds to the specified GUID.
4437 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4440 ITypeInfo
**ppTInfo
)
4442 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4445 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4447 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4448 if(IsEqualIID(&This
->typeinfos
[i
]->TypeAttr
.guid
, guid
)){
4449 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[i
];
4450 ITypeInfo_AddRef(*ppTInfo
);
4455 return TYPE_E_ELEMENTNOTFOUND
;
4458 /* ITypeLib::GetLibAttr
4460 * Retrieves the structure that contains the library's attributes.
4463 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4467 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4469 TRACE("(%p, %p)\n", This
, attr
);
4471 if (!attr
) return E_INVALIDARG
;
4473 *attr
= heap_alloc(sizeof(**attr
));
4474 if (!*attr
) return E_OUTOFMEMORY
;
4476 **attr
= This
->LibAttr
;
4480 /* ITypeLib::GetTypeComp
4482 * Enables a client compiler to bind to a library's types, variables,
4483 * constants, and global functions.
4486 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4488 ITypeComp
**ppTComp
)
4490 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4492 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4493 *ppTComp
= &This
->ITypeComp_iface
;
4494 ITypeComp_AddRef(*ppTComp
);
4499 /* ITypeLib::GetDocumentation
4501 * Retrieves the library's documentation string, the complete Help file name
4502 * and path, and the context identifier for the library Help topic in the Help
4505 * On a successful return all non-null BSTR pointers will have been set,
4508 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4512 BSTR
*pBstrDocString
,
4513 DWORD
*pdwHelpContext
,
4514 BSTR
*pBstrHelpFile
)
4516 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4517 HRESULT result
= E_INVALIDARG
;
4520 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4522 pBstrName
, pBstrDocString
,
4523 pdwHelpContext
, pBstrHelpFile
);
4527 /* documentation for the typelib */
4532 if(!(*pBstrName
= SysAllocString(This
->Name
)))
4540 if (This
->DocString
)
4542 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
4545 else if (This
->Name
)
4547 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
4551 *pBstrDocString
= NULL
;
4555 *pdwHelpContext
= This
->dwHelpContext
;
4561 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
4565 *pBstrHelpFile
= NULL
;
4572 /* for a typeinfo */
4573 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4575 if(SUCCEEDED(result
))
4577 result
= ITypeInfo_GetDocumentation(pTInfo
,
4581 pdwHelpContext
, pBstrHelpFile
);
4583 ITypeInfo_Release(pTInfo
);
4588 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4590 if (pBstrName
) SysFreeString (*pBstrName
);
4592 return STG_E_INSUFFICIENTMEMORY
;
4597 * Indicates whether a passed-in string contains the name of a type or member
4598 * described in the library.
4601 static HRESULT WINAPI
ITypeLib2_fnIsName(
4607 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4609 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
4611 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4615 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4616 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4617 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4618 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4619 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4622 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4623 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++)
4624 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4625 goto ITypeLib2_fnIsName_exit
;
4627 for(vrc
= 0; vrc
< pTInfo
->TypeAttr
.cVars
; ++vrc
){
4628 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4629 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4635 ITypeLib2_fnIsName_exit
:
4636 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4637 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4642 /* ITypeLib::FindName
4644 * Finds occurrences of a type description in a type library. This may be used
4645 * to quickly verify that a name exists in a type library.
4648 static HRESULT WINAPI
ITypeLib2_fnFindName(
4652 ITypeInfo
**ppTInfo
,
4656 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4661 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
4663 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
4664 return E_INVALIDARG
;
4666 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
4667 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
4668 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4672 if(!memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4673 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4674 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
4677 if(!memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4678 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
4679 if(!memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
4680 goto ITypeLib2_fnFindName_exit
;
4684 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->TypeAttr
.cVars
, name
);
4686 goto ITypeLib2_fnFindName_exit
;
4689 ITypeLib2_fnFindName_exit
:
4690 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4691 ppTInfo
[count
]=(LPTYPEINFO
)pTInfo
;
4694 TRACE("found %d typeinfos\n", count
);
4701 /* ITypeLib::ReleaseTLibAttr
4703 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4706 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4708 TLIBATTR
*pTLibAttr
)
4710 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4711 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
4712 heap_free(pTLibAttr
);
4715 /* ITypeLib2::GetCustData
4717 * gets the custom data
4719 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4724 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4725 TLBCustData
*pCData
;
4727 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
4729 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
4731 return TYPE_E_ELEMENTNOTFOUND
;
4733 VariantInit(pVarVal
);
4734 VariantCopy(pVarVal
, &pCData
->data
);
4739 /* ITypeLib2::GetLibStatistics
4741 * Returns statistics about a type library that are required for efficient
4742 * sizing of hash tables.
4745 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4747 ULONG
*pcUniqueNames
,
4748 ULONG
*pcchUniqueNames
)
4750 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4752 FIXME("(%p): stub!\n", This
);
4754 if(pcUniqueNames
) *pcUniqueNames
=1;
4755 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4759 /* ITypeLib2::GetDocumentation2
4761 * Retrieves the library's documentation string, the complete Help file name
4762 * and path, the localization context to use, and the context ID for the
4763 * library Help topic in the Help file.
4766 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4770 BSTR
*pbstrHelpString
,
4771 DWORD
*pdwHelpStringContext
,
4772 BSTR
*pbstrHelpStringDll
)
4774 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4778 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4780 /* the help string should be obtained from the helpstringdll,
4781 * using the _DLLGetDocumentation function, based on the supplied
4782 * lcid. Nice to do sometime...
4786 /* documentation for the typelib */
4788 *pbstrHelpString
=SysAllocString(This
->DocString
);
4789 if(pdwHelpStringContext
)
4790 *pdwHelpStringContext
=This
->dwHelpContext
;
4791 if(pbstrHelpStringDll
)
4792 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4798 /* for a typeinfo */
4799 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4801 if(SUCCEEDED(result
))
4803 ITypeInfo2
* pTInfo2
;
4804 result
= ITypeInfo_QueryInterface(pTInfo
,
4806 (LPVOID
*) &pTInfo2
);
4808 if(SUCCEEDED(result
))
4810 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4814 pdwHelpStringContext
,
4815 pbstrHelpStringDll
);
4817 ITypeInfo2_Release(pTInfo2
);
4820 ITypeInfo_Release(pTInfo
);
4826 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
4828 TLBCustData
*pCData
;
4832 ct
= list_count(custdata_list
);
4834 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
4835 if(!pCustData
->prgCustData
)
4836 return E_OUTOFMEMORY
;
4838 pCustData
->cCustData
= ct
;
4840 cdi
= pCustData
->prgCustData
;
4841 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
4842 cdi
->guid
= pCData
->guid
;
4843 VariantCopy(&cdi
->varValue
, &pCData
->data
);
4851 /* ITypeLib2::GetAllCustData
4853 * Gets all custom data items for the library.
4856 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4858 CUSTDATA
*pCustData
)
4860 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4861 TRACE("(%p)->(%p)\n", This
, pCustData
);
4862 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
4865 static const ITypeLib2Vtbl tlbvt
= {
4866 ITypeLib2_fnQueryInterface
,
4868 ITypeLib2_fnRelease
,
4869 ITypeLib2_fnGetTypeInfoCount
,
4870 ITypeLib2_fnGetTypeInfo
,
4871 ITypeLib2_fnGetTypeInfoType
,
4872 ITypeLib2_fnGetTypeInfoOfGuid
,
4873 ITypeLib2_fnGetLibAttr
,
4874 ITypeLib2_fnGetTypeComp
,
4875 ITypeLib2_fnGetDocumentation
,
4877 ITypeLib2_fnFindName
,
4878 ITypeLib2_fnReleaseTLibAttr
,
4880 ITypeLib2_fnGetCustData
,
4881 ITypeLib2_fnGetLibStatistics
,
4882 ITypeLib2_fnGetDocumentation2
,
4883 ITypeLib2_fnGetAllCustData
4887 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4889 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4891 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
4894 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4896 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4898 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
4901 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4903 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4905 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
4908 static HRESULT WINAPI
ITypeLibComp_fnBind(
4913 ITypeInfo
** ppTInfo
,
4914 DESCKIND
* pDescKind
,
4917 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4918 int typemismatch
=0, i
;
4920 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4922 *pDescKind
= DESCKIND_NONE
;
4923 pBindPtr
->lptcomp
= NULL
;
4926 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4927 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
4928 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4930 /* FIXME: check wFlags here? */
4931 /* FIXME: we should use a hash table to look this info up using lHash
4932 * instead of an O(n) search */
4933 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4934 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4936 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4938 *pDescKind
= DESCKIND_TYPECOMP
;
4939 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
4940 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4941 TRACE("module or enum: %s\n", debugstr_w(szName
));
4946 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4947 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4949 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
4952 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4953 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4955 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4958 else if (hr
== TYPE_E_TYPEMISMATCH
)
4962 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4963 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4965 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
4967 ITypeInfo
*subtypeinfo
;
4969 DESCKIND subdesckind
;
4971 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4972 &subtypeinfo
, &subdesckind
, &subbindptr
);
4973 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4975 TYPEDESC tdesc_appobject
;
4976 const VARDESC vardesc_appobject
=
4979 NULL
, /* lpstrSchema */
4994 VAR_STATIC
/* varkind */
4997 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
4998 tdesc_appobject
.vt
= VT_USERDEFINED
;
5000 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5002 /* cleanup things filled in by Bind call so we can put our
5003 * application object data in there instead */
5004 switch (subdesckind
)
5006 case DESCKIND_FUNCDESC
:
5007 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5009 case DESCKIND_VARDESC
:
5010 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5015 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5017 if (pTypeInfo
->hreftype
== -1)
5018 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5020 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5024 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5025 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
5026 ITypeInfo_AddRef(*ppTInfo
);
5029 else if (hr
== TYPE_E_TYPEMISMATCH
)
5036 TRACE("type mismatch %s\n", debugstr_w(szName
));
5037 return TYPE_E_TYPEMISMATCH
;
5041 TRACE("name not found %s\n", debugstr_w(szName
));
5046 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5050 ITypeInfo
** ppTInfo
,
5051 ITypeComp
** ppTComp
)
5053 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5056 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5058 if(!szName
|| !ppTInfo
|| !ppTComp
)
5059 return E_INVALIDARG
;
5061 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
5063 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5064 /* FIXME: should use lHash to do the search */
5065 if (pTypeInfo
->Name
&& !strcmpiW(pTypeInfo
->Name
, szName
))
5067 TRACE("returning %p\n", pTypeInfo
);
5068 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5069 ITypeInfo_AddRef(*ppTInfo
);
5070 *ppTComp
= &pTypeInfo
->ITypeComp_iface
;
5071 ITypeComp_AddRef(*ppTComp
);
5076 TRACE("not found\n");
5082 static const ITypeCompVtbl tlbtcvt
=
5085 ITypeLibComp_fnQueryInterface
,
5086 ITypeLibComp_fnAddRef
,
5087 ITypeLibComp_fnRelease
,
5089 ITypeLibComp_fnBind
,
5090 ITypeLibComp_fnBindType
5093 /*================== ITypeInfo(2) Methods ===================================*/
5094 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5096 ITypeInfoImpl
*pTypeInfoImpl
;
5098 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5101 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5102 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5103 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5104 pTypeInfoImpl
->ref
= 0;
5105 pTypeInfoImpl
->hreftype
= -1;
5106 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
5107 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
5108 list_init(&pTypeInfoImpl
->custdata_list
);
5110 TRACE("(%p)\n", pTypeInfoImpl
);
5111 return pTypeInfoImpl
;
5114 /* ITypeInfo::QueryInterface
5116 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5121 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5123 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5126 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5127 IsEqualIID(riid
,&IID_ITypeInfo
)||
5128 IsEqualIID(riid
,&IID_ITypeInfo2
))
5130 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5131 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5132 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5135 ITypeInfo2_AddRef(iface
);
5136 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5139 TRACE("-- Interface: E_NOINTERFACE\n");
5140 return E_NOINTERFACE
;
5143 /* ITypeInfo::AddRef
5145 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5147 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5148 ULONG ref
= InterlockedIncrement(&This
->ref
);
5150 TRACE("(%p)->ref is %u\n",This
, ref
);
5152 if (ref
== 1 /* incremented from 0 */)
5153 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5158 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5162 TRACE("destroying ITypeInfo(%p)\n",This
);
5164 SysFreeString(This
->Name
);
5167 SysFreeString(This
->DocString
);
5168 This
->DocString
= NULL
;
5170 SysFreeString(This
->DllName
);
5171 This
->DllName
= NULL
;
5173 for (i
= 0; i
< This
->TypeAttr
.cFuncs
; ++i
)
5176 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5177 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5179 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5180 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5182 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5183 heap_free(elemdesc
->u
.paramdesc
.pparamdescex
);
5185 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5186 SysFreeString(pFInfo
->pParamDesc
[j
].Name
);
5188 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5189 heap_free(pFInfo
->pParamDesc
);
5190 TLB_FreeCustData(&pFInfo
->custdata_list
);
5191 if (!IS_INTRESOURCE(pFInfo
->Entry
) && pFInfo
->Entry
!= (BSTR
)-1)
5192 SysFreeString(pFInfo
->Entry
);
5193 SysFreeString(pFInfo
->HelpString
);
5194 SysFreeString(pFInfo
->Name
);
5196 heap_free(This
->funcdescs
);
5198 for(i
= 0; i
< This
->TypeAttr
.cVars
; ++i
)
5200 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5201 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5203 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5204 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5206 TLB_FreeCustData(&pVInfo
->custdata_list
);
5207 SysFreeString(pVInfo
->Name
);
5208 SysFreeString(pVInfo
->HelpString
);
5210 heap_free(This
->vardescs
);
5212 if(This
->impltypes
){
5213 for (i
= 0; i
< This
->TypeAttr
.cImplTypes
; ++i
){
5214 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5215 TLB_FreeCustData(&pImpl
->custdata_list
);
5217 heap_free(This
->impltypes
);
5220 TLB_FreeCustData(&This
->custdata_list
);
5225 /* ITypeInfo::Release
5227 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5229 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5230 ULONG ref
= InterlockedDecrement(&This
->ref
);
5232 TRACE("(%p)->(%u)\n",This
, ref
);
5236 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5237 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5238 if (not_attached_to_typelib
)
5240 /* otherwise This will be freed when typelib is freed */
5246 /* ITypeInfo::GetTypeAttr
5248 * Retrieves a TYPEATTR structure that contains the attributes of the type
5252 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5253 LPTYPEATTR
*ppTypeAttr
)
5255 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5258 TRACE("(%p)\n",This
);
5260 size
= sizeof(**ppTypeAttr
);
5261 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5262 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
5264 *ppTypeAttr
= heap_alloc(size
);
5266 return E_OUTOFMEMORY
;
5268 **ppTypeAttr
= This
->TypeAttr
;
5270 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5271 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5272 &This
->TypeAttr
.tdescAlias
, *ppTypeAttr
+ 1);
5274 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5275 /* This should include all the inherited funcs */
5276 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5277 /* This is always the size of IDispatch's vtbl */
5278 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5279 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5284 /* ITypeInfo::GetTypeComp
5286 * Retrieves the ITypeComp interface for the type description, which enables a
5287 * client compiler to bind to the type description's members.
5290 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5291 ITypeComp
* *ppTComp
)
5293 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5295 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5297 *ppTComp
= &This
->ITypeComp_iface
;
5298 ITypeComp_AddRef(*ppTComp
);
5302 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5304 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5305 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5306 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5310 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5313 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5314 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5316 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5317 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5318 *buffer
+= sizeof(PARAMDESCEX
);
5319 *pparamdescex_dest
= *pparamdescex_src
;
5320 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5321 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5322 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5323 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5326 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5330 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5332 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5333 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5336 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5340 SIZE_T size
= sizeof(*src
);
5344 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5345 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5346 for (i
= 0; i
< src
->cParams
; i
++)
5348 size
+= sizeof(ELEMDESC
);
5349 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5352 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5353 if (!dest
) return E_OUTOFMEMORY
;
5356 if (dispinterface
) /* overwrite funckind */
5357 dest
->funckind
= FUNC_DISPATCH
;
5358 buffer
= (char *)(dest
+ 1);
5360 if (dest
->cScodes
) {
5361 dest
->lprgscode
= (SCODE
*)buffer
;
5362 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5363 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5365 dest
->lprgscode
= NULL
;
5367 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5370 SysFreeString((BSTR
)dest
);
5374 if (dest
->cParams
) {
5375 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5376 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5377 for (i
= 0; i
< src
->cParams
; i
++)
5379 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5385 /* undo the above actions */
5386 for (i
= i
- 1; i
>= 0; i
--)
5387 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5388 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5389 SysFreeString((BSTR
)dest
);
5393 dest
->lprgelemdescParam
= NULL
;
5395 /* special treatment for dispinterfaces: this makes functions appear
5396 * to return their [retval] value when it is really returning an
5398 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5400 if (dest
->cParams
&&
5401 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5403 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5404 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5406 ERR("elemdesc should have started with VT_PTR instead of:\n");
5408 dump_ELEMDESC(elemdesc
);
5409 return E_UNEXPECTED
;
5412 /* copy last parameter to the return value. we are using a flat
5413 * buffer so there is no danger of leaking memory in
5415 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5417 /* remove the last parameter */
5421 /* otherwise this function is made to appear to have no return
5423 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5431 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5433 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5435 if (index
>= This
->TypeAttr
.cFuncs
)
5436 return TYPE_E_ELEMENTNOTFOUND
;
5438 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5442 /* internal function to make the inherited interfaces' methods appear
5443 * part of the interface */
5444 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5445 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5447 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5449 UINT implemented_funcs
= 0;
5454 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5458 ITypeInfo
*pSubTypeInfo
;
5461 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5465 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5468 &sub_funcs
, hrefoffset
);
5469 implemented_funcs
+= sub_funcs
;
5470 ITypeInfo_Release(pSubTypeInfo
);
5473 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5477 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
5481 if (index
< implemented_funcs
)
5482 return E_INVALIDARG
;
5483 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5487 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5489 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5492 switch (pTypeDesc
->vt
)
5494 case VT_USERDEFINED
:
5495 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5499 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5502 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5510 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5513 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5514 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5515 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5518 /* ITypeInfo::GetFuncDesc
5520 * Retrieves the FUNCDESC structure that contains information about a
5521 * specified function.
5524 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5525 LPFUNCDESC
*ppFuncDesc
)
5527 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5528 const FUNCDESC
*internal_funcdesc
;
5530 UINT hrefoffset
= 0;
5532 TRACE("(%p) index %d\n", This
, index
);
5535 return E_INVALIDARG
;
5537 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5538 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5539 &internal_funcdesc
, NULL
,
5542 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5543 &internal_funcdesc
);
5546 WARN("description for function %d not found\n", index
);
5550 hr
= TLB_AllocAndInitFuncDesc(
5553 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5555 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5556 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5558 TRACE("-- 0x%08x\n", hr
);
5562 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5566 SIZE_T size
= sizeof(*src
);
5569 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5570 if (src
->varkind
== VAR_CONST
)
5571 size
+= sizeof(VARIANT
);
5572 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5574 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5575 if (!dest
) return E_OUTOFMEMORY
;
5578 buffer
= (char *)(dest
+ 1);
5579 if (src
->lpstrSchema
)
5582 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5583 len
= strlenW(src
->lpstrSchema
);
5584 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5585 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5588 if (src
->varkind
== VAR_CONST
)
5592 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5593 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5594 buffer
+= sizeof(VARIANT
);
5595 VariantInit(dest
->u
.lpvarValue
);
5596 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5599 SysFreeString((BSTR
)dest
);
5603 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5606 if (src
->varkind
== VAR_CONST
)
5607 VariantClear(dest
->u
.lpvarValue
);
5608 SysFreeString((BSTR
)dest
);
5615 /* ITypeInfo::GetVarDesc
5617 * Retrieves a VARDESC structure that describes the specified variable.
5620 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5621 LPVARDESC
*ppVarDesc
)
5623 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5624 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5626 TRACE("(%p) index %d\n", This
, index
);
5628 if(index
>= This
->TypeAttr
.cVars
)
5629 return TYPE_E_ELEMENTNOTFOUND
;
5631 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5634 /* ITypeInfo_GetNames
5636 * Retrieves the variable with the specified member ID (or the name of the
5637 * property or method and its parameters) that correspond to the specified
5640 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5641 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5643 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5644 const TLBFuncDesc
*pFDesc
;
5645 const TLBVarDesc
*pVDesc
;
5647 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5648 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
5651 /* function found, now return function and parameter names */
5652 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5655 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
5657 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
5663 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
5666 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
5671 if(This
->impltypes
&&
5672 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5673 /* recursive search */
5676 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5677 if(SUCCEEDED(result
))
5679 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5680 ITypeInfo_Release(pTInfo
);
5683 WARN("Could not search inherited interface!\n");
5687 WARN("no names found\n");
5690 return TYPE_E_ELEMENTNOTFOUND
;
5697 /* ITypeInfo::GetRefTypeOfImplType
5699 * If a type description describes a COM class, it retrieves the type
5700 * description of the implemented interface types. For an interface,
5701 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5705 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5710 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5713 TRACE("(%p) index %d\n", This
, index
);
5714 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5718 /* only valid on dual interfaces;
5719 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5721 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5723 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5729 hr
= TYPE_E_ELEMENTNOTFOUND
;
5732 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5734 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5735 *pRefType
= This
->pTypeLib
->dispatch_href
;
5739 if(index
>= This
->TypeAttr
.cImplTypes
)
5740 hr
= TYPE_E_ELEMENTNOTFOUND
;
5742 *pRefType
= This
->impltypes
[index
].hRef
;
5748 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5750 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5756 /* ITypeInfo::GetImplTypeFlags
5758 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5759 * or base interface in a type description.
5761 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5762 UINT index
, INT
*pImplTypeFlags
)
5764 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5766 TRACE("(%p) index %d\n", This
, index
);
5769 return E_INVALIDARG
;
5771 if(This
->TypeAttr
.typekind
== TKIND_DISPATCH
&& index
== 0){
5772 *pImplTypeFlags
= 0;
5776 if(index
>= This
->TypeAttr
.cImplTypes
)
5777 return TYPE_E_ELEMENTNOTFOUND
;
5779 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
5785 * Maps between member names and member IDs, and parameter names and
5788 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5789 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5791 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5792 const TLBVarDesc
*pVDesc
;
5796 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5799 /* init out parameters in case of failure */
5800 for (i
= 0; i
< cNames
; i
++)
5801 pMemId
[i
] = MEMBERID_NIL
;
5803 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
) {
5805 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
5806 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5807 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5808 for(i
=1; i
< cNames
; i
++){
5809 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5810 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5812 if( j
<pFDesc
->funcdesc
.cParams
)
5815 ret
=DISP_E_UNKNOWNNAME
;
5817 TRACE("-- 0x%08x\n", ret
);
5821 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, *rgszNames
);
5824 *pMemId
= pVDesc
->vardesc
.memid
;
5827 /* not found, see if it can be found in an inherited interface */
5828 if(This
->impltypes
) {
5829 /* recursive search */
5831 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5833 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5834 ITypeInfo_Release(pTInfo
);
5837 WARN("Could not search inherited interface!\n");
5839 WARN("no names found\n");
5840 return DISP_E_UNKNOWNNAME
;
5846 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
5847 __ASM_GLOBAL_FUNC( call_method
,
5849 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5850 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5851 "movl %esp,%ebp\n\t"
5852 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5854 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5856 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5857 "movl 12(%ebp),%edx\n\t"
5858 "movl %esp,%edi\n\t"
5861 "subl %edx,%edi\n\t"
5862 "andl $~15,%edi\n\t"
5863 "movl %edi,%esp\n\t"
5864 "movl 12(%ebp),%ecx\n\t"
5865 "movl 16(%ebp),%esi\n\t"
5868 "1:\tcall *8(%ebp)\n\t"
5869 "subl %esp,%edi\n\t"
5870 "movl 20(%ebp),%ecx\n\t"
5871 "movl %edi,(%ecx)\n\t"
5872 "leal -8(%ebp),%esp\n\t"
5874 __ASM_CFI(".cfi_same_value %edi\n\t")
5876 __ASM_CFI(".cfi_same_value %esi\n\t")
5878 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5879 __ASM_CFI(".cfi_same_value %ebp\n\t")
5882 /* same function but returning floating point */
5883 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
5885 /* ITypeInfo::Invoke
5887 * Invokes a method, or accesses a property of an object, that implements the
5888 * interface described by the type description.
5891 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5895 if (TRACE_ON(ole
)) {
5897 TRACE("Calling %p(",func
);
5898 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
5899 if (nrargs
> 30) TRACE("...");
5906 res
= call_method( func
, nrargs
, args
, &stack_offset
);
5909 FIXME("unsupported calling convention %d\n",callconv
);
5913 TRACE("returns %08x\n",res
);
5917 #elif defined(__x86_64__)
5919 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
5920 __ASM_GLOBAL_FUNC( call_method
,
5922 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5923 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5924 "movq %rsp,%rbp\n\t"
5925 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5927 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5929 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5930 "movq %rcx,%rax\n\t"
5933 "cmovgq %rdx,%rcx\n\t"
5934 "leaq 0(,%rcx,8),%rdx\n\t"
5935 "subq %rdx,%rsp\n\t"
5936 "andq $~15,%rsp\n\t"
5937 "movq %rsp,%rdi\n\t"
5940 "movq 0(%rsp),%rcx\n\t"
5941 "movq 8(%rsp),%rdx\n\t"
5942 "movq 16(%rsp),%r8\n\t"
5943 "movq 24(%rsp),%r9\n\t"
5944 "movq %rcx,%xmm0\n\t"
5945 "movq %rdx,%xmm1\n\t"
5946 "movq %r8,%xmm2\n\t"
5947 "movq %r9,%xmm3\n\t"
5949 "leaq -16(%rbp),%rsp\n\t"
5951 __ASM_CFI(".cfi_same_value %rdi\n\t")
5953 __ASM_CFI(".cfi_same_value %rsi\n\t")
5954 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5956 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5957 __ASM_CFI(".cfi_same_value %rbp\n\t")
5960 /* same function but returning floating point */
5961 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
5963 #endif /* __x86_64__ */
5965 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5968 ITypeInfo
*tinfo2
= NULL
;
5969 TYPEATTR
*tattr
= NULL
;
5971 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5974 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5976 tdesc
->u
.hreftype
, hr
);
5979 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5982 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5983 ITypeInfo_Release(tinfo2
);
5987 switch (tattr
->typekind
)
5994 tdesc
= &tattr
->tdescAlias
;
5995 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5998 case TKIND_INTERFACE
:
5999 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6005 case TKIND_DISPATCH
:
6014 FIXME("TKIND_RECORD unhandled.\n");
6019 FIXME("TKIND_UNION unhandled.\n");
6024 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6028 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6029 ITypeInfo_Release(tinfo2
);
6033 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6037 /* enforce only one level of pointer indirection */
6038 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6040 tdesc
= tdesc
->u
.lptdesc
;
6042 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6043 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6044 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6045 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6046 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6048 VARTYPE vt_userdefined
= 0;
6049 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6050 if (tdesc
->vt
== VT_PTR
)
6052 vt_userdefined
= VT_BYREF
;
6053 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6055 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6057 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6058 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6060 *vt
|= vt_userdefined
;
6072 case VT_USERDEFINED
:
6073 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6080 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6081 hr
= DISP_E_BADVARTYPE
;
6085 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6100 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6106 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6110 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6112 ITypeInfo_Release(tinfo2
);
6116 switch(tattr
->typekind
) {
6118 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6121 case TKIND_INTERFACE
:
6122 case TKIND_DISPATCH
:
6123 *guid
= tattr
->guid
;
6127 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6128 hres
= E_UNEXPECTED
;
6131 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6132 ITypeInfo_Release(tinfo2
);
6136 /***********************************************************************
6137 * DispCallFunc (OLEAUT32.@)
6139 * Invokes a function of the specified calling convention, passing the
6140 * specified arguments and returns the result.
6143 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6144 * oVft [I] The offset in the vtable. See notes.
6145 * cc [I] Calling convention of the function to call.
6146 * vtReturn [I] The return type of the function.
6147 * cActuals [I] Number of parameters.
6148 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6149 * prgpvarg [I] The arguments to pass.
6150 * pvargResult [O] The return value of the function. Can be NULL.
6154 * Failure: HRESULT code.
6157 * The HRESULT return value of this function is not affected by the return
6158 * value of the user supplied function, which is returned in pvargResult.
6160 * If pvInstance is NULL then a non-object function is to be called and oVft
6161 * is the address of the function to call.
6163 * The cc parameter can be one of the following values:
6176 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6177 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6180 int argspos
, stack_offset
;
6185 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6186 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6187 pvargResult
, V_VT(pvargResult
));
6189 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6191 FIXME("unsupported calling convention %d\n",cc
);
6192 return E_INVALIDARG
;
6195 /* maximum size for an argument is sizeof(VARIANT) */
6196 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6198 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6202 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6203 func
= vtable
[oVft
/sizeof(void *)];
6204 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6206 else func
= (void *)oVft
;
6208 for (i
= 0; i
< cActuals
; i
++)
6210 VARIANT
*arg
= prgpvarg
[i
];
6221 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6222 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6226 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6227 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6229 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6230 args
[argspos
++] = V_BOOL(arg
);
6233 args
[argspos
++] = V_UI4(arg
);
6236 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6243 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6246 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6250 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6254 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6255 call_method( func
, argspos
, args
, &stack_offset
);
6260 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6263 WARN("invalid return type %u\n", vtReturn
);
6265 return E_INVALIDARG
;
6267 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6271 if (stack_offset
&& cc
== CC_STDCALL
)
6273 WARN( "stack pointer off by %d\n", stack_offset
);
6274 return DISP_E_BADCALLEE
;
6276 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6277 TRACE("retval: "); dump_Variant(pvargResult
);
6280 #elif defined(__x86_64__)
6286 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6287 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6288 pvargResult
, V_VT(pvargResult
));
6290 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6292 FIXME("unsupported calling convention %d\n",cc
);
6293 return E_INVALIDARG
;
6296 /* maximum size for an argument is sizeof(DWORD_PTR) */
6297 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6299 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6303 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6304 func
= vtable
[oVft
/sizeof(void *)];
6305 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6307 else func
= (void *)oVft
;
6309 for (i
= 0; i
< cActuals
; i
++)
6311 VARIANT
*arg
= prgpvarg
[i
];
6317 args
[argspos
++] = (ULONG_PTR
)arg
;
6319 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6320 args
[argspos
++] = V_BOOL(arg
);
6323 args
[argspos
++] = V_UI8(arg
);
6326 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6333 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6337 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6341 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6342 call_method( func
, argspos
, args
);
6345 WARN("invalid return type %u\n", vtReturn
);
6347 return E_INVALIDARG
;
6349 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6353 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6354 TRACE("retval: "); dump_Variant(pvargResult
);
6358 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6359 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6364 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6366 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6369 #define INVBUF_ELEMENT_SIZE \
6370 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6371 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6372 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6373 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6374 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6375 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6376 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6377 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6379 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6384 DISPPARAMS
*pDispParams
,
6385 VARIANT
*pVarResult
,
6386 EXCEPINFO
*pExcepInfo
,
6389 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6391 unsigned int var_index
;
6394 const TLBFuncDesc
*pFuncInfo
;
6397 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6398 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6401 if( This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6402 return DISP_E_MEMBERNOTFOUND
;
6406 ERR("NULL pDispParams not allowed\n");
6407 return E_INVALIDARG
;
6410 dump_DispParms(pDispParams
);
6412 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6414 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6415 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6416 return E_INVALIDARG
;
6419 /* we do this instead of using GetFuncDesc since it will return a fake
6420 * FUNCDESC for dispinterfaces and we want the real function description */
6421 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
6422 pFuncInfo
= &This
->funcdescs
[fdc
];
6423 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6424 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6425 !func_restricted( &pFuncInfo
->funcdesc
))
6429 if (fdc
< This
->TypeAttr
.cFuncs
) {
6430 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6434 TRACE("invoking:\n");
6435 dump_TLBFuncDescOne(pFuncInfo
);
6438 switch (func_desc
->funckind
) {
6439 case FUNC_PUREVIRTUAL
:
6440 case FUNC_VIRTUAL
: {
6441 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6443 VARIANT retval
; /* pointer for storing byref retvals in */
6444 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6445 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6446 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6447 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6448 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6449 UINT vargs_converted
=0;
6453 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6455 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6457 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6458 hres
= DISP_E_PARAMNOTFOUND
;
6463 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6465 ERR("functions with the vararg attribute do not support named arguments\n");
6466 hres
= DISP_E_NONAMEDARGS
;
6470 for (i
= 0; i
< func_desc
->cParams
; i
++)
6472 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6473 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6478 TRACE("changing args\n");
6479 for (i
= 0; i
< func_desc
->cParams
; i
++)
6481 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6482 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6483 VARIANTARG
*src_arg
;
6485 if (wParamFlags
& PARAMFLAG_FLCID
)
6488 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6490 V_I4(arg
) = This
->pTypeLib
->lcid
;
6499 for (j
= 0; j
< cNamedArgs
; j
++)
6500 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6502 src_arg
= &pDispParams
->rgvarg
[j
];
6507 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6509 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6513 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6515 /* under most conditions the caller is not allowed to
6516 * pass in a dispparam arg in the index of what would be
6517 * the retval parameter. however, there is an exception
6518 * where the extra parameter is used in an extra
6519 * IDispatch::Invoke below */
6520 if ((i
< pDispParams
->cArgs
) &&
6521 ((func_desc
->cParams
!= 1) || !pVarResult
||
6522 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6524 hres
= DISP_E_BADPARAMCOUNT
;
6528 /* note: this check is placed so that if the caller passes
6529 * in a VARIANTARG for the retval we just ignore it, like
6531 if (i
== func_desc
->cParams
- 1)
6534 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6535 memset(arg
, 0, sizeof(*arg
));
6536 V_VT(arg
) = rgvt
[i
];
6537 memset(&retval
, 0, sizeof(retval
));
6538 V_BYREF(arg
) = &retval
;
6542 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6543 hres
= E_UNEXPECTED
;
6549 dump_Variant(src_arg
);
6551 if(rgvt
[i
]!=V_VT(src_arg
))
6553 if (rgvt
[i
] == VT_VARIANT
)
6554 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6555 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6557 if (rgvt
[i
] == V_VT(src_arg
))
6558 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6561 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6562 if (wParamFlags
& PARAMFLAG_FIN
)
6563 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6564 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6566 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6568 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6571 SAFEARRAYBOUND bound
;
6575 bound
.cElements
= pDispParams
->cArgs
-i
;
6576 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6578 ERR("SafeArrayCreate failed\n");
6581 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6584 ERR("SafeArrayAccessData failed with %x\n", hres
);
6585 SafeArrayDestroy(a
);
6588 for (j
= 0; j
< bound
.cElements
; j
++)
6589 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6590 hres
= SafeArrayUnaccessData(a
);
6593 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6594 SafeArrayDestroy(a
);
6597 V_ARRAY(&rgvarg
[i
]) = a
;
6598 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6600 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6602 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6603 if (wParamFlags
& PARAMFLAG_FIN
)
6604 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6606 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6607 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6608 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6610 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6612 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6613 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6617 /* FIXME: this doesn't work for VT_BYREF arguments if
6618 * they are not the same type as in the paramdesc */
6619 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6620 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6621 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6626 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6627 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6628 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6631 prgpvarg
[i
] = &rgvarg
[i
];
6635 prgpvarg
[i
] = src_arg
;
6638 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
6639 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
6640 && V_UNKNOWN(prgpvarg
[i
])) {
6641 IUnknown
*userdefined_iface
;
6644 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
6648 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
6650 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
6654 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
6655 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
6658 else if (wParamFlags
& PARAMFLAG_FOPT
)
6661 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6662 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6664 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6670 VARIANTARG
*missing_arg
;
6671 /* if the function wants a pointer to a variant then
6672 * set that up, otherwise just pass the VT_ERROR in
6673 * the argument by value */
6674 if (rgvt
[i
] & VT_BYREF
)
6676 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6677 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6678 V_VARIANTREF(arg
) = missing_arg
;
6682 V_VT(missing_arg
) = VT_ERROR
;
6683 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6688 hres
= DISP_E_BADPARAMCOUNT
;
6692 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6694 /* VT_VOID is a special case for return types, so it is not
6695 * handled in the general function */
6696 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
6697 V_VT(&varresult
) = VT_EMPTY
;
6700 V_VT(&varresult
) = 0;
6701 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
6702 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6705 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
6706 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6707 prgpvarg
, &varresult
);
6709 vargs_converted
= 0;
6711 for (i
= 0; i
< func_desc
->cParams
; i
++)
6713 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6714 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6716 if (wParamFlags
& PARAMFLAG_FLCID
)
6718 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
6722 TRACE("[retval] value: ");
6723 dump_Variant(prgpvarg
[i
]);
6728 VariantInit(pVarResult
);
6729 /* deref return value */
6730 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6733 VARIANT_ClearInd(prgpvarg
[i
]);
6735 else if (vargs_converted
< pDispParams
->cArgs
)
6737 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6738 if (wParamFlags
& PARAMFLAG_FOUT
)
6740 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
6742 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6746 ERR("failed to convert param %d to vt %d\n", i
,
6747 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
6752 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6753 func_desc
->cParamsOpt
< 0 &&
6754 i
== func_desc
->cParams
-1)
6756 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6759 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6762 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6765 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6768 ERR("SafeArrayAccessData failed with %x\n", hres
);
6771 for (j
= 0; j
<= ubound
; j
++)
6772 VariantClear(&v
[j
]);
6773 hres
= SafeArrayUnaccessData(a
);
6776 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6780 VariantClear(&rgvarg
[i
]);
6783 else if (wParamFlags
& PARAMFLAG_FOPT
)
6785 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6786 VariantClear(&rgvarg
[i
]);
6789 VariantClear(&missing_arg
[i
]);
6792 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6794 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
6795 hres
= DISP_E_EXCEPTION
;
6798 IErrorInfo
*pErrorInfo
;
6799 pExcepInfo
->scode
= V_ERROR(&varresult
);
6800 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
6802 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
6803 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
6804 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
6805 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
6807 IErrorInfo_Release(pErrorInfo
);
6811 if (V_VT(&varresult
) != VT_ERROR
)
6813 TRACE("varresult value: ");
6814 dump_Variant(&varresult
);
6818 VariantClear(pVarResult
);
6819 *pVarResult
= varresult
;
6822 VariantClear(&varresult
);
6825 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
6826 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
6827 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
6828 (pDispParams
->cArgs
!= 0))
6830 if (V_VT(pVarResult
) == VT_DISPATCH
)
6832 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
6833 /* Note: not VariantClear; we still need the dispatch
6834 * pointer to be valid */
6835 VariantInit(pVarResult
);
6836 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
6837 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
6838 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
6839 IDispatch_Release(pDispatch
);
6843 VariantClear(pVarResult
);
6844 hres
= DISP_E_NOTACOLLECTION
;
6852 case FUNC_DISPATCH
: {
6855 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
6856 if (SUCCEEDED(hres
)) {
6857 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6858 hres
= IDispatch_Invoke(
6859 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
6860 pVarResult
,pExcepInfo
,pArgErr
6863 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
6864 IDispatch_Release(disp
);
6866 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6870 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
6875 TRACE("-- 0x%08x\n", hres
);
6878 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
6881 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
6882 if(FAILED(hres
)) return hres
;
6884 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6885 dump_VARDESC(var_desc
);
6886 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6890 /* not found, look for it in inherited interfaces */
6891 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6892 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6893 if(This
->impltypes
) {
6894 /* recursive search */
6896 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6897 if(SUCCEEDED(hres
)){
6898 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6899 ITypeInfo_Release(pTInfo
);
6902 WARN("Could not search inherited interface!\n");
6905 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6906 return DISP_E_MEMBERNOTFOUND
;
6909 /* ITypeInfo::GetDocumentation
6911 * Retrieves the documentation string, the complete Help file name and path,
6912 * and the context ID for the Help topic for a specified type description.
6914 * (Can be tested by the Visual Basic Editor in Word for instance.)
6916 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6917 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6918 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6920 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6921 const TLBFuncDesc
*pFDesc
;
6922 const TLBVarDesc
*pVDesc
;
6923 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6924 " HelpContext(%p) HelpFile(%p)\n",
6925 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6926 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6928 *pBstrName
=SysAllocString(This
->Name
);
6930 *pBstrDocString
=SysAllocString(This
->DocString
);
6932 *pdwHelpContext
=This
->dwHelpContext
;
6934 *pBstrHelpFile
=SysAllocString(This
->pTypeLib
->HelpFile
);
6936 }else {/* for a member */
6937 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
6940 *pBstrName
= SysAllocString(pFDesc
->Name
);
6942 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6944 *pdwHelpContext
=pFDesc
->helpcontext
;
6947 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
6950 *pBstrName
= SysAllocString(pVDesc
->Name
);
6952 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6954 *pdwHelpContext
=pVDesc
->HelpContext
;
6956 *pBstrHelpFile
= SysAllocString(This
->pTypeLib
->HelpFile
);
6961 if(This
->impltypes
&&
6962 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6963 /* recursive search */
6966 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6967 if(SUCCEEDED(result
)) {
6968 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6969 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6970 ITypeInfo_Release(pTInfo
);
6973 WARN("Could not search inherited interface!\n");
6976 WARN("member %d not found\n", memid
);
6977 return TYPE_E_ELEMENTNOTFOUND
;
6980 /* ITypeInfo::GetDllEntry
6982 * Retrieves a description or specification of an entry point for a function
6985 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6986 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6989 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6990 const TLBFuncDesc
*pFDesc
;
6992 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6994 if (pBstrDllName
) *pBstrDllName
= NULL
;
6995 if (pBstrName
) *pBstrName
= NULL
;
6996 if (pwOrdinal
) *pwOrdinal
= 0;
6998 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6999 return TYPE_E_BADMODULEKIND
;
7001 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
7003 dump_TypeInfo(This
);
7005 dump_TLBFuncDescOne(pFDesc
);
7008 *pBstrDllName
= SysAllocString(This
->DllName
);
7010 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7012 *pBstrName
= SysAllocString(pFDesc
->Entry
);
7020 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7023 return TYPE_E_ELEMENTNOTFOUND
;
7026 /* internal function to make the inherited interfaces' methods appear
7027 * part of the interface */
7028 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7029 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7031 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7034 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7036 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7038 ITypeInfo
*pSubTypeInfo
;
7040 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7044 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7046 ITypeInfo_Release(pSubTypeInfo
);
7050 *hRefType
-= DISPATCH_HREF_OFFSET
;
7052 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7053 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7058 /* ITypeInfo::GetRefTypeInfo
7060 * If a type description references other type descriptions, it retrieves
7061 * the referenced type descriptions.
7063 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7066 ITypeInfo
**ppTInfo
)
7068 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7069 HRESULT result
= E_FAIL
;
7072 return E_INVALIDARG
;
7074 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
7076 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
7077 ITypeInfo_AddRef(*ppTInfo
);
7080 else if (hRefType
== -1 &&
7081 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
7082 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
7084 /* when we meet a DUAL dispinterface, we must create the interface
7087 ITypeInfoImpl
*pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7090 /* the interface version contains the same information as the dispinterface
7091 * copy the contents of the structs.
7093 *pTypeInfoImpl
= *This
;
7094 pTypeInfoImpl
->ref
= 0;
7096 /* change the type to interface */
7097 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7099 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
7101 /* the AddRef implicitly adds a reference to the parent typelib, which
7102 * stops the copied data from being destroyed until the new typeinfo's
7103 * refcount goes to zero, but we need to signal to the new instance to
7104 * not free its data structures when it is destroyed */
7105 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7107 ITypeInfo_AddRef(*ppTInfo
);
7111 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
7112 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
))
7114 HREFTYPE href_dispatch
= hRefType
;
7115 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7117 TLBRefType
*ref_type
;
7120 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7122 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== hRefType
)
7125 *ppTInfo
= (ITypeInfo
*)This
->pTypeLib
->typeinfos
[i
];
7126 ITypeInfo_AddRef(*ppTInfo
);
7131 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7133 if(ref_type
->reference
== hRefType
)
7136 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7138 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7141 if(hRefType
!= -1) {
7142 ITypeLib
*pTLib
= NULL
;
7144 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7146 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7148 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7149 TRACE("typeinfo in imported typelib that is already loaded\n");
7150 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7151 ITypeLib_AddRef(pTLib
);
7154 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7155 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
7156 ref_type
->pImpTLInfo
->wVersionMajor
,
7157 ref_type
->pImpTLInfo
->wVersionMinor
,
7158 ref_type
->pImpTLInfo
->lcid
,
7161 if(FAILED(result
)) {
7162 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
7163 result
=LoadTypeLib(libnam
, &pTLib
);
7164 SysFreeString(libnam
);
7166 if(SUCCEEDED(result
)) {
7167 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7168 ITypeLib_AddRef(pTLib
);
7172 if(SUCCEEDED(result
)) {
7173 if(ref_type
->index
== TLB_REF_USE_GUID
)
7174 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, &ref_type
->guid
, ppTInfo
);
7176 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7179 ITypeLib_Release(pTLib
);
7184 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7185 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7189 /* ITypeInfo::AddressOfMember
7191 * Retrieves the addresses of static functions or variables, such as those
7194 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7195 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7197 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7203 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7205 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7209 module
= LoadLibraryW(dll
);
7212 ERR("couldn't load %s\n", debugstr_w(dll
));
7214 SysFreeString(entry
);
7215 return STG_E_FILENOTFOUND
;
7217 /* FIXME: store library somewhere where we can free it */
7222 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7223 entryA
= heap_alloc(len
);
7224 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7226 *ppv
= GetProcAddress(module
, entryA
);
7228 ERR("function not found %s\n", debugstr_a(entryA
));
7234 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7236 ERR("function not found %d\n", ordinal
);
7240 SysFreeString(entry
);
7243 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7248 /* ITypeInfo::CreateInstance
7250 * Creates a new instance of a type that describes a component object class
7253 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7254 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7256 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7260 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7266 WARN("Not able to aggregate\n");
7267 return CLASS_E_NOAGGREGATION
;
7270 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7271 if(FAILED(hr
)) return hr
;
7273 if(pTA
->typekind
!= TKIND_COCLASS
)
7275 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7281 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7284 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7285 TRACE("GetActiveObject rets %08x\n", hr
);
7288 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7289 IUnknown_Release(pUnk
);
7294 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7295 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7299 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7303 /* ITypeInfo::GetMops
7305 * Retrieves marshalling information.
7307 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7310 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7311 FIXME("(%p %d) stub!\n", This
, memid
);
7316 /* ITypeInfo::GetContainingTypeLib
7318 * Retrieves the containing type library and the index of the type description
7319 * within that type library.
7321 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7322 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7324 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7326 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7328 *pIndex
=This
->index
;
7329 TRACE("returning pIndex=%d\n", *pIndex
);
7333 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7334 ITypeLib_AddRef(*ppTLib
);
7335 TRACE("returning ppTLib=%p\n", *ppTLib
);
7341 /* ITypeInfo::ReleaseTypeAttr
7343 * Releases a TYPEATTR previously returned by GetTypeAttr.
7346 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7347 TYPEATTR
* pTypeAttr
)
7349 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7350 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7351 heap_free(pTypeAttr
);
7354 /* ITypeInfo::ReleaseFuncDesc
7356 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7358 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7360 FUNCDESC
*pFuncDesc
)
7362 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7365 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7367 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7368 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7369 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7371 SysFreeString((BSTR
)pFuncDesc
);
7374 /* ITypeInfo::ReleaseVarDesc
7376 * Releases a VARDESC previously returned by GetVarDesc.
7378 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7381 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7382 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7384 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
7385 if (pVarDesc
->varkind
== VAR_CONST
)
7386 VariantClear(pVarDesc
->u
.lpvarValue
);
7387 SysFreeString((BSTR
)pVarDesc
);
7390 /* ITypeInfo2::GetTypeKind
7392 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7395 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7396 TYPEKIND
*pTypeKind
)
7398 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7399 *pTypeKind
=This
->TypeAttr
.typekind
;
7400 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7404 /* ITypeInfo2::GetTypeFlags
7406 * Returns the type flags without any allocations. This returns a DWORD type
7407 * flag, which expands the type flags without growing the TYPEATTR (type
7411 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7413 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7414 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
7415 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7419 /* ITypeInfo2::GetFuncIndexOfMemId
7420 * Binds to a specific member based on a known DISPID, where the member name
7421 * is not known (for example, when binding to a default member).
7424 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7425 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7427 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7431 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7432 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7433 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7436 if(fdc
< This
->TypeAttr
.cFuncs
) {
7440 result
= TYPE_E_ELEMENTNOTFOUND
;
7442 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7443 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7447 /* TypeInfo2::GetVarIndexOfMemId
7449 * Binds to a specific member based on a known DISPID, where the member name
7450 * is not known (for example, when binding to a default member).
7453 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7454 MEMBERID memid
, UINT
*pVarIndex
)
7456 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7457 TLBVarDesc
*pVarInfo
;
7459 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7461 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7463 return TYPE_E_ELEMENTNOTFOUND
;
7465 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7470 /* ITypeInfo2::GetCustData
7472 * Gets the custom data
7474 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7479 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7480 TLBCustData
*pCData
;
7482 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7484 if(!guid
|| !pVarVal
)
7485 return E_INVALIDARG
;
7487 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
7489 VariantInit( pVarVal
);
7491 VariantCopy( pVarVal
, &pCData
->data
);
7493 VariantClear( pVarVal
);
7497 /* ITypeInfo2::GetFuncCustData
7499 * Gets the custom data
7501 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7507 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7508 TLBCustData
*pCData
;
7509 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7511 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7513 if(index
>= This
->TypeAttr
.cFuncs
)
7514 return TYPE_E_ELEMENTNOTFOUND
;
7516 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7518 return TYPE_E_ELEMENTNOTFOUND
;
7520 VariantInit(pVarVal
);
7521 VariantCopy(pVarVal
, &pCData
->data
);
7526 /* ITypeInfo2::GetParamCustData
7528 * Gets the custom data
7530 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7537 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7538 TLBCustData
*pCData
;
7539 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7541 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7542 debugstr_guid(guid
), pVarVal
);
7544 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7545 return TYPE_E_ELEMENTNOTFOUND
;
7547 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7548 return TYPE_E_ELEMENTNOTFOUND
;
7550 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7552 return TYPE_E_ELEMENTNOTFOUND
;
7554 VariantInit(pVarVal
);
7555 VariantCopy(pVarVal
, &pCData
->data
);
7560 /* ITypeInfo2::GetVarCustData
7562 * Gets the custom data
7564 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7570 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7571 TLBCustData
*pCData
;
7572 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7574 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7576 if(index
>= This
->TypeAttr
.cVars
)
7577 return TYPE_E_ELEMENTNOTFOUND
;
7579 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7581 return TYPE_E_ELEMENTNOTFOUND
;
7583 VariantInit(pVarVal
);
7584 VariantCopy(pVarVal
, &pCData
->data
);
7589 /* ITypeInfo2::GetImplCustData
7591 * Gets the custom data
7593 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7599 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7600 TLBCustData
*pCData
;
7601 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7603 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7605 if(index
>= This
->TypeAttr
.cImplTypes
)
7606 return TYPE_E_ELEMENTNOTFOUND
;
7608 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7610 return TYPE_E_ELEMENTNOTFOUND
;
7612 VariantInit(pVarVal
);
7613 VariantCopy(pVarVal
, &pCData
->data
);
7618 /* ITypeInfo2::GetDocumentation2
7620 * Retrieves the documentation string, the complete Help file name and path,
7621 * the localization context to use, and the context ID for the library Help
7622 * topic in the Help file.
7625 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7629 BSTR
*pbstrHelpString
,
7630 DWORD
*pdwHelpStringContext
,
7631 BSTR
*pbstrHelpStringDll
)
7633 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7634 const TLBFuncDesc
*pFDesc
;
7635 const TLBVarDesc
*pVDesc
;
7636 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7637 "HelpStringContext(%p) HelpStringDll(%p)\n",
7638 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7639 pbstrHelpStringDll
);
7640 /* the help string should be obtained from the helpstringdll,
7641 * using the _DLLGetDocumentation function, based on the supplied
7642 * lcid. Nice to do sometime...
7644 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7646 *pbstrHelpString
=SysAllocString(This
->Name
);
7647 if(pdwHelpStringContext
)
7648 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7649 if(pbstrHelpStringDll
)
7650 *pbstrHelpStringDll
=
7651 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7653 }else {/* for a member */
7654 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
7657 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
7658 if(pdwHelpStringContext
)
7659 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7660 if(pbstrHelpStringDll
)
7661 *pbstrHelpStringDll
=
7662 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7665 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7668 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
7669 if(pdwHelpStringContext
)
7670 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7671 if(pbstrHelpStringDll
)
7672 *pbstrHelpStringDll
=
7673 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7677 return TYPE_E_ELEMENTNOTFOUND
;
7680 /* ITypeInfo2::GetAllCustData
7682 * Gets all custom data items for the Type info.
7685 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7687 CUSTDATA
*pCustData
)
7689 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7691 TRACE("%p %p\n", This
, pCustData
);
7693 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
7696 /* ITypeInfo2::GetAllFuncCustData
7698 * Gets all custom data items for the specified Function
7701 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7704 CUSTDATA
*pCustData
)
7706 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7707 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7709 TRACE("%p %u %p\n", This
, index
, pCustData
);
7711 if(index
>= This
->TypeAttr
.cFuncs
)
7712 return TYPE_E_ELEMENTNOTFOUND
;
7714 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
7717 /* ITypeInfo2::GetAllParamCustData
7719 * Gets all custom data items for the Functions
7722 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7723 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7725 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7726 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7728 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
7730 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7731 return TYPE_E_ELEMENTNOTFOUND
;
7733 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7734 return TYPE_E_ELEMENTNOTFOUND
;
7736 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
7739 /* ITypeInfo2::GetAllVarCustData
7741 * Gets all custom data items for the specified Variable
7744 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7745 UINT index
, CUSTDATA
*pCustData
)
7747 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7748 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
7750 TRACE("%p %u %p\n", This
, index
, pCustData
);
7752 if(index
>= This
->TypeAttr
.cVars
)
7753 return TYPE_E_ELEMENTNOTFOUND
;
7755 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
7758 /* ITypeInfo2::GetAllImplCustData
7760 * Gets all custom data items for the specified implementation type
7763 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7766 CUSTDATA
*pCustData
)
7768 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7769 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7771 TRACE("%p %u %p\n", This
, index
, pCustData
);
7773 if(index
>= This
->TypeAttr
.cImplTypes
)
7774 return TYPE_E_ELEMENTNOTFOUND
;
7776 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
7779 static const ITypeInfo2Vtbl tinfvt
=
7782 ITypeInfo_fnQueryInterface
,
7784 ITypeInfo_fnRelease
,
7786 ITypeInfo_fnGetTypeAttr
,
7787 ITypeInfo_fnGetTypeComp
,
7788 ITypeInfo_fnGetFuncDesc
,
7789 ITypeInfo_fnGetVarDesc
,
7790 ITypeInfo_fnGetNames
,
7791 ITypeInfo_fnGetRefTypeOfImplType
,
7792 ITypeInfo_fnGetImplTypeFlags
,
7793 ITypeInfo_fnGetIDsOfNames
,
7795 ITypeInfo_fnGetDocumentation
,
7796 ITypeInfo_fnGetDllEntry
,
7797 ITypeInfo_fnGetRefTypeInfo
,
7798 ITypeInfo_fnAddressOfMember
,
7799 ITypeInfo_fnCreateInstance
,
7800 ITypeInfo_fnGetMops
,
7801 ITypeInfo_fnGetContainingTypeLib
,
7802 ITypeInfo_fnReleaseTypeAttr
,
7803 ITypeInfo_fnReleaseFuncDesc
,
7804 ITypeInfo_fnReleaseVarDesc
,
7806 ITypeInfo2_fnGetTypeKind
,
7807 ITypeInfo2_fnGetTypeFlags
,
7808 ITypeInfo2_fnGetFuncIndexOfMemId
,
7809 ITypeInfo2_fnGetVarIndexOfMemId
,
7810 ITypeInfo2_fnGetCustData
,
7811 ITypeInfo2_fnGetFuncCustData
,
7812 ITypeInfo2_fnGetParamCustData
,
7813 ITypeInfo2_fnGetVarCustData
,
7814 ITypeInfo2_fnGetImplTypeCustData
,
7815 ITypeInfo2_fnGetDocumentation2
,
7816 ITypeInfo2_fnGetAllCustData
,
7817 ITypeInfo2_fnGetAllFuncCustData
,
7818 ITypeInfo2_fnGetAllParamCustData
,
7819 ITypeInfo2_fnGetAllVarCustData
,
7820 ITypeInfo2_fnGetAllImplTypeCustData
,
7823 /******************************************************************************
7824 * CreateDispTypeInfo [OLEAUT32.31]
7826 * Build type information for an object so it can be called through an
7827 * IDispatch interface.
7830 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7831 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7834 * This call allows an objects methods to be accessed through IDispatch, by
7835 * building an ITypeInfo object that IDispatch can use to call through.
7837 HRESULT WINAPI
CreateDispTypeInfo(
7838 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7839 LCID lcid
, /* [I] Locale Id */
7840 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7842 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7843 ITypeLibImpl
*pTypeLibImpl
;
7844 unsigned int param
, func
;
7845 TLBFuncDesc
*pFuncDesc
;
7849 pTypeLibImpl
= TypeLibImpl_Constructor();
7850 if (!pTypeLibImpl
) return E_FAIL
;
7852 pTypeLibImpl
->TypeInfoCount
= 2;
7853 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
7855 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
7856 pTIIface
->pTypeLib
= pTypeLibImpl
;
7857 pTIIface
->index
= 0;
7858 pTIIface
->Name
= NULL
;
7859 pTIIface
->dwHelpContext
= -1;
7860 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7861 pTIIface
->TypeAttr
.lcid
= lcid
;
7862 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7863 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7864 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7865 pTIIface
->TypeAttr
.cbAlignment
= 2;
7866 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7867 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7868 pTIIface
->TypeAttr
.cFuncs
= 0;
7869 pTIIface
->TypeAttr
.cImplTypes
= 0;
7870 pTIIface
->TypeAttr
.cVars
= 0;
7871 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7873 pTIIface
->funcdescs
= TLBFuncDesc_Constructor(pidata
->cMembers
);
7874 pFuncDesc
= pTIIface
->funcdescs
;
7875 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7876 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7877 pFuncDesc
->Name
= SysAllocString(md
->szName
);
7878 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
7879 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
7880 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
7881 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
7882 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
7883 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
7884 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
7885 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
7886 pFuncDesc
->funcdesc
.cScodes
= 0;
7887 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
7888 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7889 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7890 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7891 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7892 md
->cArgs
* sizeof(ELEMDESC
));
7893 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
7894 for(param
= 0; param
< md
->cArgs
; param
++) {
7895 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7896 pFuncDesc
->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7898 pFuncDesc
->helpcontext
= 0;
7899 pFuncDesc
->HelpStringContext
= 0;
7900 pFuncDesc
->HelpString
= NULL
;
7901 pFuncDesc
->Entry
= NULL
;
7902 list_init(&pFuncDesc
->custdata_list
);
7903 pTIIface
->TypeAttr
.cFuncs
++;
7907 dump_TypeInfo(pTIIface
);
7909 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
7910 pTIClass
->pTypeLib
= pTypeLibImpl
;
7911 pTIClass
->index
= 1;
7912 pTIClass
->Name
= NULL
;
7913 pTIClass
->dwHelpContext
= -1;
7914 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7915 pTIClass
->TypeAttr
.lcid
= lcid
;
7916 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7917 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7918 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7919 pTIClass
->TypeAttr
.cbAlignment
= 2;
7920 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7921 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7922 pTIClass
->TypeAttr
.cFuncs
= 0;
7923 pTIClass
->TypeAttr
.cImplTypes
= 1;
7924 pTIClass
->TypeAttr
.cVars
= 0;
7925 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7927 pTIClass
->impltypes
= TLBImplType_Constructor(1);
7929 ref
= heap_alloc_zero(sizeof(*ref
));
7930 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7931 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7933 dump_TypeInfo(pTIClass
);
7935 *pptinfo
= (ITypeInfo
*)pTIClass
;
7937 ITypeInfo_AddRef(*pptinfo
);
7938 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
7944 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7946 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7948 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7951 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7953 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7955 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7958 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7960 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7962 return ITypeInfo_Release((ITypeInfo
*)This
);
7965 static HRESULT WINAPI
ITypeComp_fnBind(
7970 ITypeInfo
** ppTInfo
,
7971 DESCKIND
* pDescKind
,
7974 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7975 const TLBFuncDesc
*pFDesc
;
7976 const TLBVarDesc
*pVDesc
;
7977 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7980 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7982 *pDescKind
= DESCKIND_NONE
;
7983 pBindPtr
->lpfuncdesc
= NULL
;
7986 for(fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7987 pFDesc
= &This
->funcdescs
[fdc
];
7988 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7989 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7992 /* name found, but wrong flags */
7993 hr
= TYPE_E_TYPEMISMATCH
;
7997 if (fdc
< This
->TypeAttr
.cFuncs
)
7999 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8001 &pBindPtr
->lpfuncdesc
,
8002 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
8005 *pDescKind
= DESCKIND_FUNCDESC
;
8006 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8007 ITypeInfo_AddRef(*ppTInfo
);
8010 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, szName
);
8012 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8015 *pDescKind
= DESCKIND_VARDESC
;
8016 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8017 ITypeInfo_AddRef(*ppTInfo
);
8021 /* FIXME: search each inherited interface, not just the first */
8022 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8023 /* recursive search */
8027 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8030 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8031 ITypeInfo_Release(pTInfo
);
8035 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8036 ITypeComp_Release(pTComp
);
8039 WARN("Could not search inherited interface!\n");
8041 if (hr
== DISP_E_MEMBERNOTFOUND
)
8043 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8047 static HRESULT WINAPI
ITypeComp_fnBindType(
8051 ITypeInfo
** ppTInfo
,
8052 ITypeComp
** ppTComp
)
8054 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8056 /* strange behaviour (does nothing) but like the
8059 if (!ppTInfo
|| !ppTComp
)
8068 static const ITypeCompVtbl tcompvt
=
8071 ITypeComp_fnQueryInterface
,
8073 ITypeComp_fnRelease
,
8076 ITypeComp_fnBindType
8079 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8080 REFIID riid
, void **object
)
8082 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8084 return ITypeLib2_QueryInterface((ITypeLib2
*)This
, riid
, object
);
8087 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8089 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8091 return ITypeLib2_AddRef((ITypeLib2
*)This
);
8094 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8096 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8098 return ITypeLib2_Release((ITypeLib2
*)This
);
8101 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8102 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8104 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8105 FIXME("%p %s %d %p - stub\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8109 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8112 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8114 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8117 return E_INVALIDARG
;
8119 SysFreeString(This
->Name
);
8120 This
->Name
= SysAllocString(name
);
8125 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8126 WORD majorVerNum
, WORD minorVerNum
)
8128 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8130 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8132 This
->LibAttr
.wMajorVerNum
= majorVerNum
;
8133 This
->LibAttr
.wMinorVerNum
= minorVerNum
;
8138 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8141 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8143 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8145 memcpy(&This
->LibAttr
.guid
, guid
, sizeof(GUID
));
8150 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8153 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8155 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8158 return E_INVALIDARG
;
8160 SysFreeString(This
->DocString
);
8161 This
->DocString
= SysAllocString(doc
);
8166 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8167 LPOLESTR helpFileName
)
8169 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8171 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8174 return E_INVALIDARG
;
8176 SysFreeString(This
->HelpFile
);
8177 This
->HelpFile
= SysAllocString(helpFileName
);
8182 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8185 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8187 TRACE("%p %d\n", This
, helpContext
);
8189 This
->dwHelpContext
= helpContext
;
8194 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8197 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8199 TRACE("%p %x\n", This
, lcid
);
8201 This
->LibAttr
.lcid
= lcid
;
8206 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8209 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8211 TRACE("%p %x\n", This
, libFlags
);
8213 This
->LibAttr
.wLibFlags
= libFlags
;
8218 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
8220 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8221 FIXME("%p - stub\n", This
);
8225 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
8228 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8229 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
8233 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
8234 REFGUID guid
, VARIANT
*varVal
)
8236 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8237 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
8241 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
8242 ULONG helpStringContext
)
8244 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8245 FIXME("%p %u - stub\n", This
, helpStringContext
);
8249 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
8252 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8253 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
8256 return E_INVALIDARG
;
8258 SysFreeString(This
->HelpStringDll
);
8259 This
->HelpStringDll
= SysAllocString(filename
);
8264 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
8265 ICreateTypeLib2_fnQueryInterface
,
8266 ICreateTypeLib2_fnAddRef
,
8267 ICreateTypeLib2_fnRelease
,
8268 ICreateTypeLib2_fnCreateTypeInfo
,
8269 ICreateTypeLib2_fnSetName
,
8270 ICreateTypeLib2_fnSetVersion
,
8271 ICreateTypeLib2_fnSetGuid
,
8272 ICreateTypeLib2_fnSetDocString
,
8273 ICreateTypeLib2_fnSetHelpFileName
,
8274 ICreateTypeLib2_fnSetHelpContext
,
8275 ICreateTypeLib2_fnSetLcid
,
8276 ICreateTypeLib2_fnSetLibFlags
,
8277 ICreateTypeLib2_fnSaveAllChanges
,
8278 ICreateTypeLib2_fnDeleteTypeInfo
,
8279 ICreateTypeLib2_fnSetCustData
,
8280 ICreateTypeLib2_fnSetHelpStringContext
,
8281 ICreateTypeLib2_fnSetHelpStringDll
8284 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
8285 REFIID riid
, void **object
)
8287 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8289 return ITypeInfo2_QueryInterface((ITypeInfo2
*)This
, riid
, object
);
8292 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
8294 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8296 return ITypeInfo2_AddRef((ITypeInfo2
*)This
);
8299 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
8301 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8303 return ITypeInfo2_Release((ITypeInfo2
*)This
);
8306 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
8309 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8310 FIXME("%p %s - stub\n", This
, debugstr_guid(guid
));
8314 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
8317 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8318 FIXME("%p %x - stub\n", This
, typeFlags
);
8322 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
8325 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8326 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(strDoc
));
8330 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
8333 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8334 FIXME("%p %d - stub\n", This
, helpContext
);
8338 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
8339 WORD majorVerNum
, WORD minorVerNum
)
8341 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8342 FIXME("%p %d %d - stub\n", This
, majorVerNum
, minorVerNum
);
8346 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
8347 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
8349 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8350 FIXME("%p %p %p - stub\n", This
, typeInfo
, refType
);
8354 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
8355 UINT index
, FUNCDESC
*funcDesc
)
8357 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8358 FIXME("%p %u %p - stub\n", This
, index
, funcDesc
);
8362 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
8363 UINT index
, HREFTYPE refType
)
8365 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8366 FIXME("%p %u %d - stub\n", This
, index
, refType
);
8370 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
8371 UINT index
, INT implTypeFlags
)
8373 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8374 FIXME("%p %u %x - stub\n", This
, index
, implTypeFlags
);
8378 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
8381 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8382 FIXME("%p %d - stub\n", This
, alignment
);
8386 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
8389 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8390 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(schema
));
8394 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
8395 UINT index
, VARDESC
*varDesc
)
8397 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8398 FIXME("%p %u %p - stub\n", This
, index
, varDesc
);
8402 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
8403 UINT index
, LPOLESTR
*names
, UINT numNames
)
8405 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8406 FIXME("%p %u %p %u - stub\n", This
, index
, names
, numNames
);
8410 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
8411 UINT index
, LPOLESTR name
)
8413 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8414 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(name
));
8418 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
8419 TYPEDESC
*tdescAlias
)
8421 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8422 FIXME("%p %p - stub\n", This
, tdescAlias
);
8426 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
8427 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
8429 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8430 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
8434 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
8435 UINT index
, LPOLESTR docString
)
8437 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8438 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
8442 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
8443 UINT index
, LPOLESTR docString
)
8445 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8446 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
8450 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
8451 UINT index
, DWORD helpContext
)
8453 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8454 FIXME("%p %u %d - stub\n", This
, index
, helpContext
);
8458 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
8459 UINT index
, DWORD helpContext
)
8461 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8462 FIXME("%p %u %d - stub\n", This
, index
, helpContext
);
8466 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
8467 UINT index
, BSTR bstrMops
)
8469 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8470 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
8474 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
8477 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8478 FIXME("%p %p - stub\n", This
, idlDesc
);
8482 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
8484 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8485 FIXME("%p - stub\n", This
);
8489 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
8492 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8493 FIXME("%p %u - stub\n", This
, index
);
8497 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
8498 MEMBERID memid
, INVOKEKIND invKind
)
8500 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8501 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
8505 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
8508 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8509 FIXME("%p %u - stub\n", This
, index
);
8513 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
8516 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8517 FIXME("%p %x - stub\n", This
, memid
);
8521 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
8524 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8525 FIXME("%p %u - stub\n", This
, index
);
8529 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
8530 REFGUID guid
, VARIANT
*varVal
)
8532 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8533 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
8537 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
8538 UINT index
, REFGUID guid
, VARIANT
*varVal
)
8540 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8541 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
8545 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
8546 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
8548 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8549 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
8553 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
8554 UINT index
, REFGUID guid
, VARIANT
*varVal
)
8556 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8557 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
8561 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
8562 UINT index
, REFGUID guid
, VARIANT
*varVal
)
8564 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8565 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
8569 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
8570 ULONG helpStringContext
)
8572 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8573 FIXME("%p %u - stub\n", This
, helpStringContext
);
8577 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
8578 UINT index
, ULONG helpStringContext
)
8580 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8581 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
8585 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
8586 UINT index
, ULONG helpStringContext
)
8588 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8589 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
8593 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
8595 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8596 FIXME("%p - stub\n", This
);
8600 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
8603 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8604 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
8608 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
8609 ICreateTypeInfo2_fnQueryInterface
,
8610 ICreateTypeInfo2_fnAddRef
,
8611 ICreateTypeInfo2_fnRelease
,
8612 ICreateTypeInfo2_fnSetGuid
,
8613 ICreateTypeInfo2_fnSetTypeFlags
,
8614 ICreateTypeInfo2_fnSetDocString
,
8615 ICreateTypeInfo2_fnSetHelpContext
,
8616 ICreateTypeInfo2_fnSetVersion
,
8617 ICreateTypeInfo2_fnAddRefTypeInfo
,
8618 ICreateTypeInfo2_fnAddFuncDesc
,
8619 ICreateTypeInfo2_fnAddImplType
,
8620 ICreateTypeInfo2_fnSetImplTypeFlags
,
8621 ICreateTypeInfo2_fnSetAlignment
,
8622 ICreateTypeInfo2_fnSetSchema
,
8623 ICreateTypeInfo2_fnAddVarDesc
,
8624 ICreateTypeInfo2_fnSetFuncAndParamNames
,
8625 ICreateTypeInfo2_fnSetVarName
,
8626 ICreateTypeInfo2_fnSetTypeDescAlias
,
8627 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
8628 ICreateTypeInfo2_fnSetFuncDocString
,
8629 ICreateTypeInfo2_fnSetVarDocString
,
8630 ICreateTypeInfo2_fnSetFuncHelpContext
,
8631 ICreateTypeInfo2_fnSetVarHelpContext
,
8632 ICreateTypeInfo2_fnSetMops
,
8633 ICreateTypeInfo2_fnSetTypeIdldesc
,
8634 ICreateTypeInfo2_fnLayOut
,
8635 ICreateTypeInfo2_fnDeleteFuncDesc
,
8636 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
8637 ICreateTypeInfo2_fnDeleteVarDesc
,
8638 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
8639 ICreateTypeInfo2_fnDeleteImplType
,
8640 ICreateTypeInfo2_fnSetCustData
,
8641 ICreateTypeInfo2_fnSetFuncCustData
,
8642 ICreateTypeInfo2_fnSetParamCustData
,
8643 ICreateTypeInfo2_fnSetVarCustData
,
8644 ICreateTypeInfo2_fnSetImplTypeCustData
,
8645 ICreateTypeInfo2_fnSetHelpStringContext
,
8646 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
8647 ICreateTypeInfo2_fnSetVarHelpStringContext
,
8648 ICreateTypeInfo2_fnInvalidate
,
8649 ICreateTypeInfo2_fnSetName