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 typedef struct tagTLBString
{
991 /* internal ITypeLib data */
992 typedef struct tagITypeLibImpl
994 ITypeLib2 ITypeLib2_iface
;
995 ITypeComp ITypeComp_iface
;
996 ICreateTypeLib2 ICreateTypeLib2_iface
;
1006 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1007 * exported to the application as a UNICODE string.
1009 struct list string_list
;
1010 struct list name_list
;
1012 const TLBString
*Name
;
1013 const TLBString
*DocString
;
1014 const TLBString
*HelpFile
;
1015 const TLBString
*HelpStringDll
;
1016 DWORD dwHelpContext
;
1017 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1018 struct tagITypeInfoImpl
**typeinfos
;
1019 struct list custdata_list
;
1020 struct list implib_list
;
1021 int ctTypeDesc
; /* number of items in type desc array */
1022 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1023 library. Only used while reading MSFT
1025 struct list ref_list
; /* list of ref types in this typelib */
1026 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1029 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1035 static const ITypeLib2Vtbl tlbvt
;
1036 static const ITypeCompVtbl tlbtcvt
;
1037 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1039 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1041 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1044 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1046 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1049 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1051 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1054 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1056 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1059 /* ITypeLib methods */
1060 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1061 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1063 /*======================= ITypeInfo implementation =======================*/
1065 /* data for referenced types */
1066 typedef struct tagTLBRefType
1068 INT index
; /* Type index for internal ref or for external ref
1069 it the format is SLTG. -2 indicates to
1073 GUID guid
; /* guid of the referenced type */
1074 /* if index == TLB_REF_USE_GUID */
1076 HREFTYPE reference
; /* The href of this ref */
1077 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1078 TLB_REF_INTERNAL for internal refs
1079 TLB_REF_NOT_FOUND for broken refs */
1084 #define TLB_REF_USE_GUID -2
1086 #define TLB_REF_INTERNAL (void*)-2
1087 #define TLB_REF_NOT_FOUND (void*)-1
1089 /* internal Parameter data */
1090 typedef struct tagTLBParDesc
1092 const TLBString
*Name
;
1093 struct list custdata_list
;
1096 /* internal Function data */
1097 typedef struct tagTLBFuncDesc
1099 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1100 const TLBString
*Name
; /* the name of this function */
1101 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1103 int HelpStringContext
;
1104 const TLBString
*HelpString
;
1105 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1106 struct list custdata_list
;
1109 /* internal Variable data */
1110 typedef struct tagTLBVarDesc
1112 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1113 const TLBString
*Name
; /* the name of this variable */
1115 int HelpStringContext
;
1116 const TLBString
*HelpString
;
1117 struct list custdata_list
;
1120 /* internal implemented interface data */
1121 typedef struct tagTLBImplType
1123 HREFTYPE hRef
; /* hRef of interface */
1124 int implflags
; /* IMPLFLAG_*s */
1125 struct list custdata_list
;
1128 /* internal TypeInfo data */
1129 typedef struct tagITypeInfoImpl
1131 ITypeInfo2 ITypeInfo2_iface
;
1132 ITypeComp ITypeComp_iface
;
1133 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1135 BOOL not_attached_to_typelib
;
1137 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1138 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1139 int index
; /* index in this typelib; */
1140 HREFTYPE hreftype
; /* hreftype for app object binding */
1141 /* type libs seem to store the doc strings in ascii
1142 * so why should we do it in unicode?
1144 const TLBString
*Name
;
1145 const TLBString
*DocString
;
1146 const TLBString
*DllName
;
1147 const TLBString
*Schema
;
1148 DWORD dwHelpContext
;
1149 DWORD dwHelpStringContext
;
1152 TLBFuncDesc
*funcdescs
;
1155 TLBVarDesc
*vardescs
;
1157 /* Implemented Interfaces */
1158 TLBImplType
*impltypes
;
1160 struct list custdata_list
;
1163 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1165 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1168 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1170 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1173 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1175 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1178 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1180 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1183 static const ITypeInfo2Vtbl tinfvt
;
1184 static const ITypeCompVtbl tcompvt
;
1185 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1187 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1188 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1190 typedef struct tagTLBContext
1192 unsigned int oStart
; /* start of TLB in file */
1193 unsigned int pos
; /* current pos */
1194 unsigned int length
; /* total length */
1195 void *mapping
; /* memory mapping */
1196 MSFT_SegDir
* pTblDir
;
1197 ITypeLibImpl
* pLibInfo
;
1201 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1203 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1205 return str
!= NULL
? str
->str
: NULL
;
1208 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1212 return memcmp(left
, str
->str
, len
);
1218 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1219 if (pTD
->vt
& VT_RESERVED
)
1220 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1221 if (pTD
->vt
& VT_BYREF
)
1222 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1223 if (pTD
->vt
& VT_ARRAY
)
1224 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1225 if (pTD
->vt
& VT_VECTOR
)
1226 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1227 switch(pTD
->vt
& VT_TYPEMASK
) {
1228 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1229 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1230 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1231 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1232 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1233 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1234 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1235 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1236 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1237 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1238 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1239 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1240 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1241 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1242 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1243 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1244 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1245 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1246 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1247 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1248 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1249 pTD
->u
.hreftype
); break;
1250 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1251 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1252 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1253 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1255 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1256 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1258 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1259 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1260 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1263 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1267 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1269 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1270 dump_TypeDesc(&edesc
->tdesc
,buf
);
1271 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1272 MESSAGE("\t\tu.paramdesc.wParamFlags");
1273 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1274 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1275 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1276 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1277 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1278 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1279 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1280 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1281 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1283 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1285 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1286 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1287 MESSAGE("Param %d:\n",i
);
1288 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1290 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1291 switch (funcdesc
->funckind
) {
1292 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1293 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1294 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1295 case FUNC_STATIC
: MESSAGE("static");break;
1296 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1297 default: MESSAGE("unknown");break;
1299 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1300 switch (funcdesc
->invkind
) {
1301 case INVOKE_FUNC
: MESSAGE("func");break;
1302 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1303 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1304 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1306 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1307 switch (funcdesc
->callconv
) {
1308 case CC_CDECL
: MESSAGE("cdecl");break;
1309 case CC_PASCAL
: MESSAGE("pascal");break;
1310 case CC_STDCALL
: MESSAGE("stdcall");break;
1311 case CC_SYSCALL
: MESSAGE("syscall");break;
1314 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1315 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1316 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1318 MESSAGE("\telemdescFunc (return value type):\n");
1319 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1322 static const char * const typekind_desc
[] =
1335 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1338 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1339 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1340 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1343 dump_FUNCDESC(&(pfd
->funcdesc
));
1345 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1346 if(pfd
->Entry
== NULL
)
1347 MESSAGE("\tentry: (null)\n");
1348 else if(pfd
->Entry
== (void*)-1)
1349 MESSAGE("\tentry: invalid\n");
1350 else if(IS_INTRESOURCE(pfd
->Entry
))
1351 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1353 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1355 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1359 dump_TLBFuncDescOne(pfd
);
1364 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1368 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1374 static void dump_TLBImpLib(const TLBImpLib
*import
)
1376 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1377 debugstr_w(import
->name
));
1378 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1379 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1382 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1386 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1388 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1389 if(ref
->index
== -1)
1390 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1392 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1394 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1396 TRACE_(typelib
)("in lib\n");
1397 dump_TLBImpLib(ref
->pImpTLInfo
);
1402 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1407 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1408 impl
->hRef
, impl
->implflags
);
1414 static void dump_Variant(const VARIANT
* pvar
)
1418 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1422 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1423 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1425 TRACE(",%p", V_BYREF(pvar
));
1427 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1429 TRACE(",%p", V_ARRAY(pvar
));
1431 else switch (V_TYPE(pvar
))
1433 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1434 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1435 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1436 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1438 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1440 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1441 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1442 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1443 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1444 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1445 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1446 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1447 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1448 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1449 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1450 V_CY(pvar
).s
.Lo
); break;
1452 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1453 TRACE(",<invalid>");
1455 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1456 st
.wHour
, st
.wMinute
, st
.wSecond
);
1460 case VT_USERDEFINED
:
1462 case VT_NULL
: break;
1463 default: TRACE(",?"); break;
1469 static void dump_DispParms(const DISPPARAMS
* pdp
)
1473 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1475 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1477 TRACE("named args:\n");
1478 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1479 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1482 if (pdp
->cArgs
&& pdp
->rgvarg
)
1485 for (index
= 0; index
< pdp
->cArgs
; index
++)
1486 dump_Variant( &pdp
->rgvarg
[index
] );
1490 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1492 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1493 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1494 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1495 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1496 TRACE("fct:%u var:%u impl:%u\n",
1497 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1498 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1499 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1500 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1502 dump_TLBFuncDesc(pty
->funcdescs
, pty
->TypeAttr
.cFuncs
);
1503 dump_TLBVarDesc(pty
->vardescs
, pty
->TypeAttr
.cVars
);
1504 dump_TLBImplType(pty
->impltypes
, pty
->TypeAttr
.cImplTypes
);
1507 static void dump_VARDESC(const VARDESC
*v
)
1509 MESSAGE("memid %d\n",v
->memid
);
1510 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1511 MESSAGE("oInst %d\n",v
->u
.oInst
);
1512 dump_ELEMDESC(&(v
->elemdescVar
));
1513 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1514 MESSAGE("varkind %d\n",v
->varkind
);
1517 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1519 /* VT_LPWSTR is largest type that, may appear in type description */
1520 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1521 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1522 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1523 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1524 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1525 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1526 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1527 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1530 static void TLB_abort(void)
1535 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1537 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1538 if (!ret
) ERR("cannot allocate memory\n");
1542 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1544 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1545 if (!ret
) ERR("cannot allocate memory\n");
1549 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1551 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1554 void heap_free(void *ptr
)
1556 HeapFree(GetProcessHeap(), 0, ptr
);
1559 /* returns the size required for a deep copy of a typedesc into a
1561 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1565 if (alloc_initial_space
)
1566 size
+= sizeof(TYPEDESC
);
1572 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1575 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1576 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1582 /* deep copy a typedesc into a flat buffer */
1583 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1588 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1597 dest
->u
.lptdesc
= buffer
;
1598 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1601 dest
->u
.lpadesc
= buffer
;
1602 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1603 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1604 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1610 /* free custom data allocated by MSFT_CustData */
1611 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1613 TLBCustData
*cd
, *cdn
;
1614 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1616 list_remove(&cd
->entry
);
1617 VariantClear(&cd
->data
);
1622 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1627 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1628 ret
= SysAllocStringLen(NULL
, len
- 1);
1629 if (!ret
) return ret
;
1630 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1634 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1635 UINT n
, MEMBERID memid
)
1638 if(funcdescs
->funcdesc
.memid
== memid
)
1646 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1647 UINT n
, const OLECHAR
*name
)
1650 if(!lstrcmpiW(TLB_get_bstr(funcdescs
->Name
), name
))
1658 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1659 UINT n
, MEMBERID memid
)
1662 if(vardescs
->vardesc
.memid
== memid
)
1670 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1671 UINT n
, const OLECHAR
*name
)
1674 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1682 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1684 TLBCustData
*cust_data
;
1685 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1686 if(IsEqualIID(&cust_data
->guid
, guid
))
1691 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1692 UINT n
, const OLECHAR
*name
)
1695 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1703 static TLBVarDesc
*TLBVarDesc_Constructor(UINT n
)
1707 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1712 list_init(&ret
[n
-1].custdata_list
);
1719 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1723 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1728 list_init(&ret
[n
-1].custdata_list
);
1735 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1737 list_init(&func_desc
->custdata_list
);
1740 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1744 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1749 TLBFuncDesc_Constructor(&ret
[n
-1]);
1756 static void TLBImplType_Constructor(TLBImplType
*impl
)
1758 list_init(&impl
->custdata_list
);
1761 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1765 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1770 TLBImplType_Constructor(&ret
[n
-1]);
1777 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, REFGUID guid
, VARIANT
*var
)
1779 TLBCustData
*cust_data
;
1791 return DISP_E_BADVARTYPE
;
1794 cust_data
= TLB_get_custdata_by_guid(custdata_list
, guid
);
1797 cust_data
= heap_alloc(sizeof(TLBCustData
));
1799 return E_OUTOFMEMORY
;
1801 cust_data
->guid
= *guid
;
1802 VariantInit(&cust_data
->data
);
1804 list_add_tail(custdata_list
, &cust_data
->entry
);
1806 VariantClear(&cust_data
->data
);
1808 return VariantCopy(&cust_data
->data
, var
);
1811 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1815 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1816 if (strcmpW(str
->str
, new_str
) == 0)
1820 str
= heap_alloc(sizeof(TLBString
));
1824 str
->str
= SysAllocString(new_str
);
1830 list_add_tail(string_list
, &str
->entry
);
1835 /**********************************************************************
1837 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1839 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1844 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
1846 if (where
!= DO_NOT_SEEK
)
1848 where
+= pcx
->oStart
;
1849 if (where
> pcx
->length
)
1852 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
1860 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
1862 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1863 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1865 MSFT_Seek(pcx
, where
);
1866 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1867 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1872 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1877 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1878 FromLEDWords(buffer
, ret
);
1883 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1888 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1889 FromLEWords(buffer
, ret
);
1894 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1896 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1897 memset(pGuid
,0, sizeof(GUID
));
1900 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1901 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1902 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1903 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1904 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1907 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1909 MSFT_NameIntro niName
;
1913 ERR_(typelib
)("bad offset %d\n", offset
);
1917 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1918 pcx
->pTblDir
->pNametab
.offset
+offset
);
1920 return niName
.hreftype
;
1923 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
1926 MSFT_NameIntro intro
;
1928 int offs
= 0, lengthInChars
;
1930 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
1934 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
1937 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
1938 intro
.namelen
&= 0xFF;
1939 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
1941 len_piece
= (len_piece
+ 4) & ~0x3;
1945 string
= heap_alloc(len_piece
+ 1);
1946 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
1947 string
[intro
.namelen
] = '\0';
1949 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1950 string
, -1, NULL
, 0);
1951 if (!lengthInChars
) {
1953 return E_UNEXPECTED
;
1956 tlbstr
= heap_alloc(sizeof(TLBString
));
1958 tlbstr
->offset
= offs
;
1959 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1960 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
1964 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
1970 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
1974 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
1975 if (tlbstr
->offset
== offset
) {
1976 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
1984 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
1988 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
1989 if (tlbstr
->offset
== offset
) {
1990 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
1999 * read a value and fill a VARIANT structure
2001 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2005 TRACE_(typelib
)("\n");
2007 if(offset
<0) { /* data are packed in here */
2008 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2009 V_I4(pVar
) = offset
& 0x3ffffff;
2012 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2013 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2014 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2015 switch (V_VT(pVar
)){
2016 case VT_EMPTY
: /* FIXME: is this right? */
2017 case VT_NULL
: /* FIXME: is this right? */
2018 case VT_I2
: /* this should not happen */
2029 case VT_VOID
: /* FIXME: is this right? */
2037 case VT_DECIMAL
: /* FIXME: is this right? */
2040 /* pointer types with known behaviour */
2043 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2046 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
2049 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
2051 nullPos
= MSFT_Tell(pcx
);
2052 size
= nullPos
- origPos
;
2053 MSFT_Seek(pcx
, origPos
);
2055 ptr
= heap_alloc_zero(size
);/* allocate temp buffer */
2056 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
2057 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2058 /* FIXME: do we need a AtoW conversion here? */
2059 V_UNION(pVar
, bstrVal
[size
])='\0';
2060 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2064 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2071 case VT_USERDEFINED
:
2077 case VT_STREAMED_OBJECT
:
2078 case VT_STORED_OBJECT
:
2079 case VT_BLOB_OBJECT
:
2084 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2088 if(size
>0) /* (big|small) endian correct? */
2089 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2093 * create a linked list with custom data
2095 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2101 TRACE_(typelib
)("\n");
2103 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2107 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2108 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2109 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
2110 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2111 list_add_head(custdata_list
, &pNew
->entry
);
2112 offset
= entry
.next
;
2117 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
2121 pTd
->vt
=type
& VT_TYPEMASK
;
2123 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2125 if(pTd
->vt
== VT_USERDEFINED
)
2126 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
2128 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2131 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
2133 /* resolve referenced type if any */
2136 switch (lpTypeDesc
->vt
)
2139 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
2143 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
2146 case VT_USERDEFINED
:
2147 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
2148 lpTypeDesc
->u
.hreftype
);
2160 MSFT_DoFuncs(TLBContext
* pcx
,
2165 TLBFuncDesc
** pptfd
)
2168 * member information is stored in a data structure at offset
2169 * indicated by the memoffset field of the typeinfo structure
2170 * There are several distinctive parts.
2171 * The first part starts with a field that holds the total length
2172 * of this (first) part excluding this field. Then follow the records,
2173 * for each member there is one record.
2175 * The first entry is always the length of the record (including this
2177 * The rest of the record depends on the type of the member. If there is
2178 * a field indicating the member type (function, variable, interface, etc)
2179 * I have not found it yet. At this time we depend on the information
2180 * in the type info and the usual order how things are stored.
2182 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2185 * Third is an equal sized array with file offsets to the name entry
2188 * The fourth and last (?) part is an array with offsets to the records
2189 * in the first part of this file segment.
2192 int infolen
, nameoffset
, reclength
, i
;
2193 int recoffset
= offset
+ sizeof(INT
);
2195 char *recbuf
= heap_alloc(0xffff);
2196 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2197 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2199 TRACE_(typelib
)("\n");
2201 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2203 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2205 for ( i
= 0; i
< cFuncs
; i
++ )
2209 /* name, eventually add to a hash table */
2210 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2211 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2213 /* nameoffset is sometimes -1 on the second half of a propget/propput
2214 * pair of functions */
2215 if ((nameoffset
== -1) && (i
> 0))
2216 ptfd
->Name
= ptfd_prev
->Name
;
2218 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2220 /* read the function information record */
2221 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2223 reclength
&= 0xffff;
2225 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2227 /* size without argument data */
2228 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2230 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2231 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2233 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2234 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2236 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2238 if (pFuncRec
->FKCCIC
& 0x2000 )
2240 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2241 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2242 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2245 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2248 ptfd
->Entry
= (TLBString
*)-1;
2250 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2251 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2253 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2254 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2256 /* fill the FuncDesc Structure */
2257 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2258 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2260 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2261 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2262 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2263 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2264 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2265 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2266 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2270 &ptfd
->funcdesc
.elemdescFunc
.tdesc
,
2272 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2274 /* do the parameters/arguments */
2275 if(pFuncRec
->nrargs
)
2278 MSFT_ParameterInfo paraminfo
;
2280 ptfd
->funcdesc
.lprgelemdescParam
=
2281 heap_alloc_zero(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
2283 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2285 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2286 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2288 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2290 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2297 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2300 if (paraminfo
.oName
== -1)
2301 /* this occurs for [propput] or [propget] methods, so
2302 * we should just set the name of the parameter to the
2303 * name of the method. */
2304 ptfd
->pParamDesc
[j
].Name
= ptfd
->Name
;
2306 ptfd
->pParamDesc
[j
].Name
=
2307 MSFT_ReadName( pcx
, paraminfo
.oName
);
2308 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2310 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
2313 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2314 (pFuncRec
->FKCCIC
& 0x1000) )
2316 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2318 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2320 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2322 pParamDesc
->pparamdescex
= heap_alloc_zero(sizeof(PARAMDESCEX
));
2323 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2325 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2329 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2332 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2333 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2334 pFuncRec
->FKCCIC
& 0x80 )
2337 pFuncRec
->oArgCustData
[j
],
2338 &ptfd
->pParamDesc
[j
].custdata_list
);
2341 /* SEEK value = jump to offset,
2342 * from there jump to the end of record,
2343 * go back by (j-1) arguments
2345 MSFT_ReadLEDWords( ¶minfo
,
2346 sizeof(MSFT_ParameterInfo
), pcx
,
2347 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2348 * sizeof(MSFT_ParameterInfo
)));
2352 /* scode is not used: archaic win16 stuff FIXME: right? */
2353 ptfd
->funcdesc
.cScodes
= 0 ;
2354 ptfd
->funcdesc
.lprgscode
= NULL
;
2358 recoffset
+= reclength
;
2363 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2364 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2366 int infolen
, nameoffset
, reclength
;
2368 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2373 TRACE_(typelib
)("\n");
2375 ptvd
= *pptvd
= TLBVarDesc_Constructor(cVars
);
2376 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2377 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2378 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2379 recoffset
+= offset
+sizeof(INT
);
2380 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2381 /* name, eventually add to a hash table */
2382 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2383 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2384 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2385 /* read the variable information record */
2386 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2388 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2391 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2392 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2394 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2395 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2397 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2398 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2400 /* fill the VarDesc Structure */
2401 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2402 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2403 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2404 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2405 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2406 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2407 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2408 if(pVarRec
->VarKind
== VAR_CONST
){
2409 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2410 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2411 pVarRec
->OffsValue
, pcx
);
2413 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2414 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptvd
->vardesc
.elemdescVar
.tdesc
);
2415 recoffset
+= reclength
;
2419 /* fill in data for a hreftype (offset). When the referenced type is contained
2420 * in the typelib, it's just an (file) offset in the type info base dir.
2421 * If comes from import, it's an offset+1 in the ImpInfo table
2423 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2428 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2430 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2432 if(ref
->reference
== offset
) return;
2435 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2436 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2438 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2439 /* external typelib */
2440 MSFT_ImpInfo impinfo
;
2443 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2445 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2446 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2448 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2449 if(pImpLib
->offset
==impinfo
.oImpFile
)
2452 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2453 ref
->reference
= offset
& (~0x3);
2454 ref
->pImpTLInfo
= pImpLib
;
2455 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2456 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2457 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2458 ref
->index
= TLB_REF_USE_GUID
;
2460 ref
->index
= impinfo
.oGuid
;
2462 ERR("Cannot find a reference\n");
2463 ref
->reference
= -1;
2464 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2467 /* in this typelib */
2468 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2469 ref
->reference
= offset
;
2470 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2474 /* process Implemented Interfaces of a com class */
2475 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2479 MSFT_RefRecord refrec
;
2482 TRACE_(typelib
)("\n");
2484 pTI
->impltypes
= TLBImplType_Alloc(count
);
2485 pImpl
= pTI
->impltypes
;
2486 for(i
=0;i
<count
;i
++){
2487 if(offset
<0) break; /* paranoia */
2488 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2489 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2490 pImpl
->hRef
= refrec
.reftype
;
2491 pImpl
->implflags
=refrec
.flags
;
2492 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2493 offset
=refrec
.onext
;
2498 * process a typeinfo record
2500 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2503 ITypeLibImpl
* pLibInfo
)
2505 MSFT_TypeInfoBase tiBase
;
2506 ITypeInfoImpl
*ptiRet
;
2508 TRACE_(typelib
)("count=%u\n", count
);
2510 ptiRet
= ITypeInfoImpl_Constructor();
2511 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2512 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2514 /* this is where we are coming from */
2515 ptiRet
->pTypeLib
= pLibInfo
;
2516 ptiRet
->index
=count
;
2517 /* fill in the typeattr fields */
2519 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2520 ptiRet
->TypeAttr
.lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2521 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2522 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2523 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2524 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2525 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2526 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2527 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2528 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2529 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2530 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2531 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2532 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2533 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2534 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2537 /* IDLDESC idldescType; *//* never saw this one != zero */
2539 /* name, eventually add to a hash table */
2540 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2541 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2542 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2544 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2545 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2546 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2548 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2549 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2551 /* note: InfoType's Help file and HelpStringDll come from the containing
2552 * library. Further HelpString and Docstring appear to be the same thing :(
2555 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2556 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2557 ptiRet
->TypeAttr
.cVars
,
2558 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2560 if(ptiRet
->TypeAttr
.cVars
>0 )
2561 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2562 ptiRet
->TypeAttr
.cVars
,
2563 tiBase
.memoffset
, &ptiRet
->vardescs
);
2564 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2565 switch(ptiRet
->TypeAttr
.typekind
)
2568 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2571 case TKIND_DISPATCH
:
2572 /* This is not -1 when the interface is a non-base dual interface or
2573 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2574 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2578 if (tiBase
.datatype1
!= -1)
2580 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2581 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2582 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2586 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2587 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2588 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2592 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->custdata_list
);
2594 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2595 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2596 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2597 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2598 if (TRACE_ON(typelib
))
2599 dump_TypeInfo(ptiRet
);
2604 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2607 INT16 len_str
, len_piece
;
2608 int offs
= 0, lengthInChars
;
2610 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2614 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2617 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2618 len_piece
= len_str
+ sizeof(INT16
);
2620 len_piece
= (len_piece
+ 4) & ~0x3;
2624 string
= heap_alloc(len_piece
+ 1);
2625 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2626 string
[len_str
] = '\0';
2628 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2629 string
, -1, NULL
, 0);
2630 if (!lengthInChars
) {
2632 return E_UNEXPECTED
;
2635 tlbstr
= heap_alloc(sizeof(TLBString
));
2637 tlbstr
->offset
= offs
;
2638 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2639 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2643 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2649 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2650 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2651 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2654 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2655 static CRITICAL_SECTION cache_section
;
2656 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2658 0, 0, &cache_section
,
2659 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2660 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2662 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2665 typedef struct TLB_PEFile
2667 IUnknown IUnknown_iface
;
2670 HRSRC typelib_resource
;
2671 HGLOBAL typelib_global
;
2672 LPVOID typelib_base
;
2675 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2677 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2680 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2682 if (IsEqualIID(riid
, &IID_IUnknown
))
2685 IUnknown_AddRef(iface
);
2689 return E_NOINTERFACE
;
2692 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2694 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2695 return InterlockedIncrement(&This
->refs
);
2698 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2700 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2701 ULONG refs
= InterlockedDecrement(&This
->refs
);
2704 if (This
->typelib_global
)
2705 FreeResource(This
->typelib_global
);
2707 FreeLibrary(This
->dll
);
2713 static const IUnknownVtbl TLB_PEFile_Vtable
=
2715 TLB_PEFile_QueryInterface
,
2720 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2723 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2725 This
= heap_alloc(sizeof(TLB_PEFile
));
2727 return E_OUTOFMEMORY
;
2729 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2732 This
->typelib_resource
= NULL
;
2733 This
->typelib_global
= NULL
;
2734 This
->typelib_base
= NULL
;
2736 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2737 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2741 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2742 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2743 if (This
->typelib_resource
)
2745 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2746 if (This
->typelib_global
)
2748 This
->typelib_base
= LockResource(This
->typelib_global
);
2750 if (This
->typelib_base
)
2752 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2753 *ppBase
= This
->typelib_base
;
2754 *ppFile
= &This
->IUnknown_iface
;
2760 TRACE("No TYPELIB resource found\n");
2764 TLB_PEFile_Release(&This
->IUnknown_iface
);
2768 typedef struct TLB_NEFile
2770 IUnknown IUnknown_iface
;
2772 LPVOID typelib_base
;
2775 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2777 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2780 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2782 if (IsEqualIID(riid
, &IID_IUnknown
))
2785 IUnknown_AddRef(iface
);
2789 return E_NOINTERFACE
;
2792 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2794 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2795 return InterlockedIncrement(&This
->refs
);
2798 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2800 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2801 ULONG refs
= InterlockedDecrement(&This
->refs
);
2804 heap_free(This
->typelib_base
);
2810 static const IUnknownVtbl TLB_NEFile_Vtable
=
2812 TLB_NEFile_QueryInterface
,
2817 /***********************************************************************
2818 * read_xx_header [internal]
2820 static int read_xx_header( HFILE lzfd
)
2822 IMAGE_DOS_HEADER mzh
;
2825 LZSeek( lzfd
, 0, SEEK_SET
);
2826 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2828 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2831 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2832 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2835 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2837 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2838 return IMAGE_OS2_SIGNATURE
;
2839 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2840 return IMAGE_NT_SIGNATURE
;
2843 WARN("Can't handle %s files.\n", magic
);
2848 /***********************************************************************
2849 * find_ne_resource [internal]
2851 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2852 DWORD
*resLen
, DWORD
*resOff
)
2854 IMAGE_OS2_HEADER nehd
;
2855 NE_TYPEINFO
*typeInfo
;
2856 NE_NAMEINFO
*nameInfo
;
2862 /* Read in NE header */
2863 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2864 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2866 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2869 TRACE("No resources in NE dll\n" );
2873 /* Read in resource table */
2874 resTab
= heap_alloc( resTabSize
);
2875 if ( !resTab
) return FALSE
;
2877 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2878 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2880 heap_free( resTab
);
2885 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2887 if (!IS_INTRESOURCE(typeid)) /* named type */
2889 BYTE len
= strlen( typeid );
2890 while (typeInfo
->type_id
)
2892 if (!(typeInfo
->type_id
& 0x8000))
2894 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2895 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2897 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2898 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2901 else /* numeric type id */
2903 WORD id
= LOWORD(typeid) | 0x8000;
2904 while (typeInfo
->type_id
)
2906 if (typeInfo
->type_id
== id
) goto found_type
;
2907 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2908 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2911 TRACE("No typeid entry found for %p\n", typeid );
2912 heap_free( resTab
);
2916 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2918 if (!IS_INTRESOURCE(resid
)) /* named resource */
2920 BYTE len
= strlen( resid
);
2921 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2923 BYTE
*p
= resTab
+ nameInfo
->id
;
2924 if (nameInfo
->id
& 0x8000) continue;
2925 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2928 else /* numeric resource id */
2930 WORD id
= LOWORD(resid
) | 0x8000;
2931 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2932 if (nameInfo
->id
== id
) goto found_name
;
2934 TRACE("No resid entry found for %p\n", typeid );
2935 heap_free( resTab
);
2939 /* Return resource data */
2940 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2941 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2943 heap_free( resTab
);
2947 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
2951 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2954 This
= heap_alloc(sizeof(TLB_NEFile
));
2955 if (!This
) return E_OUTOFMEMORY
;
2957 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
2959 This
->typelib_base
= NULL
;
2961 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
2962 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
2964 DWORD reslen
, offset
;
2965 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
2967 This
->typelib_base
= heap_alloc(reslen
);
2968 if( !This
->typelib_base
)
2972 LZSeek( lzfd
, offset
, SEEK_SET
);
2973 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
2975 *ppBase
= This
->typelib_base
;
2976 *pdwTLBLength
= reslen
;
2977 *ppFile
= &This
->IUnknown_iface
;
2983 if( lzfd
>= 0) LZClose( lzfd
);
2984 TLB_NEFile_Release(&This
->IUnknown_iface
);
2988 typedef struct TLB_Mapping
2990 IUnknown IUnknown_iface
;
2994 LPVOID typelib_base
;
2997 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
2999 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3002 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3004 if (IsEqualIID(riid
, &IID_IUnknown
))
3007 IUnknown_AddRef(iface
);
3011 return E_NOINTERFACE
;
3014 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3016 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3017 return InterlockedIncrement(&This
->refs
);
3020 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3022 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3023 ULONG refs
= InterlockedDecrement(&This
->refs
);
3026 if (This
->typelib_base
)
3027 UnmapViewOfFile(This
->typelib_base
);
3029 CloseHandle(This
->mapping
);
3030 if (This
->file
!= INVALID_HANDLE_VALUE
)
3031 CloseHandle(This
->file
);
3037 static const IUnknownVtbl TLB_Mapping_Vtable
=
3039 TLB_Mapping_QueryInterface
,
3044 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3048 This
= heap_alloc(sizeof(TLB_Mapping
));
3050 return E_OUTOFMEMORY
;
3052 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3054 This
->file
= INVALID_HANDLE_VALUE
;
3055 This
->mapping
= NULL
;
3056 This
->typelib_base
= NULL
;
3058 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3059 if (INVALID_HANDLE_VALUE
!= This
->file
)
3061 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3064 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3065 if(This
->typelib_base
)
3067 /* retrieve file size */
3068 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3069 *ppBase
= This
->typelib_base
;
3070 *ppFile
= &This
->IUnknown_iface
;
3076 IUnknown_Release(&This
->IUnknown_iface
);
3077 return TYPE_E_CANTLOADLIBRARY
;
3080 /****************************************************************************
3083 * find the type of the typelib file and map the typelib resource into
3087 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3088 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3090 ITypeLibImpl
*entry
;
3093 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3094 LPVOID pBase
= NULL
;
3095 DWORD dwTLBLength
= 0;
3096 IUnknown
*pFile
= NULL
;
3100 index_str
= strrchrW(pszFileName
, '\\');
3101 if(index_str
&& *++index_str
!= '\0')
3104 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3105 if(*end_ptr
== '\0')
3107 int str_len
= index_str
- pszFileName
- 1;
3109 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3110 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3115 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3117 if(strchrW(file
, '\\'))
3119 lstrcpyW(pszPath
, file
);
3123 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3124 pszPath
[len
] = '\\';
3125 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3129 if(file
!= pszFileName
) heap_free(file
);
3131 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3133 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3134 EnterCriticalSection(&cache_section
);
3135 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3137 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3139 TRACE("cache hit\n");
3140 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3141 ITypeLib2_AddRef(*ppTypeLib
);
3142 LeaveCriticalSection(&cache_section
);
3146 LeaveCriticalSection(&cache_section
);
3148 /* now actually load and parse the typelib */
3150 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3151 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3152 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3153 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3154 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3157 if (dwTLBLength
>= 4)
3159 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3160 if (dwSignature
== MSFT_SIGNATURE
)
3161 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3162 else if (dwSignature
== SLTG_SIGNATURE
)
3163 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3166 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3167 ret
= TYPE_E_CANTLOADLIBRARY
;
3171 ret
= TYPE_E_CANTLOADLIBRARY
;
3172 IUnknown_Release(pFile
);
3176 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3178 TRACE("adding to cache\n");
3179 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3180 lstrcpyW(impl
->path
, pszPath
);
3181 /* We should really canonicalise the path here. */
3182 impl
->index
= index
;
3184 /* FIXME: check if it has added already in the meantime */
3185 EnterCriticalSection(&cache_section
);
3186 list_add_head(&tlb_cache
, &impl
->entry
);
3187 LeaveCriticalSection(&cache_section
);
3193 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3195 ret
= TYPE_E_CANTLOADLIBRARY
;
3202 /*================== ITypeLib(2) Methods ===================================*/
3204 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3206 ITypeLibImpl
* pTypeLibImpl
;
3208 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3209 if (!pTypeLibImpl
) return NULL
;
3211 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3212 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3213 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3214 pTypeLibImpl
->ref
= 1;
3216 list_init(&pTypeLibImpl
->implib_list
);
3217 list_init(&pTypeLibImpl
->custdata_list
);
3218 list_init(&pTypeLibImpl
->name_list
);
3219 list_init(&pTypeLibImpl
->string_list
);
3220 list_init(&pTypeLibImpl
->ref_list
);
3221 pTypeLibImpl
->dispatch_href
= -1;
3223 return pTypeLibImpl
;
3226 /****************************************************************************
3227 * ITypeLib2_Constructor_MSFT
3229 * loading an MSFT typelib from an in-memory image
3231 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3235 MSFT_Header tlbHeader
;
3236 MSFT_SegDir tlbSegDir
;
3237 ITypeLibImpl
* pTypeLibImpl
;
3239 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3241 pTypeLibImpl
= TypeLibImpl_Constructor();
3242 if (!pTypeLibImpl
) return NULL
;
3244 /* get pointer to beginning of typelib data */
3248 cx
.pLibInfo
= pTypeLibImpl
;
3249 cx
.length
= dwTLBLength
;
3252 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3253 TRACE_(typelib
)("header:\n");
3254 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3255 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3256 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3259 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3261 /* there is a small amount of information here until the next important
3263 * the segment directory . Try to calculate the amount of data */
3264 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3266 /* now read the segment directory */
3267 TRACE("read segment directory (at %d)\n",lPSegDir
);
3268 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3269 cx
.pTblDir
= &tlbSegDir
;
3271 /* just check two entries */
3272 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3274 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3275 heap_free(pTypeLibImpl
);
3279 MSFT_ReadAllNames(&cx
);
3280 MSFT_ReadAllStrings(&cx
);
3282 /* now fill our internal data */
3283 /* TLIBATTR fields */
3284 MSFT_ReadGuid(&pTypeLibImpl
->guid
, tlbHeader
.posguid
, &cx
);
3286 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3287 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3288 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3289 pTypeLibImpl
->libflags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3291 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3292 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3294 /* name, eventually add to a hash table */
3295 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3298 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3299 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3301 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3304 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3305 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3308 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3311 if(tlbHeader
.CustomDataOffset
>= 0)
3313 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3316 /* fill in type descriptions */
3317 if(tlbSegDir
.pTypdescTab
.length
> 0)
3319 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3321 pTypeLibImpl
->ctTypeDesc
= cTD
;
3322 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3323 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3326 /* FIXME: add several sanity checks here */
3327 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3328 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3330 /* FIXME: check safearray */
3332 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3334 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3336 else if(td
[0] == VT_CARRAY
)
3338 /* array descr table here */
3339 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3341 else if(td
[0] == VT_USERDEFINED
)
3343 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3345 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3348 /* second time around to fill the array subscript info */
3351 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3352 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3354 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3355 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3358 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3360 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3362 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3364 for(j
= 0; j
<td
[2]; j
++)
3366 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3367 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3368 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3369 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3374 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3375 ERR("didn't find array description data\n");
3380 /* imported type libs */
3381 if(tlbSegDir
.pImpFiles
.offset
>0)
3384 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3387 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3391 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3392 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3393 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3395 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3396 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3397 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3398 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3401 name
= heap_alloc_zero(size
+1);
3402 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3403 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3406 MSFT_ReadGuid(&pImpLib
->guid
, oGuid
, &cx
);
3407 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3409 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3413 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3414 if(pTypeLibImpl
->dispatch_href
!= -1)
3415 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3418 if(tlbHeader
.nrtypeinfos
>= 0 )
3420 ITypeInfoImpl
**ppTI
;
3423 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3425 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3427 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3430 (pTypeLibImpl
->TypeInfoCount
)++;
3434 TRACE("(%p)\n", pTypeLibImpl
);
3435 return &pTypeLibImpl
->ITypeLib2_iface
;
3439 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3445 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3446 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3450 guid
->Data4
[0] = s
>> 8;
3451 guid
->Data4
[1] = s
& 0xff;
3454 for(i
= 0; i
< 6; i
++) {
3455 memcpy(b
, str
+ 24 + 2 * i
, 2);
3456 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3461 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3468 bytelen
= *(const WORD
*)ptr
;
3469 if(bytelen
== 0xffff) return 2;
3471 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3472 tmp_str
= SysAllocStringLen(NULL
, len
);
3474 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3475 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3476 SysFreeString(tmp_str
);
3481 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3486 bytelen
= *(const WORD
*)ptr
;
3487 if(bytelen
== 0xffff) return 2;
3488 *str
= heap_alloc(bytelen
+ 1);
3489 memcpy(*str
, ptr
+ 2, bytelen
);
3490 (*str
)[bytelen
] = '\0';
3494 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3499 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3500 if (tlbstr
->offset
== offset
)
3504 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3505 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3506 SysFreeString(tmp_str
);
3511 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3513 char *ptr
= pLibBlk
;
3516 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3517 FIXME("libblk magic = %04x\n", w
);
3522 if((w
= *(WORD
*)ptr
) != 0xffff) {
3523 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3528 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3530 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3532 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3535 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3538 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3539 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3541 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3544 ptr
+= 4; /* skip res12 */
3546 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3549 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3552 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3555 memcpy(&pTypeLibImpl
->guid
, ptr
, sizeof(GUID
));
3556 ptr
+= sizeof(GUID
);
3558 return ptr
- (char*)pLibBlk
;
3561 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3566 } sltg_ref_lookup_t
;
3568 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3569 HREFTYPE
*typelib_ref
)
3571 if(table
&& typeinfo_ref
< table
->num
)
3573 *typelib_ref
= table
->refs
[typeinfo_ref
];
3577 ERR_(typelib
)("Unable to find reference\n");
3582 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3587 if((*pType
& 0xe00) == 0xe00) {
3589 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3590 pTD
= pTD
->u
.lptdesc
;
3592 switch(*pType
& 0x3f) {
3595 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3596 pTD
= pTD
->u
.lptdesc
;
3599 case VT_USERDEFINED
:
3600 pTD
->vt
= VT_USERDEFINED
;
3601 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3607 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3610 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3612 pTD
->vt
= VT_CARRAY
;
3613 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3614 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3615 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3616 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3618 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3624 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3628 pTD
->vt
= VT_SAFEARRAY
;
3629 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3630 pTD
= pTD
->u
.lptdesc
;
3634 pTD
->vt
= *pType
& 0x3f;
3643 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3644 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3646 /* Handle [in/out] first */
3647 if((*pType
& 0xc000) == 0xc000)
3648 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3649 else if(*pType
& 0x8000)
3650 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3651 else if(*pType
& 0x4000)
3652 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3654 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3657 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3660 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3662 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3666 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3671 TLBRefType
*ref_type
;
3672 sltg_ref_lookup_t
*table
;
3673 HREFTYPE typelib_ref
;
3675 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3676 FIXME("Ref magic = %x\n", pRef
->magic
);
3679 name
= ( (char*)pRef
->names
+ pRef
->number
);
3681 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3682 table
->num
= pRef
->number
>> 3;
3684 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3686 /* We don't want the first href to be 0 */
3687 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3689 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3691 unsigned int lib_offs
, type_num
;
3693 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3695 name
+= SLTG_ReadStringA(name
, &refname
);
3696 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3697 FIXME_(typelib
)("Can't sscanf ref\n");
3698 if(lib_offs
!= 0xffff) {
3701 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3702 if(import
->offset
== lib_offs
)
3705 if(&import
->entry
== &pTL
->implib_list
) {
3706 char fname
[MAX_PATH
+1];
3709 import
= heap_alloc_zero(sizeof(*import
));
3710 import
->offset
= lib_offs
;
3711 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3713 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3714 &import
->wVersionMajor
,
3715 &import
->wVersionMinor
,
3716 &import
->lcid
, fname
) != 4) {
3717 FIXME_(typelib
)("can't sscanf ref %s\n",
3718 pNameTable
+ lib_offs
+ 40);
3720 len
= strlen(fname
);
3721 if(fname
[len
-1] != '#')
3722 FIXME("fname = %s\n", fname
);
3723 fname
[len
-1] = '\0';
3724 import
->name
= TLB_MultiByteToBSTR(fname
);
3725 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3727 ref_type
->pImpTLInfo
= import
;
3729 /* Store a reference to IDispatch */
3730 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
, &IID_StdOle
) && type_num
== 4)
3731 pTL
->dispatch_href
= typelib_ref
;
3733 } else { /* internal ref */
3734 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3736 ref_type
->reference
= typelib_ref
;
3737 ref_type
->index
= type_num
;
3740 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3742 table
->refs
[ref
] = typelib_ref
;
3745 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3746 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3747 dump_TLBRefType(pTL
);
3751 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3752 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3754 SLTG_ImplInfo
*info
;
3755 TLBImplType
*pImplType
;
3756 /* I don't really get this structure, usually it's 0x16 bytes
3757 long, but iuser.tlb contains some that are 0x18 bytes long.
3758 That's ok because we can use the next ptr to jump to the next
3759 one. But how do we know the length of the last one? The WORD
3760 at offs 0x8 might be the clue. For now I'm just assuming that
3761 the last one is the regular 0x16 bytes. */
3763 info
= (SLTG_ImplInfo
*)pBlk
;
3765 pTI
->TypeAttr
.cImplTypes
++;
3766 if(info
->next
== 0xffff)
3768 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3771 info
= (SLTG_ImplInfo
*)pBlk
;
3772 pTI
->impltypes
= TLBImplType_Alloc(pTI
->TypeAttr
.cImplTypes
);
3773 pImplType
= pTI
->impltypes
;
3775 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3776 pImplType
->implflags
= info
->impltypeflags
;
3779 if(info
->next
== 0xffff)
3782 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3783 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3785 info
++; /* see comment at top of function */
3789 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3790 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3792 TLBVarDesc
*pVarDesc
;
3793 const TLBString
*prevName
= NULL
;
3794 SLTG_Variable
*pItem
;
3798 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Constructor(cVars
);
3800 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3801 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3803 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3805 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3806 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3807 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3811 if (pItem
->name
== 0xfffe)
3812 pVarDesc
->Name
= prevName
;
3814 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
3816 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
3817 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3818 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3820 if(pItem
->flags
& 0x02)
3821 pType
= &pItem
->type
;
3823 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3825 if (pItem
->flags
& ~0xda)
3826 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3828 SLTG_DoElem(pType
, pBlk
,
3829 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3831 if (TRACE_ON(typelib
)) {
3833 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3834 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3837 if (pItem
->flags
& 0x40) {
3838 TRACE_(typelib
)("VAR_DISPATCH\n");
3839 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3841 else if (pItem
->flags
& 0x10) {
3842 TRACE_(typelib
)("VAR_CONST\n");
3843 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3844 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3845 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3846 if (pItem
->flags
& 0x08)
3847 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3849 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3855 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3857 TRACE_(typelib
)("len = %u\n", len
);
3858 if (len
== 0xffff) {
3861 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3862 str
= SysAllocStringLen(NULL
, alloc_len
);
3863 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3865 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3866 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3875 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3876 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3879 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3884 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3885 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3886 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3889 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3890 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3892 if (pItem
->flags
& 0x80)
3893 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3895 prevName
= pVarDesc
->Name
;
3897 pTI
->TypeAttr
.cVars
= cVars
;
3900 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3901 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3903 SLTG_Function
*pFunc
;
3905 TLBFuncDesc
*pFuncDesc
;
3907 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
3909 pFuncDesc
= pTI
->funcdescs
;
3910 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
3911 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
3916 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3917 case SLTG_FUNCTION_MAGIC
:
3918 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3920 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3921 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
3923 case SLTG_STATIC_FUNCTION_MAGIC
:
3924 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
3927 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3930 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
3932 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
3933 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
3934 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3935 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3936 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3937 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
3939 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3940 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3942 if(pFunc
->retnextopt
& 0x80)
3943 pType
= &pFunc
->rettype
;
3945 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3947 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
3949 pFuncDesc
->funcdesc
.lprgelemdescParam
=
3950 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
3951 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
3953 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3955 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
3956 char *paramName
= pNameTable
+ *pArg
;
3958 /* If arg type follows then paramName points to the 2nd
3959 letter of the name, else the next WORD is an offset to
3960 the arg type and paramName points to the first letter.
3961 So let's take one char off paramName and see if we're
3962 pointing at an alpha-numeric char. However if *pArg is
3963 0xffff or 0xfffe then the param has no name, the former
3964 meaning that the next WORD is the type, the latter
3965 meaning that the next WORD is an offset to the type. */
3970 else if(*pArg
== 0xfffe) {
3974 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3979 if(HaveOffs
) { /* the next word is an offset to type */
3980 pType
= (WORD
*)(pBlk
+ *pArg
);
3981 SLTG_DoElem(pType
, pBlk
,
3982 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3987 pArg
= SLTG_DoElem(pArg
, pBlk
,
3988 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3991 /* Are we an optional param ? */
3992 if(pFuncDesc
->funcdesc
.cParams
- param
<=
3993 pFuncDesc
->funcdesc
.cParamsOpt
)
3994 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3997 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
3998 paramName
- pNameTable
, pTI
->pTypeLib
);
4000 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4004 pTI
->TypeAttr
.cFuncs
= cFuncs
;
4007 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4008 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4009 SLTG_TypeInfoTail
*pTITail
)
4012 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4014 if(pTIHeader
->href_table
!= 0xffffffff) {
4015 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4021 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4022 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4024 heap_free(ref_lookup
);
4028 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4029 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4030 const SLTG_TypeInfoTail
*pTITail
)
4033 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4035 if(pTIHeader
->href_table
!= 0xffffffff) {
4036 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4042 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4043 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4046 if (pTITail
->funcs_off
!= 0xffff)
4047 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4049 heap_free(ref_lookup
);
4051 if (TRACE_ON(typelib
))
4052 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
4055 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4056 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4057 const SLTG_TypeInfoTail
*pTITail
)
4059 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4062 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4063 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4064 const SLTG_TypeInfoTail
*pTITail
)
4067 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4069 if (pTITail
->simple_alias
) {
4070 /* if simple alias, no more processing required */
4071 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
4075 if(pTIHeader
->href_table
!= 0xffffffff) {
4076 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4080 /* otherwise it is an offset to a type */
4081 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4083 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
4085 heap_free(ref_lookup
);
4088 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4089 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4090 const SLTG_TypeInfoTail
*pTITail
)
4092 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4093 if (pTIHeader
->href_table
!= 0xffffffff)
4094 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4097 if (pTITail
->vars_off
!= 0xffff)
4098 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4100 if (pTITail
->funcs_off
!= 0xffff)
4101 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4103 if (pTITail
->impls_off
!= 0xffff)
4104 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4106 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4107 * of dispinterface functions including the IDispatch ones, so
4108 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4109 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
4111 heap_free(ref_lookup
);
4112 if (TRACE_ON(typelib
))
4113 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
4116 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4117 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4118 const SLTG_TypeInfoTail
*pTITail
)
4120 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4123 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4124 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4125 const SLTG_TypeInfoTail
*pTITail
)
4127 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4128 if (pTIHeader
->href_table
!= 0xffffffff)
4129 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4132 if (pTITail
->vars_off
!= 0xffff)
4133 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4135 if (pTITail
->funcs_off
!= 0xffff)
4136 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4137 heap_free(ref_lookup
);
4138 if (TRACE_ON(typelib
))
4142 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4143 manageable copy of it into this */
4156 } SLTG_InternalOtherTypeInfo
;
4158 /****************************************************************************
4159 * ITypeLib2_Constructor_SLTG
4161 * loading a SLTG typelib from an in-memory image
4163 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4165 ITypeLibImpl
*pTypeLibImpl
;
4166 SLTG_Header
*pHeader
;
4167 SLTG_BlkEntry
*pBlkEntry
;
4171 LPVOID pBlk
, pFirstBlk
;
4172 SLTG_LibBlk
*pLibBlk
;
4173 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4174 char *pAfterOTIBlks
= NULL
;
4175 char *pNameTable
, *ptr
;
4178 ITypeInfoImpl
**ppTypeInfoImpl
;
4180 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4183 pTypeLibImpl
= TypeLibImpl_Constructor();
4184 if (!pTypeLibImpl
) return NULL
;
4188 TRACE_(typelib
)("header:\n");
4189 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4190 pHeader
->nrOfFileBlks
);
4191 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4192 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4193 pHeader
->SLTG_magic
);
4197 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4198 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4200 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4201 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4203 /* Next we have a magic block */
4204 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4206 /* Let's see if we're still in sync */
4207 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4208 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4209 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4212 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4213 sizeof(SLTG_DIR_MAGIC
))) {
4214 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4218 pIndex
= (SLTG_Index
*)(pMagic
+1);
4220 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4222 pFirstBlk
= pPad9
+ 1;
4224 /* We'll set up a ptr to the main library block, which is the last one. */
4226 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4227 pBlkEntry
[order
].next
!= 0;
4228 order
= pBlkEntry
[order
].next
- 1, i
++) {
4229 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4233 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4235 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4240 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4242 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4245 ptr
= (char*)pLibBlk
+ len
;
4247 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4251 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4253 w
= *(WORD
*)(ptr
+ 2);
4256 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4257 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4258 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4260 w
= *(WORD
*)(ptr
+ 4 + len
);
4262 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4264 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4265 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4266 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4268 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4269 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4270 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4272 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4273 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4276 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4277 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4278 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4279 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4280 len
+= sizeof(SLTG_OtherTypeInfo
);
4284 pAfterOTIBlks
= ptr
;
4286 /* Skip this WORD and get the next DWORD */
4287 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4289 /* Now add this to pLibBLk look at what we're pointing at and
4290 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4291 dust and we should be pointing at the beginning of the name
4294 pNameTable
= (char*)pLibBlk
+ len
;
4296 switch(*(WORD
*)pNameTable
) {
4303 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4307 pNameTable
+= 0x216;
4311 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4313 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4316 /* Hopefully we now have enough ptrs set up to actually read in
4317 some TypeInfos. It's not clear which order to do them in, so
4318 I'll just follow the links along the BlkEntry chain and read
4319 them in the order in which they are in the file */
4321 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4322 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4324 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4325 pBlkEntry
[order
].next
!= 0;
4326 order
= pBlkEntry
[order
].next
- 1, i
++) {
4328 SLTG_TypeInfoHeader
*pTIHeader
;
4329 SLTG_TypeInfoTail
*pTITail
;
4330 SLTG_MemberHeader
*pMemHeader
;
4332 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4333 FIXME_(typelib
)("Index strings don't match\n");
4334 heap_free(pOtherTypeInfoBlks
);
4339 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4340 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4341 heap_free(pOtherTypeInfoBlks
);
4344 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4345 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4346 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4348 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4349 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4350 (*ppTypeInfoImpl
)->index
= i
;
4351 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4352 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4353 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
4354 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
4355 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
4356 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
4357 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
4358 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4360 if((*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4361 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= TKIND_DISPATCH
;
4363 if((pTIHeader
->typeflags1
& 7) != 2)
4364 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4365 if(pTIHeader
->typeflags3
!= 2)
4366 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4368 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4369 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4370 typekind_desc
[pTIHeader
->typekind
],
4371 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
4372 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
4374 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4376 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4378 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
4379 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4380 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
4382 switch(pTIHeader
->typekind
) {
4384 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4385 pTIHeader
, pTITail
);
4389 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4390 pTIHeader
, pTITail
);
4393 case TKIND_INTERFACE
:
4394 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4395 pTIHeader
, pTITail
);
4399 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4400 pTIHeader
, pTITail
);
4404 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4405 pTIHeader
, pTITail
);
4408 case TKIND_DISPATCH
:
4409 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4410 pTIHeader
, pTITail
);
4414 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4415 pTIHeader
, pTITail
);
4419 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4424 /* could get cFuncs, cVars and cImplTypes from here
4425 but we've already set those */
4426 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4442 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4445 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4446 FIXME("Somehow processed %d TypeInfos\n", i
);
4447 heap_free(pOtherTypeInfoBlks
);
4451 heap_free(pOtherTypeInfoBlks
);
4452 return &pTypeLibImpl
->ITypeLib2_iface
;
4455 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4457 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4459 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4461 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4462 IsEqualIID(riid
,&IID_ITypeLib
)||
4463 IsEqualIID(riid
,&IID_ITypeLib2
))
4465 *ppv
= &This
->ITypeLib2_iface
;
4467 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4468 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4470 *ppv
= &This
->ICreateTypeLib2_iface
;
4475 TRACE("-- Interface: E_NOINTERFACE\n");
4476 return E_NOINTERFACE
;
4479 IUnknown_AddRef((IUnknown
*)*ppv
);
4483 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4485 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4486 ULONG ref
= InterlockedIncrement(&This
->ref
);
4488 TRACE("(%p) ref=%u\n", This
, ref
);
4493 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4495 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4496 ULONG ref
= InterlockedDecrement(&This
->ref
);
4498 TRACE("(%p) ref=%u\n",This
, ref
);
4502 TLBImpLib
*pImpLib
, *pImpLibNext
;
4503 TLBRefType
*ref_type
;
4504 TLBString
*tlbstr
, *tlbstr_next
;
4508 /* remove cache entry */
4511 TRACE("removing from cache list\n");
4512 EnterCriticalSection(&cache_section
);
4513 if(This
->entry
.next
)
4514 list_remove(&This
->entry
);
4515 LeaveCriticalSection(&cache_section
);
4516 heap_free(This
->path
);
4518 TRACE(" destroying ITypeLib(%p)\n",This
);
4520 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4521 list_remove(&tlbstr
->entry
);
4525 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4526 list_remove(&tlbstr
->entry
);
4530 TLB_FreeCustData(&This
->custdata_list
);
4532 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4533 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4534 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4536 heap_free(This
->pTypeDesc
);
4538 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4540 if (pImpLib
->pImpTypeLib
)
4541 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4542 SysFreeString(pImpLib
->name
);
4544 list_remove(&pImpLib
->entry
);
4548 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4550 list_remove(&ref_type
->entry
);
4551 heap_free(ref_type
);
4554 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4555 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4556 heap_free(This
->typeinfos
);
4564 /* ITypeLib::GetTypeInfoCount
4566 * Returns the number of type descriptions in the type library
4568 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4570 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4571 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4572 return This
->TypeInfoCount
;
4575 /* ITypeLib::GetTypeInfo
4577 * retrieves the specified type description in the library.
4579 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4582 ITypeInfo
**ppTInfo
)
4584 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4586 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4589 return E_INVALIDARG
;
4591 if(index
>= This
->TypeInfoCount
)
4592 return TYPE_E_ELEMENTNOTFOUND
;
4594 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[index
];
4595 ITypeInfo_AddRef(*ppTInfo
);
4601 /* ITypeLibs::GetTypeInfoType
4603 * Retrieves the type of a type description.
4605 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4610 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4612 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4615 return E_INVALIDARG
;
4617 if(index
>= This
->TypeInfoCount
)
4618 return TYPE_E_ELEMENTNOTFOUND
;
4620 *pTKind
= This
->typeinfos
[index
]->TypeAttr
.typekind
;
4625 /* ITypeLib::GetTypeInfoOfGuid
4627 * Retrieves the type description that corresponds to the specified GUID.
4630 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4633 ITypeInfo
**ppTInfo
)
4635 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4638 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4640 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4641 if(IsEqualIID(&This
->typeinfos
[i
]->TypeAttr
.guid
, guid
)){
4642 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[i
];
4643 ITypeInfo_AddRef(*ppTInfo
);
4648 return TYPE_E_ELEMENTNOTFOUND
;
4651 /* ITypeLib::GetLibAttr
4653 * Retrieves the structure that contains the library's attributes.
4656 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4660 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4662 TRACE("(%p, %p)\n", This
, attr
);
4664 if (!attr
) return E_INVALIDARG
;
4666 *attr
= heap_alloc(sizeof(**attr
));
4667 if (!*attr
) return E_OUTOFMEMORY
;
4669 (*attr
)->guid
= This
->guid
;
4670 (*attr
)->lcid
= This
->set_lcid
;
4671 (*attr
)->syskind
= This
->syskind
;
4672 (*attr
)->wMajorVerNum
= This
->ver_major
;
4673 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4674 (*attr
)->wLibFlags
= This
->libflags
;
4679 /* ITypeLib::GetTypeComp
4681 * Enables a client compiler to bind to a library's types, variables,
4682 * constants, and global functions.
4685 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4687 ITypeComp
**ppTComp
)
4689 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4691 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4692 *ppTComp
= &This
->ITypeComp_iface
;
4693 ITypeComp_AddRef(*ppTComp
);
4698 /* ITypeLib::GetDocumentation
4700 * Retrieves the library's documentation string, the complete Help file name
4701 * and path, and the context identifier for the library Help topic in the Help
4704 * On a successful return all non-null BSTR pointers will have been set,
4707 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4711 BSTR
*pBstrDocString
,
4712 DWORD
*pdwHelpContext
,
4713 BSTR
*pBstrHelpFile
)
4715 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4716 HRESULT result
= E_INVALIDARG
;
4719 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4721 pBstrName
, pBstrDocString
,
4722 pdwHelpContext
, pBstrHelpFile
);
4726 /* documentation for the typelib */
4731 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4739 if (This
->DocString
)
4741 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4744 else if (This
->Name
)
4746 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->Name
))))
4750 *pBstrDocString
= NULL
;
4754 *pdwHelpContext
= This
->dwHelpContext
;
4760 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4764 *pBstrHelpFile
= NULL
;
4771 /* for a typeinfo */
4772 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4774 if(SUCCEEDED(result
))
4776 result
= ITypeInfo_GetDocumentation(pTInfo
,
4780 pdwHelpContext
, pBstrHelpFile
);
4782 ITypeInfo_Release(pTInfo
);
4787 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4789 if (pBstrName
) SysFreeString (*pBstrName
);
4791 return STG_E_INSUFFICIENTMEMORY
;
4796 * Indicates whether a passed-in string contains the name of a type or member
4797 * described in the library.
4800 static HRESULT WINAPI
ITypeLib2_fnIsName(
4806 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4808 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
4810 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4814 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4815 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4816 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4817 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4818 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4820 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4821 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
4822 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4823 goto ITypeLib2_fnIsName_exit
;
4826 for(vrc
= 0; vrc
< pTInfo
->TypeAttr
.cVars
; ++vrc
){
4827 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4828 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4834 ITypeLib2_fnIsName_exit
:
4835 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4836 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4841 /* ITypeLib::FindName
4843 * Finds occurrences of a type description in a type library. This may be used
4844 * to quickly verify that a name exists in a type library.
4847 static HRESULT WINAPI
ITypeLib2_fnFindName(
4851 ITypeInfo
**ppTInfo
,
4855 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4860 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
4862 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
4863 return E_INVALIDARG
;
4865 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
4866 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
4867 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4871 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4872 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4873 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
4876 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4877 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
4878 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
4879 goto ITypeLib2_fnFindName_exit
;
4883 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->TypeAttr
.cVars
, name
);
4885 goto ITypeLib2_fnFindName_exit
;
4888 ITypeLib2_fnFindName_exit
:
4889 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4890 ppTInfo
[count
]=(LPTYPEINFO
)pTInfo
;
4893 TRACE("found %d typeinfos\n", count
);
4900 /* ITypeLib::ReleaseTLibAttr
4902 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4905 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4907 TLIBATTR
*pTLibAttr
)
4909 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4910 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
4911 heap_free(pTLibAttr
);
4914 /* ITypeLib2::GetCustData
4916 * gets the custom data
4918 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4923 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4924 TLBCustData
*pCData
;
4926 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
4928 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
4930 return TYPE_E_ELEMENTNOTFOUND
;
4932 VariantInit(pVarVal
);
4933 VariantCopy(pVarVal
, &pCData
->data
);
4938 /* ITypeLib2::GetLibStatistics
4940 * Returns statistics about a type library that are required for efficient
4941 * sizing of hash tables.
4944 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4946 ULONG
*pcUniqueNames
,
4947 ULONG
*pcchUniqueNames
)
4949 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4951 FIXME("(%p): stub!\n", This
);
4953 if(pcUniqueNames
) *pcUniqueNames
=1;
4954 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4958 /* ITypeLib2::GetDocumentation2
4960 * Retrieves the library's documentation string, the complete Help file name
4961 * and path, the localization context to use, and the context ID for the
4962 * library Help topic in the Help file.
4965 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4969 BSTR
*pbstrHelpString
,
4970 DWORD
*pdwHelpStringContext
,
4971 BSTR
*pbstrHelpStringDll
)
4973 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4977 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4979 /* the help string should be obtained from the helpstringdll,
4980 * using the _DLLGetDocumentation function, based on the supplied
4981 * lcid. Nice to do sometime...
4985 /* documentation for the typelib */
4987 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
4988 if(pdwHelpStringContext
)
4989 *pdwHelpStringContext
=This
->dwHelpContext
;
4990 if(pbstrHelpStringDll
)
4991 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
4997 /* for a typeinfo */
4998 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5000 if(SUCCEEDED(result
))
5002 ITypeInfo2
* pTInfo2
;
5003 result
= ITypeInfo_QueryInterface(pTInfo
,
5005 (LPVOID
*) &pTInfo2
);
5007 if(SUCCEEDED(result
))
5009 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5013 pdwHelpStringContext
,
5014 pbstrHelpStringDll
);
5016 ITypeInfo2_Release(pTInfo2
);
5019 ITypeInfo_Release(pTInfo
);
5025 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5027 TLBCustData
*pCData
;
5031 ct
= list_count(custdata_list
);
5033 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5034 if(!pCustData
->prgCustData
)
5035 return E_OUTOFMEMORY
;
5037 pCustData
->cCustData
= ct
;
5039 cdi
= pCustData
->prgCustData
;
5040 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5041 cdi
->guid
= pCData
->guid
;
5042 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5050 /* ITypeLib2::GetAllCustData
5052 * Gets all custom data items for the library.
5055 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5057 CUSTDATA
*pCustData
)
5059 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5060 TRACE("(%p)->(%p)\n", This
, pCustData
);
5061 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5064 static const ITypeLib2Vtbl tlbvt
= {
5065 ITypeLib2_fnQueryInterface
,
5067 ITypeLib2_fnRelease
,
5068 ITypeLib2_fnGetTypeInfoCount
,
5069 ITypeLib2_fnGetTypeInfo
,
5070 ITypeLib2_fnGetTypeInfoType
,
5071 ITypeLib2_fnGetTypeInfoOfGuid
,
5072 ITypeLib2_fnGetLibAttr
,
5073 ITypeLib2_fnGetTypeComp
,
5074 ITypeLib2_fnGetDocumentation
,
5076 ITypeLib2_fnFindName
,
5077 ITypeLib2_fnReleaseTLibAttr
,
5079 ITypeLib2_fnGetCustData
,
5080 ITypeLib2_fnGetLibStatistics
,
5081 ITypeLib2_fnGetDocumentation2
,
5082 ITypeLib2_fnGetAllCustData
5086 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5088 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5090 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5093 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5095 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5097 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5100 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5102 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5104 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5107 static HRESULT WINAPI
ITypeLibComp_fnBind(
5112 ITypeInfo
** ppTInfo
,
5113 DESCKIND
* pDescKind
,
5116 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5117 int typemismatch
=0, i
;
5119 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5121 *pDescKind
= DESCKIND_NONE
;
5122 pBindPtr
->lptcomp
= NULL
;
5125 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5126 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5127 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5129 /* FIXME: check wFlags here? */
5130 /* FIXME: we should use a hash table to look this info up using lHash
5131 * instead of an O(n) search */
5132 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
5133 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
5135 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5137 *pDescKind
= DESCKIND_TYPECOMP
;
5138 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5139 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5140 TRACE("module or enum: %s\n", debugstr_w(szName
));
5145 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
5146 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
5148 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5151 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5152 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5154 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5157 else if (hr
== TYPE_E_TYPEMISMATCH
)
5161 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
5162 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5164 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5166 ITypeInfo
*subtypeinfo
;
5168 DESCKIND subdesckind
;
5170 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5171 &subtypeinfo
, &subdesckind
, &subbindptr
);
5172 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5174 TYPEDESC tdesc_appobject
;
5175 const VARDESC vardesc_appobject
=
5178 NULL
, /* lpstrSchema */
5193 VAR_STATIC
/* varkind */
5196 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5197 tdesc_appobject
.vt
= VT_USERDEFINED
;
5199 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5201 /* cleanup things filled in by Bind call so we can put our
5202 * application object data in there instead */
5203 switch (subdesckind
)
5205 case DESCKIND_FUNCDESC
:
5206 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5208 case DESCKIND_VARDESC
:
5209 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5214 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5216 if (pTypeInfo
->hreftype
== -1)
5217 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5219 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5223 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5224 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
5225 ITypeInfo_AddRef(*ppTInfo
);
5228 else if (hr
== TYPE_E_TYPEMISMATCH
)
5235 TRACE("type mismatch %s\n", debugstr_w(szName
));
5236 return TYPE_E_TYPEMISMATCH
;
5240 TRACE("name not found %s\n", debugstr_w(szName
));
5245 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5249 ITypeInfo
** ppTInfo
,
5250 ITypeComp
** ppTComp
)
5252 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5253 ITypeInfoImpl
*info
;
5255 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5257 if(!szName
|| !ppTInfo
|| !ppTComp
)
5258 return E_INVALIDARG
;
5260 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5267 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5268 ITypeInfo_AddRef(*ppTInfo
);
5269 *ppTComp
= &info
->ITypeComp_iface
;
5270 ITypeComp_AddRef(*ppTComp
);
5275 static const ITypeCompVtbl tlbtcvt
=
5278 ITypeLibComp_fnQueryInterface
,
5279 ITypeLibComp_fnAddRef
,
5280 ITypeLibComp_fnRelease
,
5282 ITypeLibComp_fnBind
,
5283 ITypeLibComp_fnBindType
5286 /*================== ITypeInfo(2) Methods ===================================*/
5287 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5289 ITypeInfoImpl
*pTypeInfoImpl
;
5291 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5294 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5295 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5296 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5297 pTypeInfoImpl
->ref
= 0;
5298 pTypeInfoImpl
->hreftype
= -1;
5299 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
5300 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
5301 list_init(&pTypeInfoImpl
->custdata_list
);
5303 TRACE("(%p)\n", pTypeInfoImpl
);
5304 return pTypeInfoImpl
;
5307 /* ITypeInfo::QueryInterface
5309 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5314 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5316 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5319 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5320 IsEqualIID(riid
,&IID_ITypeInfo
)||
5321 IsEqualIID(riid
,&IID_ITypeInfo2
))
5323 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5324 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5325 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5328 ITypeInfo2_AddRef(iface
);
5329 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5332 TRACE("-- Interface: E_NOINTERFACE\n");
5333 return E_NOINTERFACE
;
5336 /* ITypeInfo::AddRef
5338 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5340 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5341 ULONG ref
= InterlockedIncrement(&This
->ref
);
5343 TRACE("(%p)->ref is %u\n",This
, ref
);
5345 if (ref
== 1 /* incremented from 0 */)
5346 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5351 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5355 TRACE("destroying ITypeInfo(%p)\n",This
);
5357 for (i
= 0; i
< This
->TypeAttr
.cFuncs
; ++i
)
5360 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5361 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5363 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5364 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5366 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5367 heap_free(elemdesc
->u
.paramdesc
.pparamdescex
);
5369 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5371 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5372 heap_free(pFInfo
->pParamDesc
);
5373 TLB_FreeCustData(&pFInfo
->custdata_list
);
5375 heap_free(This
->funcdescs
);
5377 for(i
= 0; i
< This
->TypeAttr
.cVars
; ++i
)
5379 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5380 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5382 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5383 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5385 TLB_FreeCustData(&pVInfo
->custdata_list
);
5387 heap_free(This
->vardescs
);
5389 if(This
->impltypes
){
5390 for (i
= 0; i
< This
->TypeAttr
.cImplTypes
; ++i
){
5391 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5392 TLB_FreeCustData(&pImpl
->custdata_list
);
5394 heap_free(This
->impltypes
);
5397 TLB_FreeCustData(&This
->custdata_list
);
5402 /* ITypeInfo::Release
5404 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5406 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5407 ULONG ref
= InterlockedDecrement(&This
->ref
);
5409 TRACE("(%p)->(%u)\n",This
, ref
);
5413 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5414 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5415 if (not_attached_to_typelib
)
5417 /* otherwise This will be freed when typelib is freed */
5423 /* ITypeInfo::GetTypeAttr
5425 * Retrieves a TYPEATTR structure that contains the attributes of the type
5429 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5430 LPTYPEATTR
*ppTypeAttr
)
5432 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5435 TRACE("(%p)\n",This
);
5437 size
= sizeof(**ppTypeAttr
);
5438 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5439 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
5441 *ppTypeAttr
= heap_alloc(size
);
5443 return E_OUTOFMEMORY
;
5445 **ppTypeAttr
= This
->TypeAttr
;
5447 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5448 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5449 &This
->TypeAttr
.tdescAlias
, *ppTypeAttr
+ 1);
5451 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5452 /* This should include all the inherited funcs */
5453 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5454 /* This is always the size of IDispatch's vtbl */
5455 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5456 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5461 /* ITypeInfo::GetTypeComp
5463 * Retrieves the ITypeComp interface for the type description, which enables a
5464 * client compiler to bind to the type description's members.
5467 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5468 ITypeComp
* *ppTComp
)
5470 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5472 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5474 *ppTComp
= &This
->ITypeComp_iface
;
5475 ITypeComp_AddRef(*ppTComp
);
5479 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5481 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5482 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5483 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5487 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5490 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5491 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5493 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5494 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5495 *buffer
+= sizeof(PARAMDESCEX
);
5496 *pparamdescex_dest
= *pparamdescex_src
;
5497 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5498 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5499 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5500 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5503 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5507 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5509 UINT len
= SysStringLen(str
), i
;
5510 for (i
= 0; i
< len
; ++i
)
5516 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5518 if (V_VT(var
) == VT_INT
)
5519 return VariantChangeType(var
, var
, 0, VT_I4
);
5520 else if (V_VT(var
) == VT_UINT
)
5521 return VariantChangeType(var
, var
, 0, VT_UI4
);
5522 else if (V_VT(var
) == VT_BSTR
)
5523 return TLB_SanitizeBSTR(V_BSTR(var
));
5528 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5530 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5531 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5534 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5538 SIZE_T size
= sizeof(*src
);
5542 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5543 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5544 for (i
= 0; i
< src
->cParams
; i
++)
5546 size
+= sizeof(ELEMDESC
);
5547 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5550 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5551 if (!dest
) return E_OUTOFMEMORY
;
5554 if (dispinterface
) /* overwrite funckind */
5555 dest
->funckind
= FUNC_DISPATCH
;
5556 buffer
= (char *)(dest
+ 1);
5558 dest
->oVft
= dest
->oVft
& 0xFFFC;
5560 if (dest
->cScodes
) {
5561 dest
->lprgscode
= (SCODE
*)buffer
;
5562 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5563 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5565 dest
->lprgscode
= NULL
;
5567 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5570 SysFreeString((BSTR
)dest
);
5574 if (dest
->cParams
) {
5575 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5576 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5577 for (i
= 0; i
< src
->cParams
; i
++)
5579 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5585 /* undo the above actions */
5586 for (i
= i
- 1; i
>= 0; i
--)
5587 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5588 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5589 SysFreeString((BSTR
)dest
);
5593 dest
->lprgelemdescParam
= NULL
;
5595 /* special treatment for dispinterfaces: this makes functions appear
5596 * to return their [retval] value when it is really returning an
5598 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5600 if (dest
->cParams
&&
5601 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5603 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5604 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5606 ERR("elemdesc should have started with VT_PTR instead of:\n");
5608 dump_ELEMDESC(elemdesc
);
5609 return E_UNEXPECTED
;
5612 /* copy last parameter to the return value. we are using a flat
5613 * buffer so there is no danger of leaking memory in
5615 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5617 /* remove the last parameter */
5621 /* otherwise this function is made to appear to have no return
5623 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5631 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5633 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5635 if (index
>= This
->TypeAttr
.cFuncs
)
5636 return TYPE_E_ELEMENTNOTFOUND
;
5638 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5642 /* internal function to make the inherited interfaces' methods appear
5643 * part of the interface */
5644 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5645 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5647 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5649 UINT implemented_funcs
= 0;
5654 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5658 ITypeInfo
*pSubTypeInfo
;
5661 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5665 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5668 &sub_funcs
, hrefoffset
);
5669 implemented_funcs
+= sub_funcs
;
5670 ITypeInfo_Release(pSubTypeInfo
);
5673 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5677 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
5681 if (index
< implemented_funcs
)
5682 return E_INVALIDARG
;
5683 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5687 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5689 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5692 switch (pTypeDesc
->vt
)
5694 case VT_USERDEFINED
:
5695 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5699 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5702 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5710 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5713 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5714 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5715 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5718 /* ITypeInfo::GetFuncDesc
5720 * Retrieves the FUNCDESC structure that contains information about a
5721 * specified function.
5724 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5725 LPFUNCDESC
*ppFuncDesc
)
5727 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5728 const FUNCDESC
*internal_funcdesc
;
5730 UINT hrefoffset
= 0;
5732 TRACE("(%p) index %d\n", This
, index
);
5735 return E_INVALIDARG
;
5737 if (This
->needs_layout
)
5738 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5740 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5741 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5742 &internal_funcdesc
, NULL
,
5745 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5746 &internal_funcdesc
);
5749 WARN("description for function %d not found\n", index
);
5753 hr
= TLB_AllocAndInitFuncDesc(
5756 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5758 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5759 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5761 TRACE("-- 0x%08x\n", hr
);
5765 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5769 SIZE_T size
= sizeof(*src
);
5772 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5773 if (src
->varkind
== VAR_CONST
)
5774 size
+= sizeof(VARIANT
);
5775 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5777 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5778 if (!dest
) return E_OUTOFMEMORY
;
5781 buffer
= (char *)(dest
+ 1);
5782 if (src
->lpstrSchema
)
5785 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5786 len
= strlenW(src
->lpstrSchema
);
5787 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5788 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5791 if (src
->varkind
== VAR_CONST
)
5795 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5796 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5797 buffer
+= sizeof(VARIANT
);
5798 VariantInit(dest
->u
.lpvarValue
);
5799 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5802 SysFreeString((BSTR
)dest
);
5806 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5809 if (src
->varkind
== VAR_CONST
)
5810 VariantClear(dest
->u
.lpvarValue
);
5811 SysFreeString((BSTR
)dest
);
5818 /* ITypeInfo::GetVarDesc
5820 * Retrieves a VARDESC structure that describes the specified variable.
5823 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5824 LPVARDESC
*ppVarDesc
)
5826 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5827 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5829 TRACE("(%p) index %d\n", This
, index
);
5831 if(index
>= This
->TypeAttr
.cVars
)
5832 return TYPE_E_ELEMENTNOTFOUND
;
5834 if (This
->needs_layout
)
5835 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5837 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5840 /* ITypeInfo_GetNames
5842 * Retrieves the variable with the specified member ID (or the name of the
5843 * property or method and its parameters) that correspond to the specified
5846 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5847 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5849 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5850 const TLBFuncDesc
*pFDesc
;
5851 const TLBVarDesc
*pVDesc
;
5853 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5854 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
5857 /* function found, now return function and parameter names */
5858 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5861 *rgBstrNames
=SysAllocString(TLB_get_bstr(pFDesc
->Name
));
5863 rgBstrNames
[i
]=SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
-1].Name
));
5869 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
5872 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
5877 if(This
->impltypes
&&
5878 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5879 /* recursive search */
5882 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5883 if(SUCCEEDED(result
))
5885 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5886 ITypeInfo_Release(pTInfo
);
5889 WARN("Could not search inherited interface!\n");
5893 WARN("no names found\n");
5896 return TYPE_E_ELEMENTNOTFOUND
;
5903 /* ITypeInfo::GetRefTypeOfImplType
5905 * If a type description describes a COM class, it retrieves the type
5906 * description of the implemented interface types. For an interface,
5907 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5911 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5916 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5919 TRACE("(%p) index %d\n", This
, index
);
5920 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5924 /* only valid on dual interfaces;
5925 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5928 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5934 hr
= TYPE_E_ELEMENTNOTFOUND
;
5937 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5939 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5940 *pRefType
= This
->pTypeLib
->dispatch_href
;
5944 if(index
>= This
->TypeAttr
.cImplTypes
)
5945 hr
= TYPE_E_ELEMENTNOTFOUND
;
5947 *pRefType
= This
->impltypes
[index
].hRef
;
5953 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5955 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5961 /* ITypeInfo::GetImplTypeFlags
5963 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5964 * or base interface in a type description.
5966 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5967 UINT index
, INT
*pImplTypeFlags
)
5969 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5971 TRACE("(%p) index %d\n", This
, index
);
5974 return E_INVALIDARG
;
5976 if(This
->TypeAttr
.typekind
== TKIND_DISPATCH
&& index
== 0){
5977 *pImplTypeFlags
= 0;
5981 if(index
>= This
->TypeAttr
.cImplTypes
)
5982 return TYPE_E_ELEMENTNOTFOUND
;
5984 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
5990 * Maps between member names and member IDs, and parameter names and
5993 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5994 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5996 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5997 const TLBVarDesc
*pVDesc
;
6001 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6004 /* init out parameters in case of failure */
6005 for (i
= 0; i
< cNames
; i
++)
6006 pMemId
[i
] = MEMBERID_NIL
;
6008 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
) {
6010 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6011 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6012 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6013 for(i
=1; i
< cNames
; i
++){
6014 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6015 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6017 if( j
<pFDesc
->funcdesc
.cParams
)
6020 ret
=DISP_E_UNKNOWNNAME
;
6022 TRACE("-- 0x%08x\n", ret
);
6026 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, *rgszNames
);
6029 *pMemId
= pVDesc
->vardesc
.memid
;
6032 /* not found, see if it can be found in an inherited interface */
6033 if(This
->impltypes
) {
6034 /* recursive search */
6036 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6038 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6039 ITypeInfo_Release(pTInfo
);
6042 WARN("Could not search inherited interface!\n");
6044 WARN("no names found\n");
6045 return DISP_E_UNKNOWNNAME
;
6051 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6052 __ASM_GLOBAL_FUNC( call_method
,
6054 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6055 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6056 "movl %esp,%ebp\n\t"
6057 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6059 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6061 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6062 "movl 12(%ebp),%edx\n\t"
6063 "movl %esp,%edi\n\t"
6066 "subl %edx,%edi\n\t"
6067 "andl $~15,%edi\n\t"
6068 "movl %edi,%esp\n\t"
6069 "movl 12(%ebp),%ecx\n\t"
6070 "movl 16(%ebp),%esi\n\t"
6073 "1:\tcall *8(%ebp)\n\t"
6074 "subl %esp,%edi\n\t"
6075 "movl 20(%ebp),%ecx\n\t"
6076 "movl %edi,(%ecx)\n\t"
6077 "leal -8(%ebp),%esp\n\t"
6079 __ASM_CFI(".cfi_same_value %edi\n\t")
6081 __ASM_CFI(".cfi_same_value %esi\n\t")
6083 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6084 __ASM_CFI(".cfi_same_value %ebp\n\t")
6087 /* same function but returning floating point */
6088 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6090 /* ITypeInfo::Invoke
6092 * Invokes a method, or accesses a property of an object, that implements the
6093 * interface described by the type description.
6096 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6100 if (TRACE_ON(ole
)) {
6102 TRACE("Calling %p(",func
);
6103 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6104 if (nrargs
> 30) TRACE("...");
6111 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6114 FIXME("unsupported calling convention %d\n",callconv
);
6118 TRACE("returns %08x\n",res
);
6122 #elif defined(__x86_64__)
6124 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6125 __ASM_GLOBAL_FUNC( call_method
,
6127 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6128 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6129 "movq %rsp,%rbp\n\t"
6130 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6132 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6134 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6135 "movq %rcx,%rax\n\t"
6138 "cmovgq %rdx,%rcx\n\t"
6139 "leaq 0(,%rcx,8),%rdx\n\t"
6140 "subq %rdx,%rsp\n\t"
6141 "andq $~15,%rsp\n\t"
6142 "movq %rsp,%rdi\n\t"
6145 "movq 0(%rsp),%rcx\n\t"
6146 "movq 8(%rsp),%rdx\n\t"
6147 "movq 16(%rsp),%r8\n\t"
6148 "movq 24(%rsp),%r9\n\t"
6149 "movq %rcx,%xmm0\n\t"
6150 "movq %rdx,%xmm1\n\t"
6151 "movq %r8,%xmm2\n\t"
6152 "movq %r9,%xmm3\n\t"
6154 "leaq -16(%rbp),%rsp\n\t"
6156 __ASM_CFI(".cfi_same_value %rdi\n\t")
6158 __ASM_CFI(".cfi_same_value %rsi\n\t")
6159 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6161 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6162 __ASM_CFI(".cfi_same_value %rbp\n\t")
6165 /* same function but returning floating point */
6166 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6168 #endif /* __x86_64__ */
6170 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6173 ITypeInfo
*tinfo2
= NULL
;
6174 TYPEATTR
*tattr
= NULL
;
6176 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6179 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6181 tdesc
->u
.hreftype
, hr
);
6184 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6187 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6188 ITypeInfo_Release(tinfo2
);
6192 switch (tattr
->typekind
)
6199 tdesc
= &tattr
->tdescAlias
;
6200 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6203 case TKIND_INTERFACE
:
6204 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6210 case TKIND_DISPATCH
:
6219 FIXME("TKIND_RECORD unhandled.\n");
6224 FIXME("TKIND_UNION unhandled.\n");
6229 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6233 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6234 ITypeInfo_Release(tinfo2
);
6238 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6242 /* enforce only one level of pointer indirection */
6243 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6245 tdesc
= tdesc
->u
.lptdesc
;
6247 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6248 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6249 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6250 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6251 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6253 VARTYPE vt_userdefined
= 0;
6254 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6255 if (tdesc
->vt
== VT_PTR
)
6257 vt_userdefined
= VT_BYREF
;
6258 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6260 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6262 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6263 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6265 *vt
|= vt_userdefined
;
6277 case VT_USERDEFINED
:
6278 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6285 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6286 hr
= DISP_E_BADVARTYPE
;
6290 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6305 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6311 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6315 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6317 ITypeInfo_Release(tinfo2
);
6321 switch(tattr
->typekind
) {
6323 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6326 case TKIND_INTERFACE
:
6327 case TKIND_DISPATCH
:
6328 *guid
= tattr
->guid
;
6332 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6333 hres
= E_UNEXPECTED
;
6336 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6337 ITypeInfo_Release(tinfo2
);
6341 /***********************************************************************
6342 * DispCallFunc (OLEAUT32.@)
6344 * Invokes a function of the specified calling convention, passing the
6345 * specified arguments and returns the result.
6348 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6349 * oVft [I] The offset in the vtable. See notes.
6350 * cc [I] Calling convention of the function to call.
6351 * vtReturn [I] The return type of the function.
6352 * cActuals [I] Number of parameters.
6353 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6354 * prgpvarg [I] The arguments to pass.
6355 * pvargResult [O] The return value of the function. Can be NULL.
6359 * Failure: HRESULT code.
6362 * The HRESULT return value of this function is not affected by the return
6363 * value of the user supplied function, which is returned in pvargResult.
6365 * If pvInstance is NULL then a non-object function is to be called and oVft
6366 * is the address of the function to call.
6368 * The cc parameter can be one of the following values:
6381 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6382 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6385 int argspos
, stack_offset
;
6390 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6391 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6392 pvargResult
, V_VT(pvargResult
));
6394 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6396 FIXME("unsupported calling convention %d\n",cc
);
6397 return E_INVALIDARG
;
6400 /* maximum size for an argument is sizeof(VARIANT) */
6401 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6403 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6407 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6408 func
= vtable
[oVft
/sizeof(void *)];
6409 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6411 else func
= (void *)oVft
;
6413 for (i
= 0; i
< cActuals
; i
++)
6415 VARIANT
*arg
= prgpvarg
[i
];
6426 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6427 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6431 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6432 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6434 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6435 args
[argspos
++] = V_BOOL(arg
);
6438 args
[argspos
++] = V_UI4(arg
);
6441 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6448 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6451 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6455 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6459 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6460 call_method( func
, argspos
, args
, &stack_offset
);
6465 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6468 WARN("invalid return type %u\n", vtReturn
);
6470 return E_INVALIDARG
;
6472 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6476 if (stack_offset
&& cc
== CC_STDCALL
)
6478 WARN( "stack pointer off by %d\n", stack_offset
);
6479 return DISP_E_BADCALLEE
;
6481 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6482 TRACE("retval: "); dump_Variant(pvargResult
);
6485 #elif defined(__x86_64__)
6491 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6492 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6493 pvargResult
, V_VT(pvargResult
));
6495 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6497 FIXME("unsupported calling convention %d\n",cc
);
6498 return E_INVALIDARG
;
6501 /* maximum size for an argument is sizeof(DWORD_PTR) */
6502 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6504 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6508 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6509 func
= vtable
[oVft
/sizeof(void *)];
6510 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6512 else func
= (void *)oVft
;
6514 for (i
= 0; i
< cActuals
; i
++)
6516 VARIANT
*arg
= prgpvarg
[i
];
6522 args
[argspos
++] = (ULONG_PTR
)arg
;
6524 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6525 args
[argspos
++] = V_BOOL(arg
);
6528 args
[argspos
++] = V_UI8(arg
);
6531 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6538 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6542 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6546 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6547 call_method( func
, argspos
, args
);
6550 WARN("invalid return type %u\n", vtReturn
);
6552 return E_INVALIDARG
;
6554 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6558 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6559 TRACE("retval: "); dump_Variant(pvargResult
);
6563 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6564 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6569 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6571 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6574 #define INVBUF_ELEMENT_SIZE \
6575 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6576 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6577 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6578 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6579 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6580 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6581 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6582 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6584 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6589 DISPPARAMS
*pDispParams
,
6590 VARIANT
*pVarResult
,
6591 EXCEPINFO
*pExcepInfo
,
6594 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6596 unsigned int var_index
;
6599 const TLBFuncDesc
*pFuncInfo
;
6602 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6603 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6606 if( This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6607 return DISP_E_MEMBERNOTFOUND
;
6611 ERR("NULL pDispParams not allowed\n");
6612 return E_INVALIDARG
;
6615 dump_DispParms(pDispParams
);
6617 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6619 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6620 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6621 return E_INVALIDARG
;
6624 /* we do this instead of using GetFuncDesc since it will return a fake
6625 * FUNCDESC for dispinterfaces and we want the real function description */
6626 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
6627 pFuncInfo
= &This
->funcdescs
[fdc
];
6628 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6629 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6630 !func_restricted( &pFuncInfo
->funcdesc
))
6634 if (fdc
< This
->TypeAttr
.cFuncs
) {
6635 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6639 TRACE("invoking:\n");
6640 dump_TLBFuncDescOne(pFuncInfo
);
6643 switch (func_desc
->funckind
) {
6644 case FUNC_PUREVIRTUAL
:
6645 case FUNC_VIRTUAL
: {
6646 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6648 VARIANT retval
; /* pointer for storing byref retvals in */
6649 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6650 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6651 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6652 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6653 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6654 UINT vargs_converted
=0;
6658 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6660 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6662 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6663 hres
= DISP_E_PARAMNOTFOUND
;
6668 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6670 ERR("functions with the vararg attribute do not support named arguments\n");
6671 hres
= DISP_E_NONAMEDARGS
;
6675 for (i
= 0; i
< func_desc
->cParams
; i
++)
6677 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6678 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6683 TRACE("changing args\n");
6684 for (i
= 0; i
< func_desc
->cParams
; i
++)
6686 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6687 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6688 VARIANTARG
*src_arg
;
6690 if (wParamFlags
& PARAMFLAG_FLCID
)
6693 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6695 V_I4(arg
) = This
->pTypeLib
->lcid
;
6704 for (j
= 0; j
< cNamedArgs
; j
++)
6705 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6707 src_arg
= &pDispParams
->rgvarg
[j
];
6712 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6714 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6718 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6720 /* under most conditions the caller is not allowed to
6721 * pass in a dispparam arg in the index of what would be
6722 * the retval parameter. however, there is an exception
6723 * where the extra parameter is used in an extra
6724 * IDispatch::Invoke below */
6725 if ((i
< pDispParams
->cArgs
) &&
6726 ((func_desc
->cParams
!= 1) || !pVarResult
||
6727 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6729 hres
= DISP_E_BADPARAMCOUNT
;
6733 /* note: this check is placed so that if the caller passes
6734 * in a VARIANTARG for the retval we just ignore it, like
6736 if (i
== func_desc
->cParams
- 1)
6739 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6740 memset(arg
, 0, sizeof(*arg
));
6741 V_VT(arg
) = rgvt
[i
];
6742 memset(&retval
, 0, sizeof(retval
));
6743 V_BYREF(arg
) = &retval
;
6747 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6748 hres
= E_UNEXPECTED
;
6754 dump_Variant(src_arg
);
6756 if(rgvt
[i
]!=V_VT(src_arg
))
6758 if (rgvt
[i
] == VT_VARIANT
)
6759 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6760 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6762 if (rgvt
[i
] == V_VT(src_arg
))
6763 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6766 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6767 if (wParamFlags
& PARAMFLAG_FIN
)
6768 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6769 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6771 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6773 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6776 SAFEARRAYBOUND bound
;
6780 bound
.cElements
= pDispParams
->cArgs
-i
;
6781 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6783 ERR("SafeArrayCreate failed\n");
6786 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6789 ERR("SafeArrayAccessData failed with %x\n", hres
);
6790 SafeArrayDestroy(a
);
6793 for (j
= 0; j
< bound
.cElements
; j
++)
6794 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6795 hres
= SafeArrayUnaccessData(a
);
6798 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6799 SafeArrayDestroy(a
);
6802 V_ARRAY(&rgvarg
[i
]) = a
;
6803 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6805 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6807 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6808 if (wParamFlags
& PARAMFLAG_FIN
)
6809 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6811 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6812 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6813 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6815 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6817 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6818 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6822 /* FIXME: this doesn't work for VT_BYREF arguments if
6823 * they are not the same type as in the paramdesc */
6824 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6825 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6826 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6831 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6832 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6833 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6836 prgpvarg
[i
] = &rgvarg
[i
];
6840 prgpvarg
[i
] = src_arg
;
6843 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
6844 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
6845 && V_UNKNOWN(prgpvarg
[i
])) {
6846 IUnknown
*userdefined_iface
;
6849 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
6853 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
6855 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
6859 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
6860 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
6863 else if (wParamFlags
& PARAMFLAG_FOPT
)
6866 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6867 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6869 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6875 VARIANTARG
*missing_arg
;
6876 /* if the function wants a pointer to a variant then
6877 * set that up, otherwise just pass the VT_ERROR in
6878 * the argument by value */
6879 if (rgvt
[i
] & VT_BYREF
)
6881 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6882 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6883 V_VARIANTREF(arg
) = missing_arg
;
6887 V_VT(missing_arg
) = VT_ERROR
;
6888 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6893 hres
= DISP_E_BADPARAMCOUNT
;
6897 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6899 /* VT_VOID is a special case for return types, so it is not
6900 * handled in the general function */
6901 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
6902 V_VT(&varresult
) = VT_EMPTY
;
6905 V_VT(&varresult
) = 0;
6906 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
6907 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6910 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
6911 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6912 prgpvarg
, &varresult
);
6914 vargs_converted
= 0;
6916 for (i
= 0; i
< func_desc
->cParams
; i
++)
6918 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6919 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6921 if (wParamFlags
& PARAMFLAG_FLCID
)
6923 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
6927 TRACE("[retval] value: ");
6928 dump_Variant(prgpvarg
[i
]);
6933 VariantInit(pVarResult
);
6934 /* deref return value */
6935 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6938 VARIANT_ClearInd(prgpvarg
[i
]);
6940 else if (vargs_converted
< pDispParams
->cArgs
)
6942 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6943 if (wParamFlags
& PARAMFLAG_FOUT
)
6945 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
6947 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6951 ERR("failed to convert param %d to vt %d\n", i
,
6952 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
6957 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6958 func_desc
->cParamsOpt
< 0 &&
6959 i
== func_desc
->cParams
-1)
6961 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6964 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6967 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6970 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6973 ERR("SafeArrayAccessData failed with %x\n", hres
);
6976 for (j
= 0; j
<= ubound
; j
++)
6977 VariantClear(&v
[j
]);
6978 hres
= SafeArrayUnaccessData(a
);
6981 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6985 VariantClear(&rgvarg
[i
]);
6988 else if (wParamFlags
& PARAMFLAG_FOPT
)
6990 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6991 VariantClear(&rgvarg
[i
]);
6994 VariantClear(&missing_arg
[i
]);
6997 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6999 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7000 hres
= DISP_E_EXCEPTION
;
7003 IErrorInfo
*pErrorInfo
;
7004 pExcepInfo
->scode
= V_ERROR(&varresult
);
7005 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7007 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7008 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7009 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7010 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7012 IErrorInfo_Release(pErrorInfo
);
7016 if (V_VT(&varresult
) != VT_ERROR
)
7018 TRACE("varresult value: ");
7019 dump_Variant(&varresult
);
7023 VariantClear(pVarResult
);
7024 *pVarResult
= varresult
;
7027 VariantClear(&varresult
);
7030 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7031 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7032 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7033 (pDispParams
->cArgs
!= 0))
7035 if (V_VT(pVarResult
) == VT_DISPATCH
)
7037 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7038 /* Note: not VariantClear; we still need the dispatch
7039 * pointer to be valid */
7040 VariantInit(pVarResult
);
7041 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7042 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7043 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7044 IDispatch_Release(pDispatch
);
7048 VariantClear(pVarResult
);
7049 hres
= DISP_E_NOTACOLLECTION
;
7057 case FUNC_DISPATCH
: {
7060 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7061 if (SUCCEEDED(hres
)) {
7062 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7063 hres
= IDispatch_Invoke(
7064 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7065 pVarResult
,pExcepInfo
,pArgErr
7068 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7069 IDispatch_Release(disp
);
7071 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7075 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7080 TRACE("-- 0x%08x\n", hres
);
7083 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7086 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7087 if(FAILED(hres
)) return hres
;
7089 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7090 dump_VARDESC(var_desc
);
7091 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7095 /* not found, look for it in inherited interfaces */
7096 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7097 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7098 if(This
->impltypes
) {
7099 /* recursive search */
7101 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7102 if(SUCCEEDED(hres
)){
7103 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7104 ITypeInfo_Release(pTInfo
);
7107 WARN("Could not search inherited interface!\n");
7110 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7111 return DISP_E_MEMBERNOTFOUND
;
7114 /* ITypeInfo::GetDocumentation
7116 * Retrieves the documentation string, the complete Help file name and path,
7117 * and the context ID for the Help topic for a specified type description.
7119 * (Can be tested by the Visual Basic Editor in Word for instance.)
7121 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7122 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7123 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7125 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7126 const TLBFuncDesc
*pFDesc
;
7127 const TLBVarDesc
*pVDesc
;
7128 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7129 " HelpContext(%p) HelpFile(%p)\n",
7130 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7131 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7133 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7135 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7137 *pdwHelpContext
=This
->dwHelpContext
;
7139 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7141 }else {/* for a member */
7142 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
7145 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7147 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7149 *pdwHelpContext
=pFDesc
->helpcontext
;
7151 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7154 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7157 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7159 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7161 *pdwHelpContext
=pVDesc
->HelpContext
;
7163 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7168 if(This
->impltypes
&&
7169 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
7170 /* recursive search */
7173 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7174 if(SUCCEEDED(result
)) {
7175 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7176 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7177 ITypeInfo_Release(pTInfo
);
7180 WARN("Could not search inherited interface!\n");
7183 WARN("member %d not found\n", memid
);
7184 return TYPE_E_ELEMENTNOTFOUND
;
7187 /* ITypeInfo::GetDllEntry
7189 * Retrieves a description or specification of an entry point for a function
7192 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7193 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7196 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7197 const TLBFuncDesc
*pFDesc
;
7199 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7201 if (pBstrDllName
) *pBstrDllName
= NULL
;
7202 if (pBstrName
) *pBstrName
= NULL
;
7203 if (pwOrdinal
) *pwOrdinal
= 0;
7205 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
7206 return TYPE_E_BADMODULEKIND
;
7208 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
7210 dump_TypeInfo(This
);
7212 dump_TLBFuncDescOne(pFDesc
);
7215 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7217 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7219 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7227 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7230 return TYPE_E_ELEMENTNOTFOUND
;
7233 /* internal function to make the inherited interfaces' methods appear
7234 * part of the interface */
7235 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7236 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7238 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7241 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7243 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7245 ITypeInfo
*pSubTypeInfo
;
7247 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7251 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7253 ITypeInfo_Release(pSubTypeInfo
);
7257 *hRefType
-= DISPATCH_HREF_OFFSET
;
7259 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7260 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7265 /* ITypeInfo::GetRefTypeInfo
7267 * If a type description references other type descriptions, it retrieves
7268 * the referenced type descriptions.
7270 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7273 ITypeInfo
**ppTInfo
)
7275 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7276 HRESULT result
= E_FAIL
;
7279 return E_INVALIDARG
;
7281 if ((INT
)hRefType
< 0) {
7282 ITypeInfoImpl
*pTypeInfoImpl
;
7284 if (!(This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7285 !(This
->TypeAttr
.typekind
== TKIND_INTERFACE
||
7286 This
->TypeAttr
.typekind
== TKIND_DISPATCH
))
7287 return TYPE_E_ELEMENTNOTFOUND
;
7289 /* when we meet a DUAL typeinfo, we must create the alternate
7292 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7294 *pTypeInfoImpl
= *This
;
7295 pTypeInfoImpl
->ref
= 0;
7297 if (This
->TypeAttr
.typekind
== TKIND_INTERFACE
)
7298 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_DISPATCH
;
7300 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7302 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7303 /* the AddRef implicitly adds a reference to the parent typelib, which
7304 * stops the copied data from being destroyed until the new typeinfo's
7305 * refcount goes to zero, but we need to signal to the new instance to
7306 * not free its data structures when it is destroyed */
7307 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7309 ITypeInfo_AddRef(*ppTInfo
);
7312 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7313 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
))
7315 HREFTYPE href_dispatch
= hRefType
;
7316 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7318 TLBRefType
*ref_type
;
7319 ITypeLib
*pTLib
= NULL
;
7322 if(!(hRefType
& 0x1)){
7323 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7325 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7328 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7329 ITypeInfo_AddRef(*ppTInfo
);
7333 result
= TYPE_E_ELEMENTNOTFOUND
;
7337 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7339 if(ref_type
->reference
== (hRefType
& (~0x3)))
7342 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7344 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7348 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7350 TRACE("internal reference\n");
7351 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7353 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7354 TRACE("typeinfo in imported typelib that is already loaded\n");
7355 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7356 ITypeLib_AddRef(pTLib
);
7359 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7360 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
7361 ref_type
->pImpTLInfo
->wVersionMajor
,
7362 ref_type
->pImpTLInfo
->wVersionMinor
,
7363 ref_type
->pImpTLInfo
->lcid
,
7366 if(FAILED(result
)) {
7367 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
7368 result
=LoadTypeLib(libnam
, &pTLib
);
7369 SysFreeString(libnam
);
7371 if(SUCCEEDED(result
)) {
7372 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7373 ITypeLib_AddRef(pTLib
);
7377 if(SUCCEEDED(result
)) {
7378 if(ref_type
->index
== TLB_REF_USE_GUID
)
7379 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, &ref_type
->guid
, ppTInfo
);
7381 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7384 ITypeLib_Release(pTLib
);
7388 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7389 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7393 /* ITypeInfo::AddressOfMember
7395 * Retrieves the addresses of static functions or variables, such as those
7398 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7399 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7401 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7407 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7409 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7413 module
= LoadLibraryW(dll
);
7416 ERR("couldn't load %s\n", debugstr_w(dll
));
7418 SysFreeString(entry
);
7419 return STG_E_FILENOTFOUND
;
7421 /* FIXME: store library somewhere where we can free it */
7426 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7427 entryA
= heap_alloc(len
);
7428 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7430 *ppv
= GetProcAddress(module
, entryA
);
7432 ERR("function not found %s\n", debugstr_a(entryA
));
7438 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7440 ERR("function not found %d\n", ordinal
);
7444 SysFreeString(entry
);
7447 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7452 /* ITypeInfo::CreateInstance
7454 * Creates a new instance of a type that describes a component object class
7457 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7458 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7460 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7464 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7470 WARN("Not able to aggregate\n");
7471 return CLASS_E_NOAGGREGATION
;
7474 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7475 if(FAILED(hr
)) return hr
;
7477 if(pTA
->typekind
!= TKIND_COCLASS
)
7479 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7485 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7488 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7489 TRACE("GetActiveObject rets %08x\n", hr
);
7492 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7493 IUnknown_Release(pUnk
);
7498 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7499 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7503 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7507 /* ITypeInfo::GetMops
7509 * Retrieves marshalling information.
7511 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7514 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7515 FIXME("(%p %d) stub!\n", This
, memid
);
7520 /* ITypeInfo::GetContainingTypeLib
7522 * Retrieves the containing type library and the index of the type description
7523 * within that type library.
7525 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7526 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7528 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7530 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7532 *pIndex
=This
->index
;
7533 TRACE("returning pIndex=%d\n", *pIndex
);
7537 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7538 ITypeLib_AddRef(*ppTLib
);
7539 TRACE("returning ppTLib=%p\n", *ppTLib
);
7545 /* ITypeInfo::ReleaseTypeAttr
7547 * Releases a TYPEATTR previously returned by GetTypeAttr.
7550 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7551 TYPEATTR
* pTypeAttr
)
7553 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7554 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7555 heap_free(pTypeAttr
);
7558 /* ITypeInfo::ReleaseFuncDesc
7560 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7562 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7564 FUNCDESC
*pFuncDesc
)
7566 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7569 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7571 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7572 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7573 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7575 SysFreeString((BSTR
)pFuncDesc
);
7578 /* ITypeInfo::ReleaseVarDesc
7580 * Releases a VARDESC previously returned by GetVarDesc.
7582 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7585 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7586 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7588 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
7589 if (pVarDesc
->varkind
== VAR_CONST
)
7590 VariantClear(pVarDesc
->u
.lpvarValue
);
7591 SysFreeString((BSTR
)pVarDesc
);
7594 /* ITypeInfo2::GetTypeKind
7596 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7599 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7600 TYPEKIND
*pTypeKind
)
7602 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7603 *pTypeKind
=This
->TypeAttr
.typekind
;
7604 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7608 /* ITypeInfo2::GetTypeFlags
7610 * Returns the type flags without any allocations. This returns a DWORD type
7611 * flag, which expands the type flags without growing the TYPEATTR (type
7615 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7617 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7618 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
7619 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7623 /* ITypeInfo2::GetFuncIndexOfMemId
7624 * Binds to a specific member based on a known DISPID, where the member name
7625 * is not known (for example, when binding to a default member).
7628 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7629 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7631 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7635 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7636 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7637 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7640 if(fdc
< This
->TypeAttr
.cFuncs
) {
7644 result
= TYPE_E_ELEMENTNOTFOUND
;
7646 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7647 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7651 /* TypeInfo2::GetVarIndexOfMemId
7653 * Binds to a specific member based on a known DISPID, where the member name
7654 * is not known (for example, when binding to a default member).
7657 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7658 MEMBERID memid
, UINT
*pVarIndex
)
7660 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7661 TLBVarDesc
*pVarInfo
;
7663 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7665 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7667 return TYPE_E_ELEMENTNOTFOUND
;
7669 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7674 /* ITypeInfo2::GetCustData
7676 * Gets the custom data
7678 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7683 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7684 TLBCustData
*pCData
;
7686 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7688 if(!guid
|| !pVarVal
)
7689 return E_INVALIDARG
;
7691 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
7693 VariantInit( pVarVal
);
7695 VariantCopy( pVarVal
, &pCData
->data
);
7697 VariantClear( pVarVal
);
7701 /* ITypeInfo2::GetFuncCustData
7703 * Gets the custom data
7705 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7711 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7712 TLBCustData
*pCData
;
7713 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7715 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7717 if(index
>= This
->TypeAttr
.cFuncs
)
7718 return TYPE_E_ELEMENTNOTFOUND
;
7720 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7722 return TYPE_E_ELEMENTNOTFOUND
;
7724 VariantInit(pVarVal
);
7725 VariantCopy(pVarVal
, &pCData
->data
);
7730 /* ITypeInfo2::GetParamCustData
7732 * Gets the custom data
7734 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7741 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7742 TLBCustData
*pCData
;
7743 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7745 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7746 debugstr_guid(guid
), pVarVal
);
7748 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7749 return TYPE_E_ELEMENTNOTFOUND
;
7751 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7752 return TYPE_E_ELEMENTNOTFOUND
;
7754 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7756 return TYPE_E_ELEMENTNOTFOUND
;
7758 VariantInit(pVarVal
);
7759 VariantCopy(pVarVal
, &pCData
->data
);
7764 /* ITypeInfo2::GetVarCustData
7766 * Gets the custom data
7768 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7774 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7775 TLBCustData
*pCData
;
7776 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7778 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7780 if(index
>= This
->TypeAttr
.cVars
)
7781 return TYPE_E_ELEMENTNOTFOUND
;
7783 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7785 return TYPE_E_ELEMENTNOTFOUND
;
7787 VariantInit(pVarVal
);
7788 VariantCopy(pVarVal
, &pCData
->data
);
7793 /* ITypeInfo2::GetImplCustData
7795 * Gets the custom data
7797 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7803 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7804 TLBCustData
*pCData
;
7805 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7807 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7809 if(index
>= This
->TypeAttr
.cImplTypes
)
7810 return TYPE_E_ELEMENTNOTFOUND
;
7812 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7814 return TYPE_E_ELEMENTNOTFOUND
;
7816 VariantInit(pVarVal
);
7817 VariantCopy(pVarVal
, &pCData
->data
);
7822 /* ITypeInfo2::GetDocumentation2
7824 * Retrieves the documentation string, the complete Help file name and path,
7825 * the localization context to use, and the context ID for the library Help
7826 * topic in the Help file.
7829 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7833 BSTR
*pbstrHelpString
,
7834 DWORD
*pdwHelpStringContext
,
7835 BSTR
*pbstrHelpStringDll
)
7837 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7838 const TLBFuncDesc
*pFDesc
;
7839 const TLBVarDesc
*pVDesc
;
7840 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7841 "HelpStringContext(%p) HelpStringDll(%p)\n",
7842 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7843 pbstrHelpStringDll
);
7844 /* the help string should be obtained from the helpstringdll,
7845 * using the _DLLGetDocumentation function, based on the supplied
7846 * lcid. Nice to do sometime...
7848 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7850 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
7851 if(pdwHelpStringContext
)
7852 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7853 if(pbstrHelpStringDll
)
7854 *pbstrHelpStringDll
=
7855 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7857 }else {/* for a member */
7858 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
7861 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7862 if(pdwHelpStringContext
)
7863 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7864 if(pbstrHelpStringDll
)
7865 *pbstrHelpStringDll
=
7866 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7869 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7872 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7873 if(pdwHelpStringContext
)
7874 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7875 if(pbstrHelpStringDll
)
7876 *pbstrHelpStringDll
=
7877 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7881 return TYPE_E_ELEMENTNOTFOUND
;
7884 /* ITypeInfo2::GetAllCustData
7886 * Gets all custom data items for the Type info.
7889 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7891 CUSTDATA
*pCustData
)
7893 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7895 TRACE("%p %p\n", This
, pCustData
);
7897 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
7900 /* ITypeInfo2::GetAllFuncCustData
7902 * Gets all custom data items for the specified Function
7905 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7908 CUSTDATA
*pCustData
)
7910 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7911 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7913 TRACE("%p %u %p\n", This
, index
, pCustData
);
7915 if(index
>= This
->TypeAttr
.cFuncs
)
7916 return TYPE_E_ELEMENTNOTFOUND
;
7918 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
7921 /* ITypeInfo2::GetAllParamCustData
7923 * Gets all custom data items for the Functions
7926 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7927 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7929 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7930 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7932 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
7934 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7935 return TYPE_E_ELEMENTNOTFOUND
;
7937 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7938 return TYPE_E_ELEMENTNOTFOUND
;
7940 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
7943 /* ITypeInfo2::GetAllVarCustData
7945 * Gets all custom data items for the specified Variable
7948 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7949 UINT index
, CUSTDATA
*pCustData
)
7951 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7952 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
7954 TRACE("%p %u %p\n", This
, index
, pCustData
);
7956 if(index
>= This
->TypeAttr
.cVars
)
7957 return TYPE_E_ELEMENTNOTFOUND
;
7959 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
7962 /* ITypeInfo2::GetAllImplCustData
7964 * Gets all custom data items for the specified implementation type
7967 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7970 CUSTDATA
*pCustData
)
7972 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7973 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7975 TRACE("%p %u %p\n", This
, index
, pCustData
);
7977 if(index
>= This
->TypeAttr
.cImplTypes
)
7978 return TYPE_E_ELEMENTNOTFOUND
;
7980 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
7983 static const ITypeInfo2Vtbl tinfvt
=
7986 ITypeInfo_fnQueryInterface
,
7988 ITypeInfo_fnRelease
,
7990 ITypeInfo_fnGetTypeAttr
,
7991 ITypeInfo_fnGetTypeComp
,
7992 ITypeInfo_fnGetFuncDesc
,
7993 ITypeInfo_fnGetVarDesc
,
7994 ITypeInfo_fnGetNames
,
7995 ITypeInfo_fnGetRefTypeOfImplType
,
7996 ITypeInfo_fnGetImplTypeFlags
,
7997 ITypeInfo_fnGetIDsOfNames
,
7999 ITypeInfo_fnGetDocumentation
,
8000 ITypeInfo_fnGetDllEntry
,
8001 ITypeInfo_fnGetRefTypeInfo
,
8002 ITypeInfo_fnAddressOfMember
,
8003 ITypeInfo_fnCreateInstance
,
8004 ITypeInfo_fnGetMops
,
8005 ITypeInfo_fnGetContainingTypeLib
,
8006 ITypeInfo_fnReleaseTypeAttr
,
8007 ITypeInfo_fnReleaseFuncDesc
,
8008 ITypeInfo_fnReleaseVarDesc
,
8010 ITypeInfo2_fnGetTypeKind
,
8011 ITypeInfo2_fnGetTypeFlags
,
8012 ITypeInfo2_fnGetFuncIndexOfMemId
,
8013 ITypeInfo2_fnGetVarIndexOfMemId
,
8014 ITypeInfo2_fnGetCustData
,
8015 ITypeInfo2_fnGetFuncCustData
,
8016 ITypeInfo2_fnGetParamCustData
,
8017 ITypeInfo2_fnGetVarCustData
,
8018 ITypeInfo2_fnGetImplTypeCustData
,
8019 ITypeInfo2_fnGetDocumentation2
,
8020 ITypeInfo2_fnGetAllCustData
,
8021 ITypeInfo2_fnGetAllFuncCustData
,
8022 ITypeInfo2_fnGetAllParamCustData
,
8023 ITypeInfo2_fnGetAllVarCustData
,
8024 ITypeInfo2_fnGetAllImplTypeCustData
,
8027 /******************************************************************************
8028 * CreateDispTypeInfo [OLEAUT32.31]
8030 * Build type information for an object so it can be called through an
8031 * IDispatch interface.
8034 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8035 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8038 * This call allows an objects methods to be accessed through IDispatch, by
8039 * building an ITypeInfo object that IDispatch can use to call through.
8041 HRESULT WINAPI
CreateDispTypeInfo(
8042 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8043 LCID lcid
, /* [I] Locale Id */
8044 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8046 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8047 ITypeLibImpl
*pTypeLibImpl
;
8048 unsigned int param
, func
;
8049 TLBFuncDesc
*pFuncDesc
;
8053 pTypeLibImpl
= TypeLibImpl_Constructor();
8054 if (!pTypeLibImpl
) return E_FAIL
;
8056 pTypeLibImpl
->TypeInfoCount
= 2;
8057 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8059 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8060 pTIIface
->pTypeLib
= pTypeLibImpl
;
8061 pTIIface
->index
= 0;
8062 pTIIface
->Name
= NULL
;
8063 pTIIface
->dwHelpContext
= -1;
8064 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
8065 pTIIface
->TypeAttr
.lcid
= lcid
;
8066 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
8067 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
8068 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
8069 pTIIface
->TypeAttr
.cbAlignment
= 2;
8070 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
8071 pTIIface
->TypeAttr
.cbSizeVft
= -1;
8072 pTIIface
->TypeAttr
.cFuncs
= 0;
8073 pTIIface
->TypeAttr
.cImplTypes
= 0;
8074 pTIIface
->TypeAttr
.cVars
= 0;
8075 pTIIface
->TypeAttr
.wTypeFlags
= 0;
8076 pTIIface
->hreftype
= 0;
8078 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8079 pFuncDesc
= pTIIface
->funcdescs
;
8080 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8081 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8082 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8083 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8084 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8085 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8086 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8087 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8088 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8089 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8090 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8091 pFuncDesc
->funcdesc
.cScodes
= 0;
8092 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8093 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8094 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8095 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8096 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8097 md
->cArgs
* sizeof(ELEMDESC
));
8098 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8099 for(param
= 0; param
< md
->cArgs
; param
++) {
8100 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8101 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8103 pFuncDesc
->helpcontext
= 0;
8104 pFuncDesc
->HelpStringContext
= 0;
8105 pFuncDesc
->HelpString
= NULL
;
8106 pFuncDesc
->Entry
= NULL
;
8107 list_init(&pFuncDesc
->custdata_list
);
8108 pTIIface
->TypeAttr
.cFuncs
++;
8112 dump_TypeInfo(pTIIface
);
8114 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8115 pTIClass
->pTypeLib
= pTypeLibImpl
;
8116 pTIClass
->index
= 1;
8117 pTIClass
->Name
= NULL
;
8118 pTIClass
->dwHelpContext
= -1;
8119 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
8120 pTIClass
->TypeAttr
.lcid
= lcid
;
8121 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
8122 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
8123 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
8124 pTIClass
->TypeAttr
.cbAlignment
= 2;
8125 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
8126 pTIClass
->TypeAttr
.cbSizeVft
= -1;
8127 pTIClass
->TypeAttr
.cFuncs
= 0;
8128 pTIClass
->TypeAttr
.cImplTypes
= 1;
8129 pTIClass
->TypeAttr
.cVars
= 0;
8130 pTIClass
->TypeAttr
.wTypeFlags
= 0;
8131 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8133 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8135 ref
= heap_alloc_zero(sizeof(*ref
));
8136 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8137 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8139 dump_TypeInfo(pTIClass
);
8141 *pptinfo
= (ITypeInfo
*)pTIClass
;
8143 ITypeInfo_AddRef(*pptinfo
);
8144 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8150 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8152 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8154 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
8157 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8159 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8161 return ITypeInfo_AddRef((ITypeInfo
*)This
);
8164 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8166 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8168 return ITypeInfo_Release((ITypeInfo
*)This
);
8171 static HRESULT WINAPI
ITypeComp_fnBind(
8176 ITypeInfo
** ppTInfo
,
8177 DESCKIND
* pDescKind
,
8180 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8181 const TLBFuncDesc
*pFDesc
;
8182 const TLBVarDesc
*pVDesc
;
8183 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8186 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8188 *pDescKind
= DESCKIND_NONE
;
8189 pBindPtr
->lpfuncdesc
= NULL
;
8192 for(fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
8193 pFDesc
= &This
->funcdescs
[fdc
];
8194 if (!strcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8195 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8198 /* name found, but wrong flags */
8199 hr
= TYPE_E_TYPEMISMATCH
;
8203 if (fdc
< This
->TypeAttr
.cFuncs
)
8205 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8207 &pBindPtr
->lpfuncdesc
,
8208 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
8211 *pDescKind
= DESCKIND_FUNCDESC
;
8212 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8213 ITypeInfo_AddRef(*ppTInfo
);
8216 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, szName
);
8218 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8221 *pDescKind
= DESCKIND_VARDESC
;
8222 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8223 ITypeInfo_AddRef(*ppTInfo
);
8227 /* FIXME: search each inherited interface, not just the first */
8228 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8229 /* recursive search */
8233 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8236 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8237 ITypeInfo_Release(pTInfo
);
8241 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8242 ITypeComp_Release(pTComp
);
8245 WARN("Could not search inherited interface!\n");
8247 if (hr
== DISP_E_MEMBERNOTFOUND
)
8249 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8253 static HRESULT WINAPI
ITypeComp_fnBindType(
8257 ITypeInfo
** ppTInfo
,
8258 ITypeComp
** ppTComp
)
8260 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8262 /* strange behaviour (does nothing) but like the
8265 if (!ppTInfo
|| !ppTComp
)
8274 static const ITypeCompVtbl tcompvt
=
8277 ITypeComp_fnQueryInterface
,
8279 ITypeComp_fnRelease
,
8282 ITypeComp_fnBindType
8285 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8286 REFIID riid
, void **object
)
8288 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8290 return ITypeLib2_QueryInterface((ITypeLib2
*)This
, riid
, object
);
8293 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8295 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8297 return ITypeLib2_AddRef((ITypeLib2
*)This
);
8300 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8302 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8304 return ITypeLib2_Release((ITypeLib2
*)This
);
8307 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8308 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8310 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8311 ITypeInfoImpl
*info
;
8314 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8316 if (!ctinfo
|| !name
)
8317 return E_INVALIDARG
;
8319 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8321 return TYPE_E_NAMECONFLICT
;
8323 if (This
->typeinfos
)
8324 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8325 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8327 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8329 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8331 info
->pTypeLib
= This
;
8332 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8333 info
->index
= This
->TypeInfoCount
;
8334 info
->TypeAttr
.typekind
= kind
;
8335 info
->TypeAttr
.cbAlignment
= 4;
8337 switch(info
->TypeAttr
.typekind
) {
8339 case TKIND_INTERFACE
:
8340 case TKIND_DISPATCH
:
8342 info
->TypeAttr
.cbSizeInstance
= 4;
8346 info
->TypeAttr
.cbSizeInstance
= 0;
8349 info
->TypeAttr
.cbSizeInstance
= 2;
8352 info
->TypeAttr
.cbSizeInstance
= -0x75;
8355 FIXME("unrecognized typekind %d\n", info
->TypeAttr
.typekind
);
8356 info
->TypeAttr
.cbSizeInstance
= 0xdeadbeef;
8360 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8361 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8363 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8367 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8369 ++This
->TypeInfoCount
;
8374 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8377 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8379 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8382 return E_INVALIDARG
;
8384 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8389 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8390 WORD majorVerNum
, WORD minorVerNum
)
8392 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8394 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8396 This
->ver_major
= majorVerNum
;
8397 This
->ver_minor
= minorVerNum
;
8402 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8405 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8407 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8409 memcpy(&This
->guid
, guid
, sizeof(GUID
));
8414 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8417 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8419 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8422 return E_INVALIDARG
;
8424 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8429 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8430 LPOLESTR helpFileName
)
8432 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8434 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8437 return E_INVALIDARG
;
8439 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8444 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8447 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8449 TRACE("%p %d\n", This
, helpContext
);
8451 This
->dwHelpContext
= helpContext
;
8456 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8459 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8461 TRACE("%p %x\n", This
, lcid
);
8463 This
->set_lcid
= lcid
;
8468 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8471 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8473 TRACE("%p %x\n", This
, libFlags
);
8475 This
->libflags
= libFlags
;
8480 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
8482 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8483 FIXME("%p - stub\n", This
);
8487 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
8490 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8491 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
8495 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
8496 REFGUID guid
, VARIANT
*varVal
)
8498 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8499 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
8503 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
8504 ULONG helpStringContext
)
8506 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8507 FIXME("%p %u - stub\n", This
, helpStringContext
);
8511 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
8514 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8515 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
8518 return E_INVALIDARG
;
8520 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
8525 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
8526 ICreateTypeLib2_fnQueryInterface
,
8527 ICreateTypeLib2_fnAddRef
,
8528 ICreateTypeLib2_fnRelease
,
8529 ICreateTypeLib2_fnCreateTypeInfo
,
8530 ICreateTypeLib2_fnSetName
,
8531 ICreateTypeLib2_fnSetVersion
,
8532 ICreateTypeLib2_fnSetGuid
,
8533 ICreateTypeLib2_fnSetDocString
,
8534 ICreateTypeLib2_fnSetHelpFileName
,
8535 ICreateTypeLib2_fnSetHelpContext
,
8536 ICreateTypeLib2_fnSetLcid
,
8537 ICreateTypeLib2_fnSetLibFlags
,
8538 ICreateTypeLib2_fnSaveAllChanges
,
8539 ICreateTypeLib2_fnDeleteTypeInfo
,
8540 ICreateTypeLib2_fnSetCustData
,
8541 ICreateTypeLib2_fnSetHelpStringContext
,
8542 ICreateTypeLib2_fnSetHelpStringDll
8545 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
8546 REFIID riid
, void **object
)
8548 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8550 return ITypeInfo2_QueryInterface((ITypeInfo2
*)This
, riid
, object
);
8553 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
8555 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8557 return ITypeInfo2_AddRef((ITypeInfo2
*)This
);
8560 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
8562 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8564 return ITypeInfo2_Release((ITypeInfo2
*)This
);
8567 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
8570 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8572 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8574 memcpy(&This
->TypeAttr
.guid
, guid
, sizeof(GUID
));
8579 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
8582 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8586 TRACE("%p %x\n", This
, typeFlags
);
8588 if (typeFlags
& TYPEFLAG_FDUAL
) {
8589 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
8591 ITypeInfo
*dispatch
;
8595 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
8599 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
8600 ITypeLib_Release(stdole
);
8604 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
8605 ITypeInfo_Release(dispatch
);
8610 old_flags
= This
->TypeAttr
.wTypeFlags
;
8611 This
->TypeAttr
.wTypeFlags
= typeFlags
;
8613 hres
= ICreateTypeInfo2_LayOut(iface
);
8615 This
->TypeAttr
.wTypeFlags
= old_flags
;
8622 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
8625 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8627 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8630 return E_INVALIDARG
;
8632 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
8637 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
8640 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8642 TRACE("%p %d\n", This
, helpContext
);
8644 This
->dwHelpContext
= helpContext
;
8649 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
8650 WORD majorVerNum
, WORD minorVerNum
)
8652 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8654 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8656 This
->TypeAttr
.wMajorVerNum
= majorVerNum
;
8657 This
->TypeAttr
.wMinorVerNum
= minorVerNum
;
8662 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
8663 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
8665 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8667 ITypeLib
*container
;
8668 TLBRefType
*ref_type
;
8674 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
8676 if (!typeInfo
|| !refType
)
8677 return E_INVALIDARG
;
8679 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
8683 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
8684 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
8686 ITypeLib_Release(container
);
8688 *refType
= target
->hreftype
;
8693 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
8695 ITypeLib_Release(container
);
8699 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
8700 if(IsEqualGUID(&implib
->guid
, &libattr
->guid
) &&
8701 implib
->lcid
== libattr
->lcid
&&
8702 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
8703 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
8707 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
8708 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
8710 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
8711 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
8712 implib
->name
= SysAllocString(our_container
->path
);
8714 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
8715 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
8717 implib
->name
= NULL
;
8718 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
8722 implib
->guid
= libattr
->guid
;
8723 implib
->lcid
= libattr
->lcid
;
8724 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
8725 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
8727 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
8730 ITypeLib_ReleaseTLibAttr(container
, libattr
);
8731 ITypeLib_Release(container
);
8733 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
8738 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
8739 if(ref_type
->index
== TLB_REF_USE_GUID
&&
8740 IsEqualGUID(&ref_type
->guid
, &typeattr
->guid
) &&
8741 ref_type
->tkind
== typeattr
->typekind
)
8746 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
8747 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
8749 ref_type
->tkind
= typeattr
->typekind
;
8750 ref_type
->pImpTLInfo
= implib
;
8751 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
8753 ref_type
->index
= TLB_REF_USE_GUID
;
8755 ref_type
->guid
= typeattr
->guid
;
8757 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
8760 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
8762 *refType
= ref_type
->reference
| 0x1;
8764 if(IsEqualGUID(&ref_type
->guid
, &IID_IDispatch
))
8765 This
->pTypeLib
->dispatch_href
= *refType
;
8770 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
8771 UINT index
, FUNCDESC
*funcDesc
)
8773 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8774 TLBFuncDesc tmp_func_desc
, *func_desc
;
8779 TRACE("%p %u %p\n", This
, index
, funcDesc
);
8781 if (!funcDesc
|| funcDesc
->oVft
& 3)
8782 return E_INVALIDARG
;
8784 switch (This
->TypeAttr
.typekind
) {
8786 if (funcDesc
->funckind
!= FUNC_STATIC
)
8787 return TYPE_E_BADMODULEKIND
;
8789 case TKIND_DISPATCH
:
8790 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
8791 return TYPE_E_BADMODULEKIND
;
8794 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
8795 return TYPE_E_BADMODULEKIND
;
8798 if (index
> This
->TypeAttr
.cFuncs
)
8799 return TYPE_E_ELEMENTNOTFOUND
;
8801 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
8803 return TYPE_E_INCONSISTENTPROPFUNCS
;
8805 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
8806 TLBFuncDesc_Constructor(&tmp_func_desc
);
8808 tmp_func_desc
.funcdesc
= *funcDesc
;
8810 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
8811 tmp_func_desc
.funcdesc
.oVft
|= 1;
8813 if (funcDesc
->cScodes
) {
8814 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
8815 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
8817 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
8819 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
8820 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
8821 buf_size
+= sizeof(ELEMDESC
);
8822 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
8824 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
8825 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
8827 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
8829 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
8830 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
8834 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
8835 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
8836 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
8838 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
8839 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
8842 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
8843 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
8844 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
8845 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
8847 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
8848 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
8854 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
8856 if (This
->funcdescs
) {
8857 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
8858 sizeof(TLBFuncDesc
) * (This
->TypeAttr
.cFuncs
+ 1));
8860 if (index
< This
->TypeAttr
.cFuncs
) {
8861 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
8862 (This
->TypeAttr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
8863 func_desc
= This
->funcdescs
+ index
;
8865 func_desc
= This
->funcdescs
+ This
->TypeAttr
.cFuncs
;
8867 /* move custdata lists to the new memory location */
8868 for(i
= 0; i
< This
->TypeAttr
.cFuncs
+ 1; ++i
){
8870 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
8871 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
8872 list_init(&fd
->custdata_list
);
8874 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
8875 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
8880 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
8882 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
8883 list_init(&func_desc
->custdata_list
);
8885 ++This
->TypeAttr
.cFuncs
;
8887 This
->needs_layout
= TRUE
;
8892 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
8893 UINT index
, HREFTYPE refType
)
8895 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8896 TLBImplType
*impl_type
;
8899 TRACE("%p %u %d\n", This
, index
, refType
);
8901 switch(This
->TypeAttr
.typekind
){
8902 case TKIND_COCLASS
: {
8904 FIXME("Unhandled index: -1\n");
8908 if(index
!= This
->TypeAttr
.cImplTypes
)
8909 return TYPE_E_ELEMENTNOTFOUND
;
8913 case TKIND_INTERFACE
:
8914 case TKIND_DISPATCH
:
8915 if (index
!= 0 || This
->TypeAttr
.cImplTypes
)
8916 return TYPE_E_ELEMENTNOTFOUND
;
8919 FIXME("Unimplemented typekind: %d\n", This
->TypeAttr
.typekind
);
8923 if (This
->impltypes
){
8926 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
8927 sizeof(TLBImplType
) * (This
->TypeAttr
.cImplTypes
+ 1));
8929 if (index
< This
->TypeAttr
.cImplTypes
) {
8930 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
8931 (This
->TypeAttr
.cImplTypes
- index
) * sizeof(TLBImplType
));
8932 impl_type
= This
->impltypes
+ index
;
8934 impl_type
= This
->impltypes
+ This
->TypeAttr
.cImplTypes
;
8936 /* move custdata lists to the new memory location */
8937 for(i
= 0; i
< This
->TypeAttr
.cImplTypes
+ 1; ++i
){
8939 TLBImplType
*it
= &This
->impltypes
[i
];
8940 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
8941 list_init(&it
->custdata_list
);
8943 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
8944 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
8949 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
8951 memset(impl_type
, 0, sizeof(TLBImplType
));
8952 TLBImplType_Constructor(impl_type
);
8953 impl_type
->hRef
= refType
;
8955 ++This
->TypeAttr
.cImplTypes
;
8957 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
8958 This
->TypeAttr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
8960 hres
= ICreateTypeInfo2_LayOut(iface
);
8967 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
8968 UINT index
, INT implTypeFlags
)
8970 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8971 TLBImplType
*impl_type
= &This
->impltypes
[index
];
8973 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
8975 if (This
->TypeAttr
.typekind
!= TKIND_COCLASS
)
8976 return TYPE_E_BADMODULEKIND
;
8978 if (index
>= This
->TypeAttr
.cImplTypes
)
8979 return TYPE_E_ELEMENTNOTFOUND
;
8981 impl_type
->implflags
= implTypeFlags
;
8986 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
8989 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
8991 TRACE("%p %d\n", This
, alignment
);
8993 This
->TypeAttr
.cbAlignment
= alignment
;
8998 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
9001 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9003 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
9006 return E_INVALIDARG
;
9008 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
9010 This
->TypeAttr
.lpstrSchema
= This
->Schema
->str
;
9015 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
9016 UINT index
, VARDESC
*varDesc
)
9018 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9019 FIXME("%p %u %p - stub\n", This
, index
, varDesc
);
9023 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
9024 UINT index
, LPOLESTR
*names
, UINT numNames
)
9026 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9027 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
9030 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
9033 return E_INVALIDARG
;
9035 if (index
>= This
->TypeAttr
.cFuncs
|| numNames
== 0)
9036 return TYPE_E_ELEMENTNOTFOUND
;
9038 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
9039 if(numNames
> func_desc
->funcdesc
.cParams
)
9040 return TYPE_E_ELEMENTNOTFOUND
;
9042 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
9043 return TYPE_E_ELEMENTNOTFOUND
;
9045 for(i
= 0; i
< This
->TypeAttr
.cFuncs
; ++i
) {
9046 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
9047 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
9048 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
9049 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
9050 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
9052 return TYPE_E_AMBIGUOUSNAME
;
9056 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
9058 for (i
= 1; i
< numNames
; ++i
) {
9059 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
9060 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
9066 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
9067 UINT index
, LPOLESTR name
)
9069 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9070 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(name
));
9074 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
9075 TYPEDESC
*tdescAlias
)
9077 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9078 FIXME("%p %p - stub\n", This
, tdescAlias
);
9082 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
9083 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
9085 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9086 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
9090 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
9091 UINT index
, LPOLESTR docString
)
9093 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9094 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
9098 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
9099 UINT index
, LPOLESTR docString
)
9101 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9102 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
9106 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
9107 UINT index
, DWORD helpContext
)
9109 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9110 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
9112 TRACE("%p %u %d\n", This
, index
, helpContext
);
9114 if(index
>= This
->TypeAttr
.cFuncs
)
9115 return TYPE_E_ELEMENTNOTFOUND
;
9117 func_desc
->helpcontext
= helpContext
;
9122 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
9123 UINT index
, DWORD helpContext
)
9125 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9126 FIXME("%p %u %d - stub\n", This
, index
, helpContext
);
9130 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
9131 UINT index
, BSTR bstrMops
)
9133 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9134 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
9138 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
9141 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9143 TRACE("%p %p\n", This
, idlDesc
);
9146 return E_INVALIDARG
;
9148 This
->TypeAttr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
9149 This
->TypeAttr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
9154 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
9156 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9158 TLBFuncDesc
*func_desc
;
9159 UINT user_vft
= 0, i
, depth
= 0;
9160 HRESULT hres
= S_OK
;
9162 TRACE("%p\n", This
);
9164 This
->needs_layout
= FALSE
;
9166 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
9170 if (This
->TypeAttr
.typekind
== TKIND_INTERFACE
) {
9175 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
9177 if (SUCCEEDED(hres
)) {
9178 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
9180 if (SUCCEEDED(hres
)) {
9181 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
9183 ITypeInfo_Release(inh
);
9184 ITypeInfo_Release(tinfo
);
9187 This
->TypeAttr
.cbSizeVft
= attr
->cbSizeVft
* 4 / sizeof(void*);
9188 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
9192 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
9193 if(SUCCEEDED(hres
)){
9195 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
9196 if(SUCCEEDED(hres
)){
9197 ITypeInfo_Release(inh
);
9201 }while(SUCCEEDED(hres
));
9204 ITypeInfo_Release(inh
);
9205 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
9206 This
->TypeAttr
.cbSizeVft
= 0;
9209 ITypeInfo_Release(tinfo
);
9212 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
9213 This
->TypeAttr
.cbSizeVft
= 0;
9216 ITypeInfo_Release(tinfo
);
9219 } else if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
9220 This
->TypeAttr
.cbSizeVft
= 7 * sizeof(void*);
9222 This
->TypeAttr
.cbSizeVft
= 0;
9224 func_desc
= This
->funcdescs
;
9226 while (i
< This
->TypeAttr
.cFuncs
) {
9227 if (!(func_desc
->funcdesc
.oVft
& 0x1))
9228 func_desc
->funcdesc
.oVft
= This
->TypeAttr
.cbSizeVft
;
9230 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
9231 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
9233 This
->TypeAttr
.cbSizeVft
+= sizeof(void*);
9235 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
9240 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
9242 iter
= This
->funcdescs
;
9243 while (j
< This
->TypeAttr
.cFuncs
) {
9244 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
9246 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->TypeAttr
.cFuncs
;
9249 ++func_desc
->funcdesc
.memid
;
9250 iter
= This
->funcdescs
;
9263 if (user_vft
> This
->TypeAttr
.cbSizeVft
)
9264 This
->TypeAttr
.cbSizeVft
= user_vft
+ sizeof(void*);
9266 ITypeInfo_Release(tinfo
);
9270 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
9273 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9274 FIXME("%p %u - stub\n", This
, index
);
9278 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
9279 MEMBERID memid
, INVOKEKIND invKind
)
9281 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9282 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
9286 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
9289 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9290 FIXME("%p %u - stub\n", This
, index
);
9294 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
9297 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9298 FIXME("%p %x - stub\n", This
, memid
);
9302 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
9305 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9306 FIXME("%p %u - stub\n", This
, index
);
9310 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
9311 REFGUID guid
, VARIANT
*varVal
)
9313 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9315 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
9317 if (!guid
|| !varVal
)
9318 return E_INVALIDARG
;
9320 return TLB_set_custdata(&This
->custdata_list
, guid
, varVal
);
9323 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
9324 UINT index
, REFGUID guid
, VARIANT
*varVal
)
9326 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9327 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
9331 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
9332 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
9334 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9335 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
9339 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
9340 UINT index
, REFGUID guid
, VARIANT
*varVal
)
9342 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9343 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
9347 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
9348 UINT index
, REFGUID guid
, VARIANT
*varVal
)
9350 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9351 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
9355 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
9356 ULONG helpStringContext
)
9358 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9360 TRACE("%p %u\n", This
, helpStringContext
);
9362 This
->dwHelpStringContext
= helpStringContext
;
9367 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
9368 UINT index
, ULONG helpStringContext
)
9370 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9371 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
9375 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
9376 UINT index
, ULONG helpStringContext
)
9378 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9379 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
9383 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
9385 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9386 FIXME("%p - stub\n", This
);
9390 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
9393 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9395 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9398 return E_INVALIDARG
;
9400 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
9405 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
9406 ICreateTypeInfo2_fnQueryInterface
,
9407 ICreateTypeInfo2_fnAddRef
,
9408 ICreateTypeInfo2_fnRelease
,
9409 ICreateTypeInfo2_fnSetGuid
,
9410 ICreateTypeInfo2_fnSetTypeFlags
,
9411 ICreateTypeInfo2_fnSetDocString
,
9412 ICreateTypeInfo2_fnSetHelpContext
,
9413 ICreateTypeInfo2_fnSetVersion
,
9414 ICreateTypeInfo2_fnAddRefTypeInfo
,
9415 ICreateTypeInfo2_fnAddFuncDesc
,
9416 ICreateTypeInfo2_fnAddImplType
,
9417 ICreateTypeInfo2_fnSetImplTypeFlags
,
9418 ICreateTypeInfo2_fnSetAlignment
,
9419 ICreateTypeInfo2_fnSetSchema
,
9420 ICreateTypeInfo2_fnAddVarDesc
,
9421 ICreateTypeInfo2_fnSetFuncAndParamNames
,
9422 ICreateTypeInfo2_fnSetVarName
,
9423 ICreateTypeInfo2_fnSetTypeDescAlias
,
9424 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
9425 ICreateTypeInfo2_fnSetFuncDocString
,
9426 ICreateTypeInfo2_fnSetVarDocString
,
9427 ICreateTypeInfo2_fnSetFuncHelpContext
,
9428 ICreateTypeInfo2_fnSetVarHelpContext
,
9429 ICreateTypeInfo2_fnSetMops
,
9430 ICreateTypeInfo2_fnSetTypeIdldesc
,
9431 ICreateTypeInfo2_fnLayOut
,
9432 ICreateTypeInfo2_fnDeleteFuncDesc
,
9433 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
9434 ICreateTypeInfo2_fnDeleteVarDesc
,
9435 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
9436 ICreateTypeInfo2_fnDeleteImplType
,
9437 ICreateTypeInfo2_fnSetCustData
,
9438 ICreateTypeInfo2_fnSetFuncCustData
,
9439 ICreateTypeInfo2_fnSetParamCustData
,
9440 ICreateTypeInfo2_fnSetVarCustData
,
9441 ICreateTypeInfo2_fnSetImplTypeCustData
,
9442 ICreateTypeInfo2_fnSetHelpStringContext
,
9443 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
9444 ICreateTypeInfo2_fnSetVarHelpStringContext
,
9445 ICreateTypeInfo2_fnInvalidate
,
9446 ICreateTypeInfo2_fnSetName