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 tagTLBGuid
{
964 typedef struct tagTLBCustData
971 /* data structure for import typelibs */
972 typedef struct tagTLBImpLib
974 int offset
; /* offset in the file (MSFT)
975 offset in nametable (SLTG)
976 just used to identify library while reading
978 TLBGuid
*guid
; /* libid */
979 BSTR name
; /* name */
981 LCID lcid
; /* lcid of imported typelib */
983 WORD wVersionMajor
; /* major version number */
984 WORD wVersionMinor
; /* minor version number */
986 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
987 NULL if not yet loaded */
991 typedef struct tagTLBString
{
997 /* internal ITypeLib data */
998 typedef struct tagITypeLibImpl
1000 ITypeLib2 ITypeLib2_iface
;
1001 ITypeComp ITypeComp_iface
;
1002 ICreateTypeLib2 ICreateTypeLib2_iface
;
1012 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1013 * exported to the application as a UNICODE string.
1015 struct list string_list
;
1016 struct list name_list
;
1017 struct list guid_list
;
1019 const TLBString
*Name
;
1020 const TLBString
*DocString
;
1021 const TLBString
*HelpFile
;
1022 const TLBString
*HelpStringDll
;
1023 DWORD dwHelpContext
;
1024 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1025 struct tagITypeInfoImpl
**typeinfos
;
1026 struct list custdata_list
;
1027 struct list implib_list
;
1028 int ctTypeDesc
; /* number of items in type desc array */
1029 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1030 library. Only used while reading MSFT
1032 struct list ref_list
; /* list of ref types in this typelib */
1033 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1036 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1042 static const ITypeLib2Vtbl tlbvt
;
1043 static const ITypeCompVtbl tlbtcvt
;
1044 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1046 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1048 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1051 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1053 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1056 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1058 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1061 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1063 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1066 /* ITypeLib methods */
1067 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1068 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1070 /*======================= ITypeInfo implementation =======================*/
1072 /* data for referenced types */
1073 typedef struct tagTLBRefType
1075 INT index
; /* Type index for internal ref or for external ref
1076 it the format is SLTG. -2 indicates to
1080 TLBGuid
*guid
; /* guid of the referenced type */
1081 /* if index == TLB_REF_USE_GUID */
1083 HREFTYPE reference
; /* The href of this ref */
1084 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1085 TLB_REF_INTERNAL for internal refs
1086 TLB_REF_NOT_FOUND for broken refs */
1091 #define TLB_REF_USE_GUID -2
1093 #define TLB_REF_INTERNAL (void*)-2
1094 #define TLB_REF_NOT_FOUND (void*)-1
1096 /* internal Parameter data */
1097 typedef struct tagTLBParDesc
1099 const TLBString
*Name
;
1100 struct list custdata_list
;
1103 /* internal Function data */
1104 typedef struct tagTLBFuncDesc
1106 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1107 const TLBString
*Name
; /* the name of this function */
1108 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1110 int HelpStringContext
;
1111 const TLBString
*HelpString
;
1112 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1113 struct list custdata_list
;
1116 /* internal Variable data */
1117 typedef struct tagTLBVarDesc
1119 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1120 const TLBString
*Name
; /* the name of this variable */
1122 int HelpStringContext
;
1123 const TLBString
*HelpString
;
1124 struct list custdata_list
;
1127 /* internal implemented interface data */
1128 typedef struct tagTLBImplType
1130 HREFTYPE hRef
; /* hRef of interface */
1131 int implflags
; /* IMPLFLAG_*s */
1132 struct list custdata_list
;
1135 /* internal TypeInfo data */
1136 typedef struct tagITypeInfoImpl
1138 ITypeInfo2 ITypeInfo2_iface
;
1139 ITypeComp ITypeComp_iface
;
1140 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1142 BOOL not_attached_to_typelib
;
1147 MEMBERID memidConstructor
;
1148 MEMBERID memidDestructor
;
1149 LPOLESTR lpstrSchema
;
1150 ULONG cbSizeInstance
;
1160 TYPEDESC tdescAlias
;
1161 IDLDESC idldescType
;
1163 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1164 int index
; /* index in this typelib; */
1165 HREFTYPE hreftype
; /* hreftype for app object binding */
1166 /* type libs seem to store the doc strings in ascii
1167 * so why should we do it in unicode?
1169 const TLBString
*Name
;
1170 const TLBString
*DocString
;
1171 const TLBString
*DllName
;
1172 const TLBString
*Schema
;
1173 DWORD dwHelpContext
;
1174 DWORD dwHelpStringContext
;
1177 TLBFuncDesc
*funcdescs
;
1180 TLBVarDesc
*vardescs
;
1182 /* Implemented Interfaces */
1183 TLBImplType
*impltypes
;
1185 struct list custdata_list
;
1188 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1190 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1193 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1195 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1198 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1200 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1203 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1205 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1208 static const ITypeInfo2Vtbl tinfvt
;
1209 static const ITypeCompVtbl tcompvt
;
1210 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1212 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1213 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1215 typedef struct tagTLBContext
1217 unsigned int oStart
; /* start of TLB in file */
1218 unsigned int pos
; /* current pos */
1219 unsigned int length
; /* total length */
1220 void *mapping
; /* memory mapping */
1221 MSFT_SegDir
* pTblDir
;
1222 ITypeLibImpl
* pLibInfo
;
1226 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1228 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1230 return str
!= NULL
? str
->str
: NULL
;
1233 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1237 return memcmp(left
, str
->str
, len
);
1240 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1242 return guid
!= NULL
? &guid
->guid
: NULL
;
1245 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1247 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1253 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1254 if (pTD
->vt
& VT_RESERVED
)
1255 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1256 if (pTD
->vt
& VT_BYREF
)
1257 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1258 if (pTD
->vt
& VT_ARRAY
)
1259 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1260 if (pTD
->vt
& VT_VECTOR
)
1261 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1262 switch(pTD
->vt
& VT_TYPEMASK
) {
1263 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1264 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1265 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1266 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1267 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1268 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1269 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1270 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1271 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1272 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1273 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1274 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1275 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1276 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1277 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1278 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1279 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1280 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1281 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1282 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1283 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1284 pTD
->u
.hreftype
); break;
1285 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1286 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1287 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1288 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1290 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1291 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1293 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1294 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1295 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1298 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1302 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1304 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1305 dump_TypeDesc(&edesc
->tdesc
,buf
);
1306 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1307 MESSAGE("\t\tu.paramdesc.wParamFlags");
1308 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1309 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1310 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1311 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1312 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1313 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1314 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1315 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1316 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1318 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1320 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1321 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1322 MESSAGE("Param %d:\n",i
);
1323 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1325 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1326 switch (funcdesc
->funckind
) {
1327 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1328 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1329 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1330 case FUNC_STATIC
: MESSAGE("static");break;
1331 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1332 default: MESSAGE("unknown");break;
1334 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1335 switch (funcdesc
->invkind
) {
1336 case INVOKE_FUNC
: MESSAGE("func");break;
1337 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1338 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1339 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1341 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1342 switch (funcdesc
->callconv
) {
1343 case CC_CDECL
: MESSAGE("cdecl");break;
1344 case CC_PASCAL
: MESSAGE("pascal");break;
1345 case CC_STDCALL
: MESSAGE("stdcall");break;
1346 case CC_SYSCALL
: MESSAGE("syscall");break;
1349 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1350 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1351 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1353 MESSAGE("\telemdescFunc (return value type):\n");
1354 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1357 static const char * const typekind_desc
[] =
1370 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1373 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1374 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1375 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1378 dump_FUNCDESC(&(pfd
->funcdesc
));
1380 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1381 if(pfd
->Entry
== NULL
)
1382 MESSAGE("\tentry: (null)\n");
1383 else if(pfd
->Entry
== (void*)-1)
1384 MESSAGE("\tentry: invalid\n");
1385 else if(IS_INTRESOURCE(pfd
->Entry
))
1386 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1388 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1390 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1394 dump_TLBFuncDescOne(pfd
);
1399 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1403 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1409 static void dump_TLBImpLib(const TLBImpLib
*import
)
1411 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1412 debugstr_w(import
->name
));
1413 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1414 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1417 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1421 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1423 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1424 if(ref
->index
== -1)
1425 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1427 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1429 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1431 TRACE_(typelib
)("in lib\n");
1432 dump_TLBImpLib(ref
->pImpTLInfo
);
1437 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1442 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1443 impl
->hRef
, impl
->implflags
);
1449 static void dump_Variant(const VARIANT
* pvar
)
1453 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1457 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1458 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1460 TRACE(",%p", V_BYREF(pvar
));
1462 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1464 TRACE(",%p", V_ARRAY(pvar
));
1466 else switch (V_TYPE(pvar
))
1468 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1469 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1470 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1471 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1473 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1475 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1476 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1477 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1478 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1479 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1480 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1481 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1482 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1483 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1484 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1485 V_CY(pvar
).s
.Lo
); break;
1487 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1488 TRACE(",<invalid>");
1490 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1491 st
.wHour
, st
.wMinute
, st
.wSecond
);
1495 case VT_USERDEFINED
:
1497 case VT_NULL
: break;
1498 default: TRACE(",?"); break;
1504 static void dump_DispParms(const DISPPARAMS
* pdp
)
1508 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1510 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1512 TRACE("named args:\n");
1513 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1514 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1517 if (pdp
->cArgs
&& pdp
->rgvarg
)
1520 for (index
= 0; index
< pdp
->cArgs
; index
++)
1521 dump_Variant( &pdp
->rgvarg
[index
] );
1525 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1527 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1528 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1529 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1530 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1531 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1532 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1533 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1534 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1536 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1537 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1538 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1541 static void dump_VARDESC(const VARDESC
*v
)
1543 MESSAGE("memid %d\n",v
->memid
);
1544 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1545 MESSAGE("oInst %d\n",v
->u
.oInst
);
1546 dump_ELEMDESC(&(v
->elemdescVar
));
1547 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1548 MESSAGE("varkind %d\n",v
->varkind
);
1551 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1553 /* VT_LPWSTR is largest type that, may appear in type description */
1554 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1555 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1556 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1557 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1558 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1559 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1560 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1561 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1564 static void TLB_abort(void)
1569 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1571 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1572 if (!ret
) ERR("cannot allocate memory\n");
1576 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1578 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1579 if (!ret
) ERR("cannot allocate memory\n");
1583 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1585 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1588 void heap_free(void *ptr
)
1590 HeapFree(GetProcessHeap(), 0, ptr
);
1593 /* returns the size required for a deep copy of a typedesc into a
1595 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1599 if (alloc_initial_space
)
1600 size
+= sizeof(TYPEDESC
);
1606 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1609 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1610 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1616 /* deep copy a typedesc into a flat buffer */
1617 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1622 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1631 dest
->u
.lptdesc
= buffer
;
1632 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1635 dest
->u
.lpadesc
= buffer
;
1636 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1637 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1638 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1644 /* free custom data allocated by MSFT_CustData */
1645 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1647 TLBCustData
*cd
, *cdn
;
1648 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1650 list_remove(&cd
->entry
);
1651 VariantClear(&cd
->data
);
1656 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1661 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1662 ret
= SysAllocStringLen(NULL
, len
- 1);
1663 if (!ret
) return ret
;
1664 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1668 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1669 UINT n
, MEMBERID memid
)
1672 if(funcdescs
->funcdesc
.memid
== memid
)
1680 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1681 UINT n
, const OLECHAR
*name
)
1684 if(!lstrcmpiW(TLB_get_bstr(funcdescs
->Name
), name
))
1692 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1693 UINT n
, MEMBERID memid
)
1696 if(vardescs
->vardesc
.memid
== memid
)
1704 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1705 UINT n
, const OLECHAR
*name
)
1708 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1716 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1718 TLBCustData
*cust_data
;
1719 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1720 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1725 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1726 UINT n
, const OLECHAR
*name
)
1729 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1737 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1739 list_init(&var_desc
->custdata_list
);
1742 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1746 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1751 TLBVarDesc_Constructor(&ret
[n
-1]);
1758 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1762 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1767 list_init(&ret
[n
-1].custdata_list
);
1774 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1776 list_init(&func_desc
->custdata_list
);
1779 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1783 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1788 TLBFuncDesc_Constructor(&ret
[n
-1]);
1795 static void TLBImplType_Constructor(TLBImplType
*impl
)
1797 list_init(&impl
->custdata_list
);
1800 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1804 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1809 TLBImplType_Constructor(&ret
[n
-1]);
1816 static TLBGuid
*TLB_append_guid(struct list
*guid_list
, const GUID
*new_guid
)
1820 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1821 if (IsEqualGUID(&guid
->guid
, new_guid
))
1825 guid
= heap_alloc(sizeof(TLBGuid
));
1829 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1831 list_add_tail(guid_list
, &guid
->entry
);
1836 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1838 TLBCustData
*cust_data
;
1850 return DISP_E_BADVARTYPE
;
1853 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1856 cust_data
= heap_alloc(sizeof(TLBCustData
));
1858 return E_OUTOFMEMORY
;
1860 cust_data
->guid
= tlbguid
;
1861 VariantInit(&cust_data
->data
);
1863 list_add_tail(custdata_list
, &cust_data
->entry
);
1865 VariantClear(&cust_data
->data
);
1867 return VariantCopy(&cust_data
->data
, var
);
1870 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1874 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1875 if (strcmpW(str
->str
, new_str
) == 0)
1879 str
= heap_alloc(sizeof(TLBString
));
1883 str
->str
= SysAllocString(new_str
);
1889 list_add_tail(string_list
, &str
->entry
);
1894 /**********************************************************************
1896 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1898 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1903 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
1905 if (where
!= DO_NOT_SEEK
)
1907 where
+= pcx
->oStart
;
1908 if (where
> pcx
->length
)
1911 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
1919 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
1921 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1922 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1924 MSFT_Seek(pcx
, where
);
1925 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1926 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1931 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1936 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1937 FromLEDWords(buffer
, ret
);
1942 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1947 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1948 FromLEWords(buffer
, ret
);
1953 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
1956 MSFT_GuidEntry entry
;
1959 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
1961 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
1964 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
1966 guid
= heap_alloc(sizeof(TLBGuid
));
1968 guid
->offset
= offs
;
1969 guid
->guid
= entry
.guid
;
1971 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
1973 offs
+= sizeof(MSFT_GuidEntry
);
1977 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
1981 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
1982 if(ret
->offset
== offset
){
1983 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
1991 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1993 MSFT_NameIntro niName
;
1997 ERR_(typelib
)("bad offset %d\n", offset
);
2001 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2002 pcx
->pTblDir
->pNametab
.offset
+offset
);
2004 return niName
.hreftype
;
2007 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2010 MSFT_NameIntro intro
;
2012 int offs
= 0, lengthInChars
;
2014 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2018 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2021 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2022 intro
.namelen
&= 0xFF;
2023 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2025 len_piece
= (len_piece
+ 4) & ~0x3;
2029 string
= heap_alloc(len_piece
+ 1);
2030 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2031 string
[intro
.namelen
] = '\0';
2033 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2034 string
, -1, NULL
, 0);
2035 if (!lengthInChars
) {
2037 return E_UNEXPECTED
;
2040 tlbstr
= heap_alloc(sizeof(TLBString
));
2042 tlbstr
->offset
= offs
;
2043 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2044 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2048 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2054 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2058 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2059 if (tlbstr
->offset
== offset
) {
2060 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2068 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2072 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2073 if (tlbstr
->offset
== offset
) {
2074 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2083 * read a value and fill a VARIANT structure
2085 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2089 TRACE_(typelib
)("\n");
2091 if(offset
<0) { /* data are packed in here */
2092 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2093 V_I4(pVar
) = offset
& 0x3ffffff;
2096 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2097 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2098 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2099 switch (V_VT(pVar
)){
2100 case VT_EMPTY
: /* FIXME: is this right? */
2101 case VT_NULL
: /* FIXME: is this right? */
2102 case VT_I2
: /* this should not happen */
2113 case VT_VOID
: /* FIXME: is this right? */
2121 case VT_DECIMAL
: /* FIXME: is this right? */
2124 /* pointer types with known behaviour */
2127 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2130 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
2133 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
2135 nullPos
= MSFT_Tell(pcx
);
2136 size
= nullPos
- origPos
;
2137 MSFT_Seek(pcx
, origPos
);
2139 ptr
= heap_alloc_zero(size
);/* allocate temp buffer */
2140 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
2141 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2142 /* FIXME: do we need a AtoW conversion here? */
2143 V_UNION(pVar
, bstrVal
[size
])='\0';
2144 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2148 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2155 case VT_USERDEFINED
:
2161 case VT_STREAMED_OBJECT
:
2162 case VT_STORED_OBJECT
:
2163 case VT_BLOB_OBJECT
:
2168 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2172 if(size
>0) /* (big|small) endian correct? */
2173 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2177 * create a linked list with custom data
2179 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2185 TRACE_(typelib
)("\n");
2187 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2191 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2192 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2193 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2194 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2195 list_add_head(custdata_list
, &pNew
->entry
);
2196 offset
= entry
.next
;
2201 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
2205 pTd
->vt
=type
& VT_TYPEMASK
;
2207 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2209 if(pTd
->vt
== VT_USERDEFINED
)
2210 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
2212 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2215 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
2217 /* resolve referenced type if any */
2220 switch (lpTypeDesc
->vt
)
2223 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
2227 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
2230 case VT_USERDEFINED
:
2231 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
2232 lpTypeDesc
->u
.hreftype
);
2244 MSFT_DoFuncs(TLBContext
* pcx
,
2249 TLBFuncDesc
** pptfd
)
2252 * member information is stored in a data structure at offset
2253 * indicated by the memoffset field of the typeinfo structure
2254 * There are several distinctive parts.
2255 * The first part starts with a field that holds the total length
2256 * of this (first) part excluding this field. Then follow the records,
2257 * for each member there is one record.
2259 * The first entry is always the length of the record (including this
2261 * The rest of the record depends on the type of the member. If there is
2262 * a field indicating the member type (function, variable, interface, etc)
2263 * I have not found it yet. At this time we depend on the information
2264 * in the type info and the usual order how things are stored.
2266 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2269 * Third is an equal sized array with file offsets to the name entry
2272 * The fourth and last (?) part is an array with offsets to the records
2273 * in the first part of this file segment.
2276 int infolen
, nameoffset
, reclength
, i
;
2277 int recoffset
= offset
+ sizeof(INT
);
2279 char *recbuf
= heap_alloc(0xffff);
2280 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2281 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2283 TRACE_(typelib
)("\n");
2285 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2287 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2289 for ( i
= 0; i
< cFuncs
; i
++ )
2293 /* name, eventually add to a hash table */
2294 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2295 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2297 /* nameoffset is sometimes -1 on the second half of a propget/propput
2298 * pair of functions */
2299 if ((nameoffset
== -1) && (i
> 0))
2300 ptfd
->Name
= ptfd_prev
->Name
;
2302 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2304 /* read the function information record */
2305 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2307 reclength
&= 0xffff;
2309 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2311 /* size without argument data */
2312 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2314 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2315 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2317 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2318 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2320 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2322 if (pFuncRec
->FKCCIC
& 0x2000 )
2324 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2325 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2326 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2329 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2332 ptfd
->Entry
= (TLBString
*)-1;
2334 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2335 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2337 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2338 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2340 /* fill the FuncDesc Structure */
2341 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2342 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2344 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2345 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2346 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2347 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2348 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2349 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2350 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2354 &ptfd
->funcdesc
.elemdescFunc
.tdesc
,
2356 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2358 /* do the parameters/arguments */
2359 if(pFuncRec
->nrargs
)
2362 MSFT_ParameterInfo paraminfo
;
2364 ptfd
->funcdesc
.lprgelemdescParam
=
2365 heap_alloc_zero(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
2367 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2369 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2370 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2372 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2374 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2381 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2384 if (paraminfo
.oName
== -1)
2385 /* this occurs for [propput] or [propget] methods, so
2386 * we should just set the name of the parameter to the
2387 * name of the method. */
2388 ptfd
->pParamDesc
[j
].Name
= ptfd
->Name
;
2390 ptfd
->pParamDesc
[j
].Name
=
2391 MSFT_ReadName( pcx
, paraminfo
.oName
);
2392 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2394 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
2397 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2398 (pFuncRec
->FKCCIC
& 0x1000) )
2400 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2402 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2404 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2406 pParamDesc
->pparamdescex
= heap_alloc_zero(sizeof(PARAMDESCEX
));
2407 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2409 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2413 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2416 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2417 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2418 pFuncRec
->FKCCIC
& 0x80 )
2421 pFuncRec
->oArgCustData
[j
],
2422 &ptfd
->pParamDesc
[j
].custdata_list
);
2425 /* SEEK value = jump to offset,
2426 * from there jump to the end of record,
2427 * go back by (j-1) arguments
2429 MSFT_ReadLEDWords( ¶minfo
,
2430 sizeof(MSFT_ParameterInfo
), pcx
,
2431 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2432 * sizeof(MSFT_ParameterInfo
)));
2436 /* scode is not used: archaic win16 stuff FIXME: right? */
2437 ptfd
->funcdesc
.cScodes
= 0 ;
2438 ptfd
->funcdesc
.lprgscode
= NULL
;
2442 recoffset
+= reclength
;
2447 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2448 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2450 int infolen
, nameoffset
, reclength
;
2452 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2457 TRACE_(typelib
)("\n");
2459 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2460 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2461 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2462 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2463 recoffset
+= offset
+sizeof(INT
);
2464 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2465 /* name, eventually add to a hash table */
2466 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2467 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2468 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2469 /* read the variable information record */
2470 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2472 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2475 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2476 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2478 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2479 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2481 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2482 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2484 /* fill the VarDesc Structure */
2485 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2486 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2487 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2488 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2489 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2490 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2491 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2492 if(pVarRec
->VarKind
== VAR_CONST
){
2493 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2494 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2495 pVarRec
->OffsValue
, pcx
);
2497 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2498 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptvd
->vardesc
.elemdescVar
.tdesc
);
2499 recoffset
+= reclength
;
2503 /* fill in data for a hreftype (offset). When the referenced type is contained
2504 * in the typelib, it's just an (file) offset in the type info base dir.
2505 * If comes from import, it's an offset+1 in the ImpInfo table
2507 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2512 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2514 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2516 if(ref
->reference
== offset
) return;
2519 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2520 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2522 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2523 /* external typelib */
2524 MSFT_ImpInfo impinfo
;
2527 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2529 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2530 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2532 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2533 if(pImpLib
->offset
==impinfo
.oImpFile
)
2536 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2537 ref
->reference
= offset
& (~0x3);
2538 ref
->pImpTLInfo
= pImpLib
;
2539 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2540 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2541 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2542 ref
->index
= TLB_REF_USE_GUID
;
2544 ref
->index
= impinfo
.oGuid
;
2546 ERR("Cannot find a reference\n");
2547 ref
->reference
= -1;
2548 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2551 /* in this typelib */
2552 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2553 ref
->reference
= offset
;
2554 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2558 /* process Implemented Interfaces of a com class */
2559 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2563 MSFT_RefRecord refrec
;
2566 TRACE_(typelib
)("\n");
2568 pTI
->impltypes
= TLBImplType_Alloc(count
);
2569 pImpl
= pTI
->impltypes
;
2570 for(i
=0;i
<count
;i
++){
2571 if(offset
<0) break; /* paranoia */
2572 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2573 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2574 pImpl
->hRef
= refrec
.reftype
;
2575 pImpl
->implflags
=refrec
.flags
;
2576 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2577 offset
=refrec
.onext
;
2582 * process a typeinfo record
2584 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2587 ITypeLibImpl
* pLibInfo
)
2589 MSFT_TypeInfoBase tiBase
;
2590 ITypeInfoImpl
*ptiRet
;
2592 TRACE_(typelib
)("count=%u\n", count
);
2594 ptiRet
= ITypeInfoImpl_Constructor();
2595 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2596 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2598 /* this is where we are coming from */
2599 ptiRet
->pTypeLib
= pLibInfo
;
2600 ptiRet
->index
=count
;
2602 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2603 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2604 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2605 ptiRet
->cbSizeInstance
=tiBase
.size
;
2606 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2607 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2608 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2609 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2610 ptiRet
->wTypeFlags
=tiBase
.flags
;
2611 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2612 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2613 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2614 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2615 if(ptiRet
->typekind
== TKIND_ALIAS
)
2616 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2617 &ptiRet
->tdescAlias
, ptiRet
);
2620 /* IDLDESC idldescType; *//* never saw this one != zero */
2622 /* name, eventually add to a hash table */
2623 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2624 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2625 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2627 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2628 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2629 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2631 if (ptiRet
->typekind
== TKIND_MODULE
)
2632 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2634 /* note: InfoType's Help file and HelpStringDll come from the containing
2635 * library. Further HelpString and Docstring appear to be the same thing :(
2638 if(ptiRet
->cFuncs
>0 )
2639 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2641 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2643 if(ptiRet
->cVars
>0 )
2644 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2646 tiBase
.memoffset
, &ptiRet
->vardescs
);
2647 if(ptiRet
->cImplTypes
>0 ) {
2648 switch(ptiRet
->typekind
)
2651 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2654 case TKIND_DISPATCH
:
2655 /* This is not -1 when the interface is a non-base dual interface or
2656 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2657 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2661 if (tiBase
.datatype1
!= -1)
2663 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2664 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2665 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2669 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2670 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2671 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2675 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->custdata_list
);
2677 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2678 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2679 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2680 typekind_desc
[ptiRet
->typekind
]);
2681 if (TRACE_ON(typelib
))
2682 dump_TypeInfo(ptiRet
);
2687 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2690 INT16 len_str
, len_piece
;
2691 int offs
= 0, lengthInChars
;
2693 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2697 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2700 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2701 len_piece
= len_str
+ sizeof(INT16
);
2703 len_piece
= (len_piece
+ 4) & ~0x3;
2707 string
= heap_alloc(len_piece
+ 1);
2708 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2709 string
[len_str
] = '\0';
2711 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2712 string
, -1, NULL
, 0);
2713 if (!lengthInChars
) {
2715 return E_UNEXPECTED
;
2718 tlbstr
= heap_alloc(sizeof(TLBString
));
2720 tlbstr
->offset
= offs
;
2721 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2722 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2726 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2732 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2733 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2734 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2737 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2738 static CRITICAL_SECTION cache_section
;
2739 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2741 0, 0, &cache_section
,
2742 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2743 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2745 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2748 typedef struct TLB_PEFile
2750 IUnknown IUnknown_iface
;
2753 HRSRC typelib_resource
;
2754 HGLOBAL typelib_global
;
2755 LPVOID typelib_base
;
2758 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2760 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2763 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2765 if (IsEqualIID(riid
, &IID_IUnknown
))
2768 IUnknown_AddRef(iface
);
2772 return E_NOINTERFACE
;
2775 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2777 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2778 return InterlockedIncrement(&This
->refs
);
2781 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2783 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2784 ULONG refs
= InterlockedDecrement(&This
->refs
);
2787 if (This
->typelib_global
)
2788 FreeResource(This
->typelib_global
);
2790 FreeLibrary(This
->dll
);
2796 static const IUnknownVtbl TLB_PEFile_Vtable
=
2798 TLB_PEFile_QueryInterface
,
2803 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2806 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2808 This
= heap_alloc(sizeof(TLB_PEFile
));
2810 return E_OUTOFMEMORY
;
2812 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2815 This
->typelib_resource
= NULL
;
2816 This
->typelib_global
= NULL
;
2817 This
->typelib_base
= NULL
;
2819 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2820 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2824 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2825 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2826 if (This
->typelib_resource
)
2828 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2829 if (This
->typelib_global
)
2831 This
->typelib_base
= LockResource(This
->typelib_global
);
2833 if (This
->typelib_base
)
2835 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2836 *ppBase
= This
->typelib_base
;
2837 *ppFile
= &This
->IUnknown_iface
;
2843 TRACE("No TYPELIB resource found\n");
2847 TLB_PEFile_Release(&This
->IUnknown_iface
);
2851 typedef struct TLB_NEFile
2853 IUnknown IUnknown_iface
;
2855 LPVOID typelib_base
;
2858 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2860 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2863 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2865 if (IsEqualIID(riid
, &IID_IUnknown
))
2868 IUnknown_AddRef(iface
);
2872 return E_NOINTERFACE
;
2875 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2877 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2878 return InterlockedIncrement(&This
->refs
);
2881 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2883 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2884 ULONG refs
= InterlockedDecrement(&This
->refs
);
2887 heap_free(This
->typelib_base
);
2893 static const IUnknownVtbl TLB_NEFile_Vtable
=
2895 TLB_NEFile_QueryInterface
,
2900 /***********************************************************************
2901 * read_xx_header [internal]
2903 static int read_xx_header( HFILE lzfd
)
2905 IMAGE_DOS_HEADER mzh
;
2908 LZSeek( lzfd
, 0, SEEK_SET
);
2909 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2911 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2914 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2915 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2918 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2920 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2921 return IMAGE_OS2_SIGNATURE
;
2922 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2923 return IMAGE_NT_SIGNATURE
;
2926 WARN("Can't handle %s files.\n", magic
);
2931 /***********************************************************************
2932 * find_ne_resource [internal]
2934 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2935 DWORD
*resLen
, DWORD
*resOff
)
2937 IMAGE_OS2_HEADER nehd
;
2938 NE_TYPEINFO
*typeInfo
;
2939 NE_NAMEINFO
*nameInfo
;
2945 /* Read in NE header */
2946 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2947 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2949 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2952 TRACE("No resources in NE dll\n" );
2956 /* Read in resource table */
2957 resTab
= heap_alloc( resTabSize
);
2958 if ( !resTab
) return FALSE
;
2960 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2961 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2963 heap_free( resTab
);
2968 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2970 if (!IS_INTRESOURCE(typeid)) /* named type */
2972 BYTE len
= strlen( typeid );
2973 while (typeInfo
->type_id
)
2975 if (!(typeInfo
->type_id
& 0x8000))
2977 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2978 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2980 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2981 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2984 else /* numeric type id */
2986 WORD id
= LOWORD(typeid) | 0x8000;
2987 while (typeInfo
->type_id
)
2989 if (typeInfo
->type_id
== id
) goto found_type
;
2990 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2991 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2994 TRACE("No typeid entry found for %p\n", typeid );
2995 heap_free( resTab
);
2999 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3001 if (!IS_INTRESOURCE(resid
)) /* named resource */
3003 BYTE len
= strlen( resid
);
3004 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3006 BYTE
*p
= resTab
+ nameInfo
->id
;
3007 if (nameInfo
->id
& 0x8000) continue;
3008 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3011 else /* numeric resource id */
3013 WORD id
= LOWORD(resid
) | 0x8000;
3014 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3015 if (nameInfo
->id
== id
) goto found_name
;
3017 TRACE("No resid entry found for %p\n", typeid );
3018 heap_free( resTab
);
3022 /* Return resource data */
3023 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3024 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3026 heap_free( resTab
);
3030 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3034 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3037 This
= heap_alloc(sizeof(TLB_NEFile
));
3038 if (!This
) return E_OUTOFMEMORY
;
3040 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3042 This
->typelib_base
= NULL
;
3044 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3045 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3047 DWORD reslen
, offset
;
3048 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3050 This
->typelib_base
= heap_alloc(reslen
);
3051 if( !This
->typelib_base
)
3055 LZSeek( lzfd
, offset
, SEEK_SET
);
3056 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3058 *ppBase
= This
->typelib_base
;
3059 *pdwTLBLength
= reslen
;
3060 *ppFile
= &This
->IUnknown_iface
;
3066 if( lzfd
>= 0) LZClose( lzfd
);
3067 TLB_NEFile_Release(&This
->IUnknown_iface
);
3071 typedef struct TLB_Mapping
3073 IUnknown IUnknown_iface
;
3077 LPVOID typelib_base
;
3080 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3082 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3085 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3087 if (IsEqualIID(riid
, &IID_IUnknown
))
3090 IUnknown_AddRef(iface
);
3094 return E_NOINTERFACE
;
3097 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3099 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3100 return InterlockedIncrement(&This
->refs
);
3103 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3105 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3106 ULONG refs
= InterlockedDecrement(&This
->refs
);
3109 if (This
->typelib_base
)
3110 UnmapViewOfFile(This
->typelib_base
);
3112 CloseHandle(This
->mapping
);
3113 if (This
->file
!= INVALID_HANDLE_VALUE
)
3114 CloseHandle(This
->file
);
3120 static const IUnknownVtbl TLB_Mapping_Vtable
=
3122 TLB_Mapping_QueryInterface
,
3127 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3131 This
= heap_alloc(sizeof(TLB_Mapping
));
3133 return E_OUTOFMEMORY
;
3135 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3137 This
->file
= INVALID_HANDLE_VALUE
;
3138 This
->mapping
= NULL
;
3139 This
->typelib_base
= NULL
;
3141 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3142 if (INVALID_HANDLE_VALUE
!= This
->file
)
3144 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3147 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3148 if(This
->typelib_base
)
3150 /* retrieve file size */
3151 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3152 *ppBase
= This
->typelib_base
;
3153 *ppFile
= &This
->IUnknown_iface
;
3159 IUnknown_Release(&This
->IUnknown_iface
);
3160 return TYPE_E_CANTLOADLIBRARY
;
3163 /****************************************************************************
3166 * find the type of the typelib file and map the typelib resource into
3170 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3171 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3173 ITypeLibImpl
*entry
;
3176 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3177 LPVOID pBase
= NULL
;
3178 DWORD dwTLBLength
= 0;
3179 IUnknown
*pFile
= NULL
;
3183 index_str
= strrchrW(pszFileName
, '\\');
3184 if(index_str
&& *++index_str
!= '\0')
3187 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3188 if(*end_ptr
== '\0')
3190 int str_len
= index_str
- pszFileName
- 1;
3192 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3193 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3198 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3200 if(strchrW(file
, '\\'))
3202 lstrcpyW(pszPath
, file
);
3206 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3207 pszPath
[len
] = '\\';
3208 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3212 if(file
!= pszFileName
) heap_free(file
);
3214 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3216 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3217 EnterCriticalSection(&cache_section
);
3218 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3220 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3222 TRACE("cache hit\n");
3223 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3224 ITypeLib2_AddRef(*ppTypeLib
);
3225 LeaveCriticalSection(&cache_section
);
3229 LeaveCriticalSection(&cache_section
);
3231 /* now actually load and parse the typelib */
3233 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3234 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3235 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3236 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3237 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3240 if (dwTLBLength
>= 4)
3242 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3243 if (dwSignature
== MSFT_SIGNATURE
)
3244 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3245 else if (dwSignature
== SLTG_SIGNATURE
)
3246 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3249 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3250 ret
= TYPE_E_CANTLOADLIBRARY
;
3254 ret
= TYPE_E_CANTLOADLIBRARY
;
3255 IUnknown_Release(pFile
);
3259 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3261 TRACE("adding to cache\n");
3262 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3263 lstrcpyW(impl
->path
, pszPath
);
3264 /* We should really canonicalise the path here. */
3265 impl
->index
= index
;
3267 /* FIXME: check if it has added already in the meantime */
3268 EnterCriticalSection(&cache_section
);
3269 list_add_head(&tlb_cache
, &impl
->entry
);
3270 LeaveCriticalSection(&cache_section
);
3276 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3278 ret
= TYPE_E_CANTLOADLIBRARY
;
3285 /*================== ITypeLib(2) Methods ===================================*/
3287 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3289 ITypeLibImpl
* pTypeLibImpl
;
3291 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3292 if (!pTypeLibImpl
) return NULL
;
3294 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3295 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3296 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3297 pTypeLibImpl
->ref
= 1;
3299 list_init(&pTypeLibImpl
->implib_list
);
3300 list_init(&pTypeLibImpl
->custdata_list
);
3301 list_init(&pTypeLibImpl
->name_list
);
3302 list_init(&pTypeLibImpl
->string_list
);
3303 list_init(&pTypeLibImpl
->guid_list
);
3304 list_init(&pTypeLibImpl
->ref_list
);
3305 pTypeLibImpl
->dispatch_href
= -1;
3307 return pTypeLibImpl
;
3310 /****************************************************************************
3311 * ITypeLib2_Constructor_MSFT
3313 * loading an MSFT typelib from an in-memory image
3315 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3319 MSFT_Header tlbHeader
;
3320 MSFT_SegDir tlbSegDir
;
3321 ITypeLibImpl
* pTypeLibImpl
;
3323 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3325 pTypeLibImpl
= TypeLibImpl_Constructor();
3326 if (!pTypeLibImpl
) return NULL
;
3328 /* get pointer to beginning of typelib data */
3332 cx
.pLibInfo
= pTypeLibImpl
;
3333 cx
.length
= dwTLBLength
;
3336 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3337 TRACE_(typelib
)("header:\n");
3338 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3339 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3340 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3343 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3345 /* there is a small amount of information here until the next important
3347 * the segment directory . Try to calculate the amount of data */
3348 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3350 /* now read the segment directory */
3351 TRACE("read segment directory (at %d)\n",lPSegDir
);
3352 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3353 cx
.pTblDir
= &tlbSegDir
;
3355 /* just check two entries */
3356 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3358 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3359 heap_free(pTypeLibImpl
);
3363 MSFT_ReadAllNames(&cx
);
3364 MSFT_ReadAllStrings(&cx
);
3365 MSFT_ReadAllGuids(&cx
);
3367 /* now fill our internal data */
3368 /* TLIBATTR fields */
3369 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3371 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3372 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3373 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3374 pTypeLibImpl
->libflags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3376 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3377 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3379 /* name, eventually add to a hash table */
3380 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3383 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3384 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3386 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3389 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3390 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3393 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3396 if(tlbHeader
.CustomDataOffset
>= 0)
3398 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3401 /* fill in type descriptions */
3402 if(tlbSegDir
.pTypdescTab
.length
> 0)
3404 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3406 pTypeLibImpl
->ctTypeDesc
= cTD
;
3407 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3408 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3411 /* FIXME: add several sanity checks here */
3412 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3413 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3415 /* FIXME: check safearray */
3417 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3419 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3421 else if(td
[0] == VT_CARRAY
)
3423 /* array descr table here */
3424 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3426 else if(td
[0] == VT_USERDEFINED
)
3428 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3430 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3433 /* second time around to fill the array subscript info */
3436 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3437 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3439 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3440 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3443 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3445 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3447 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3449 for(j
= 0; j
<td
[2]; j
++)
3451 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3452 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3453 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3454 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3459 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3460 ERR("didn't find array description data\n");
3465 /* imported type libs */
3466 if(tlbSegDir
.pImpFiles
.offset
>0)
3469 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3472 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3476 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3477 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3478 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3480 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3481 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3482 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3483 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3486 name
= heap_alloc_zero(size
+1);
3487 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3488 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3491 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3492 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3494 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3498 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3499 if(pTypeLibImpl
->dispatch_href
!= -1)
3500 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3503 if(tlbHeader
.nrtypeinfos
>= 0 )
3505 ITypeInfoImpl
**ppTI
;
3508 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3510 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3512 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3515 (pTypeLibImpl
->TypeInfoCount
)++;
3519 TRACE("(%p)\n", pTypeLibImpl
);
3520 return &pTypeLibImpl
->ITypeLib2_iface
;
3524 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3530 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3531 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3535 guid
->Data4
[0] = s
>> 8;
3536 guid
->Data4
[1] = s
& 0xff;
3539 for(i
= 0; i
< 6; i
++) {
3540 memcpy(b
, str
+ 24 + 2 * i
, 2);
3541 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3546 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3553 bytelen
= *(const WORD
*)ptr
;
3554 if(bytelen
== 0xffff) return 2;
3556 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3557 tmp_str
= SysAllocStringLen(NULL
, len
);
3559 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3560 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3561 SysFreeString(tmp_str
);
3566 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3571 bytelen
= *(const WORD
*)ptr
;
3572 if(bytelen
== 0xffff) return 2;
3573 *str
= heap_alloc(bytelen
+ 1);
3574 memcpy(*str
, ptr
+ 2, bytelen
);
3575 (*str
)[bytelen
] = '\0';
3579 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3584 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3585 if (tlbstr
->offset
== offset
)
3589 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3590 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3591 SysFreeString(tmp_str
);
3596 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3598 char *ptr
= pLibBlk
;
3601 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3602 FIXME("libblk magic = %04x\n", w
);
3607 if((w
= *(WORD
*)ptr
) != 0xffff) {
3608 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3613 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3615 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3617 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3620 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3623 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3624 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3626 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3629 ptr
+= 4; /* skip res12 */
3631 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3634 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3637 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3640 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
);
3641 ptr
+= sizeof(GUID
);
3643 return ptr
- (char*)pLibBlk
;
3646 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3651 } sltg_ref_lookup_t
;
3653 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3654 HREFTYPE
*typelib_ref
)
3656 if(table
&& typeinfo_ref
< table
->num
)
3658 *typelib_ref
= table
->refs
[typeinfo_ref
];
3662 ERR_(typelib
)("Unable to find reference\n");
3667 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3672 if((*pType
& 0xe00) == 0xe00) {
3674 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3675 pTD
= pTD
->u
.lptdesc
;
3677 switch(*pType
& 0x3f) {
3680 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3681 pTD
= pTD
->u
.lptdesc
;
3684 case VT_USERDEFINED
:
3685 pTD
->vt
= VT_USERDEFINED
;
3686 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3692 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3695 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3697 pTD
->vt
= VT_CARRAY
;
3698 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3699 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3700 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3701 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3703 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3709 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3713 pTD
->vt
= VT_SAFEARRAY
;
3714 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3715 pTD
= pTD
->u
.lptdesc
;
3719 pTD
->vt
= *pType
& 0x3f;
3728 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3729 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3731 /* Handle [in/out] first */
3732 if((*pType
& 0xc000) == 0xc000)
3733 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3734 else if(*pType
& 0x8000)
3735 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3736 else if(*pType
& 0x4000)
3737 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3739 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3742 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3745 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3747 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3751 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3756 TLBRefType
*ref_type
;
3757 sltg_ref_lookup_t
*table
;
3758 HREFTYPE typelib_ref
;
3760 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3761 FIXME("Ref magic = %x\n", pRef
->magic
);
3764 name
= ( (char*)pRef
->names
+ pRef
->number
);
3766 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3767 table
->num
= pRef
->number
>> 3;
3769 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3771 /* We don't want the first href to be 0 */
3772 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3774 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3776 unsigned int lib_offs
, type_num
;
3778 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3780 name
+= SLTG_ReadStringA(name
, &refname
);
3781 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3782 FIXME_(typelib
)("Can't sscanf ref\n");
3783 if(lib_offs
!= 0xffff) {
3786 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3787 if(import
->offset
== lib_offs
)
3790 if(&import
->entry
== &pTL
->implib_list
) {
3791 char fname
[MAX_PATH
+1];
3795 import
= heap_alloc_zero(sizeof(*import
));
3796 import
->offset
= lib_offs
;
3797 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3798 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
);
3799 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3800 &import
->wVersionMajor
,
3801 &import
->wVersionMinor
,
3802 &import
->lcid
, fname
) != 4) {
3803 FIXME_(typelib
)("can't sscanf ref %s\n",
3804 pNameTable
+ lib_offs
+ 40);
3806 len
= strlen(fname
);
3807 if(fname
[len
-1] != '#')
3808 FIXME("fname = %s\n", fname
);
3809 fname
[len
-1] = '\0';
3810 import
->name
= TLB_MultiByteToBSTR(fname
);
3811 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3813 ref_type
->pImpTLInfo
= import
;
3815 /* Store a reference to IDispatch */
3816 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3817 pTL
->dispatch_href
= typelib_ref
;
3819 } else { /* internal ref */
3820 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3822 ref_type
->reference
= typelib_ref
;
3823 ref_type
->index
= type_num
;
3826 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3828 table
->refs
[ref
] = typelib_ref
;
3831 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3832 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3833 dump_TLBRefType(pTL
);
3837 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3838 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3840 SLTG_ImplInfo
*info
;
3841 TLBImplType
*pImplType
;
3842 /* I don't really get this structure, usually it's 0x16 bytes
3843 long, but iuser.tlb contains some that are 0x18 bytes long.
3844 That's ok because we can use the next ptr to jump to the next
3845 one. But how do we know the length of the last one? The WORD
3846 at offs 0x8 might be the clue. For now I'm just assuming that
3847 the last one is the regular 0x16 bytes. */
3849 info
= (SLTG_ImplInfo
*)pBlk
;
3852 if(info
->next
== 0xffff)
3854 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3857 info
= (SLTG_ImplInfo
*)pBlk
;
3858 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
3859 pImplType
= pTI
->impltypes
;
3861 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3862 pImplType
->implflags
= info
->impltypeflags
;
3865 if(info
->next
== 0xffff)
3868 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3869 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3871 info
++; /* see comment at top of function */
3875 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3876 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3878 TLBVarDesc
*pVarDesc
;
3879 const TLBString
*prevName
= NULL
;
3880 SLTG_Variable
*pItem
;
3884 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
3886 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3887 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3889 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3891 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3892 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3893 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3897 if (pItem
->name
== 0xfffe)
3898 pVarDesc
->Name
= prevName
;
3900 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
3902 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
3903 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3904 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3906 if(pItem
->flags
& 0x02)
3907 pType
= &pItem
->type
;
3909 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3911 if (pItem
->flags
& ~0xda)
3912 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3914 SLTG_DoElem(pType
, pBlk
,
3915 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3917 if (TRACE_ON(typelib
)) {
3919 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3920 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3923 if (pItem
->flags
& 0x40) {
3924 TRACE_(typelib
)("VAR_DISPATCH\n");
3925 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3927 else if (pItem
->flags
& 0x10) {
3928 TRACE_(typelib
)("VAR_CONST\n");
3929 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3930 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3931 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3932 if (pItem
->flags
& 0x08)
3933 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3935 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3941 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3943 TRACE_(typelib
)("len = %u\n", len
);
3944 if (len
== 0xffff) {
3947 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3948 str
= SysAllocStringLen(NULL
, alloc_len
);
3949 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3951 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3952 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3961 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3962 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3965 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3970 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3971 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3972 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3975 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3976 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3978 if (pItem
->flags
& 0x80)
3979 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3981 prevName
= pVarDesc
->Name
;
3986 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3987 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3989 SLTG_Function
*pFunc
;
3991 TLBFuncDesc
*pFuncDesc
;
3993 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
3995 pFuncDesc
= pTI
->funcdescs
;
3996 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
3997 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4002 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4003 case SLTG_FUNCTION_MAGIC
:
4004 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4006 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4007 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4009 case SLTG_STATIC_FUNCTION_MAGIC
:
4010 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4013 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4016 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4018 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4019 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4020 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4021 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4022 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4023 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4025 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4026 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4028 if(pFunc
->retnextopt
& 0x80)
4029 pType
= &pFunc
->rettype
;
4031 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4033 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4035 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4036 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4037 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4039 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4041 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4042 char *paramName
= pNameTable
+ *pArg
;
4044 /* If arg type follows then paramName points to the 2nd
4045 letter of the name, else the next WORD is an offset to
4046 the arg type and paramName points to the first letter.
4047 So let's take one char off paramName and see if we're
4048 pointing at an alpha-numeric char. However if *pArg is
4049 0xffff or 0xfffe then the param has no name, the former
4050 meaning that the next WORD is the type, the latter
4051 meaning that the next WORD is an offset to the type. */
4056 else if(*pArg
== 0xfffe) {
4060 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4065 if(HaveOffs
) { /* the next word is an offset to type */
4066 pType
= (WORD
*)(pBlk
+ *pArg
);
4067 SLTG_DoElem(pType
, pBlk
,
4068 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4073 pArg
= SLTG_DoElem(pArg
, pBlk
,
4074 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4077 /* Are we an optional param ? */
4078 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4079 pFuncDesc
->funcdesc
.cParamsOpt
)
4080 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4083 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4084 paramName
- pNameTable
, pTI
->pTypeLib
);
4086 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4090 pTI
->cFuncs
= cFuncs
;
4093 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4094 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4095 SLTG_TypeInfoTail
*pTITail
)
4098 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4100 if(pTIHeader
->href_table
!= 0xffffffff) {
4101 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4107 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4108 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4110 heap_free(ref_lookup
);
4114 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4115 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4116 const SLTG_TypeInfoTail
*pTITail
)
4119 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4121 if(pTIHeader
->href_table
!= 0xffffffff) {
4122 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4128 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4129 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4132 if (pTITail
->funcs_off
!= 0xffff)
4133 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4135 heap_free(ref_lookup
);
4137 if (TRACE_ON(typelib
))
4138 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4141 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4142 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4143 const SLTG_TypeInfoTail
*pTITail
)
4145 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4148 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4149 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4150 const SLTG_TypeInfoTail
*pTITail
)
4153 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4155 if (pTITail
->simple_alias
) {
4156 /* if simple alias, no more processing required */
4157 pTI
->tdescAlias
.vt
= pTITail
->tdescalias_vt
;
4161 if(pTIHeader
->href_table
!= 0xffffffff) {
4162 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4166 /* otherwise it is an offset to a type */
4167 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4169 SLTG_DoType(pType
, pBlk
, &pTI
->tdescAlias
, ref_lookup
);
4171 heap_free(ref_lookup
);
4174 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4175 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4176 const SLTG_TypeInfoTail
*pTITail
)
4178 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4179 if (pTIHeader
->href_table
!= 0xffffffff)
4180 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4183 if (pTITail
->vars_off
!= 0xffff)
4184 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4186 if (pTITail
->funcs_off
!= 0xffff)
4187 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4189 if (pTITail
->impls_off
!= 0xffff)
4190 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4192 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4193 * of dispinterface functions including the IDispatch ones, so
4194 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4195 pTI
->cbSizeVft
= pTI
->cFuncs
* sizeof(void *);
4197 heap_free(ref_lookup
);
4198 if (TRACE_ON(typelib
))
4199 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4202 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4203 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4204 const SLTG_TypeInfoTail
*pTITail
)
4206 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4209 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4210 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4211 const SLTG_TypeInfoTail
*pTITail
)
4213 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4214 if (pTIHeader
->href_table
!= 0xffffffff)
4215 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4218 if (pTITail
->vars_off
!= 0xffff)
4219 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4221 if (pTITail
->funcs_off
!= 0xffff)
4222 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4223 heap_free(ref_lookup
);
4224 if (TRACE_ON(typelib
))
4228 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4229 manageable copy of it into this */
4242 } SLTG_InternalOtherTypeInfo
;
4244 /****************************************************************************
4245 * ITypeLib2_Constructor_SLTG
4247 * loading a SLTG typelib from an in-memory image
4249 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4251 ITypeLibImpl
*pTypeLibImpl
;
4252 SLTG_Header
*pHeader
;
4253 SLTG_BlkEntry
*pBlkEntry
;
4257 LPVOID pBlk
, pFirstBlk
;
4258 SLTG_LibBlk
*pLibBlk
;
4259 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4260 char *pAfterOTIBlks
= NULL
;
4261 char *pNameTable
, *ptr
;
4264 ITypeInfoImpl
**ppTypeInfoImpl
;
4266 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4269 pTypeLibImpl
= TypeLibImpl_Constructor();
4270 if (!pTypeLibImpl
) return NULL
;
4274 TRACE_(typelib
)("header:\n");
4275 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4276 pHeader
->nrOfFileBlks
);
4277 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4278 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4279 pHeader
->SLTG_magic
);
4283 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4284 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4286 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4287 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4289 /* Next we have a magic block */
4290 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4292 /* Let's see if we're still in sync */
4293 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4294 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4295 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4298 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4299 sizeof(SLTG_DIR_MAGIC
))) {
4300 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4304 pIndex
= (SLTG_Index
*)(pMagic
+1);
4306 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4308 pFirstBlk
= pPad9
+ 1;
4310 /* We'll set up a ptr to the main library block, which is the last one. */
4312 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4313 pBlkEntry
[order
].next
!= 0;
4314 order
= pBlkEntry
[order
].next
- 1, i
++) {
4315 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4319 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4321 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4326 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4328 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4331 ptr
= (char*)pLibBlk
+ len
;
4333 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4337 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4339 w
= *(WORD
*)(ptr
+ 2);
4342 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4343 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4344 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4346 w
= *(WORD
*)(ptr
+ 4 + len
);
4348 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4350 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4351 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4352 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4354 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4355 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4356 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4358 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4359 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4362 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4363 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4364 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4365 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4366 len
+= sizeof(SLTG_OtherTypeInfo
);
4370 pAfterOTIBlks
= ptr
;
4372 /* Skip this WORD and get the next DWORD */
4373 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4375 /* Now add this to pLibBLk look at what we're pointing at and
4376 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4377 dust and we should be pointing at the beginning of the name
4380 pNameTable
= (char*)pLibBlk
+ len
;
4382 switch(*(WORD
*)pNameTable
) {
4389 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4393 pNameTable
+= 0x216;
4397 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4399 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4402 /* Hopefully we now have enough ptrs set up to actually read in
4403 some TypeInfos. It's not clear which order to do them in, so
4404 I'll just follow the links along the BlkEntry chain and read
4405 them in the order in which they are in the file */
4407 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4408 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4410 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4411 pBlkEntry
[order
].next
!= 0;
4412 order
= pBlkEntry
[order
].next
- 1, i
++) {
4414 SLTG_TypeInfoHeader
*pTIHeader
;
4415 SLTG_TypeInfoTail
*pTITail
;
4416 SLTG_MemberHeader
*pMemHeader
;
4418 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4419 FIXME_(typelib
)("Index strings don't match\n");
4420 heap_free(pOtherTypeInfoBlks
);
4425 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4426 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4427 heap_free(pOtherTypeInfoBlks
);
4430 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4431 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4432 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4434 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4435 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4436 (*ppTypeInfoImpl
)->index
= i
;
4437 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4438 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4439 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
);
4440 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4441 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4442 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4443 (*ppTypeInfoImpl
)->wTypeFlags
=
4444 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4446 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4447 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4449 if((pTIHeader
->typeflags1
& 7) != 2)
4450 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4451 if(pTIHeader
->typeflags3
!= 2)
4452 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4454 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4455 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4456 typekind_desc
[pTIHeader
->typekind
],
4457 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4458 (*ppTypeInfoImpl
)->wTypeFlags
);
4460 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4462 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4464 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4465 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4466 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4468 switch(pTIHeader
->typekind
) {
4470 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4471 pTIHeader
, pTITail
);
4475 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4476 pTIHeader
, pTITail
);
4479 case TKIND_INTERFACE
:
4480 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4481 pTIHeader
, pTITail
);
4485 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4486 pTIHeader
, pTITail
);
4490 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4491 pTIHeader
, pTITail
);
4494 case TKIND_DISPATCH
:
4495 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4496 pTIHeader
, pTITail
);
4500 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4501 pTIHeader
, pTITail
);
4505 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4510 /* could get cFuncs, cVars and cImplTypes from here
4511 but we've already set those */
4512 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4528 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4531 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4532 FIXME("Somehow processed %d TypeInfos\n", i
);
4533 heap_free(pOtherTypeInfoBlks
);
4537 heap_free(pOtherTypeInfoBlks
);
4538 return &pTypeLibImpl
->ITypeLib2_iface
;
4541 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4543 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4545 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4547 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4548 IsEqualIID(riid
,&IID_ITypeLib
)||
4549 IsEqualIID(riid
,&IID_ITypeLib2
))
4551 *ppv
= &This
->ITypeLib2_iface
;
4553 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4554 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4556 *ppv
= &This
->ICreateTypeLib2_iface
;
4561 TRACE("-- Interface: E_NOINTERFACE\n");
4562 return E_NOINTERFACE
;
4565 IUnknown_AddRef((IUnknown
*)*ppv
);
4569 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4571 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4572 ULONG ref
= InterlockedIncrement(&This
->ref
);
4574 TRACE("(%p) ref=%u\n", This
, ref
);
4579 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4581 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4582 ULONG ref
= InterlockedDecrement(&This
->ref
);
4584 TRACE("(%p) ref=%u\n",This
, ref
);
4588 TLBImpLib
*pImpLib
, *pImpLibNext
;
4589 TLBRefType
*ref_type
;
4590 TLBString
*tlbstr
, *tlbstr_next
;
4594 /* remove cache entry */
4597 TRACE("removing from cache list\n");
4598 EnterCriticalSection(&cache_section
);
4599 if(This
->entry
.next
)
4600 list_remove(&This
->entry
);
4601 LeaveCriticalSection(&cache_section
);
4602 heap_free(This
->path
);
4604 TRACE(" destroying ITypeLib(%p)\n",This
);
4606 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4607 list_remove(&tlbstr
->entry
);
4611 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4612 list_remove(&tlbstr
->entry
);
4616 TLB_FreeCustData(&This
->custdata_list
);
4618 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4619 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4620 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4622 heap_free(This
->pTypeDesc
);
4624 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4626 if (pImpLib
->pImpTypeLib
)
4627 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4628 SysFreeString(pImpLib
->name
);
4630 list_remove(&pImpLib
->entry
);
4634 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4636 list_remove(&ref_type
->entry
);
4637 heap_free(ref_type
);
4640 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4641 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4642 heap_free(This
->typeinfos
);
4650 /* ITypeLib::GetTypeInfoCount
4652 * Returns the number of type descriptions in the type library
4654 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4656 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4657 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4658 return This
->TypeInfoCount
;
4661 /* ITypeLib::GetTypeInfo
4663 * retrieves the specified type description in the library.
4665 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4668 ITypeInfo
**ppTInfo
)
4670 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4672 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4675 return E_INVALIDARG
;
4677 if(index
>= This
->TypeInfoCount
)
4678 return TYPE_E_ELEMENTNOTFOUND
;
4680 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[index
];
4681 ITypeInfo_AddRef(*ppTInfo
);
4687 /* ITypeLibs::GetTypeInfoType
4689 * Retrieves the type of a type description.
4691 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4696 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4698 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4701 return E_INVALIDARG
;
4703 if(index
>= This
->TypeInfoCount
)
4704 return TYPE_E_ELEMENTNOTFOUND
;
4706 *pTKind
= This
->typeinfos
[index
]->typekind
;
4711 /* ITypeLib::GetTypeInfoOfGuid
4713 * Retrieves the type description that corresponds to the specified GUID.
4716 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4719 ITypeInfo
**ppTInfo
)
4721 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4724 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4726 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4727 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4728 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[i
];
4729 ITypeInfo_AddRef(*ppTInfo
);
4734 return TYPE_E_ELEMENTNOTFOUND
;
4737 /* ITypeLib::GetLibAttr
4739 * Retrieves the structure that contains the library's attributes.
4742 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4746 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4748 TRACE("(%p, %p)\n", This
, attr
);
4750 if (!attr
) return E_INVALIDARG
;
4752 *attr
= heap_alloc(sizeof(**attr
));
4753 if (!*attr
) return E_OUTOFMEMORY
;
4755 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4756 (*attr
)->lcid
= This
->set_lcid
;
4757 (*attr
)->syskind
= This
->syskind
;
4758 (*attr
)->wMajorVerNum
= This
->ver_major
;
4759 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4760 (*attr
)->wLibFlags
= This
->libflags
;
4765 /* ITypeLib::GetTypeComp
4767 * Enables a client compiler to bind to a library's types, variables,
4768 * constants, and global functions.
4771 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4773 ITypeComp
**ppTComp
)
4775 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4777 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4778 *ppTComp
= &This
->ITypeComp_iface
;
4779 ITypeComp_AddRef(*ppTComp
);
4784 /* ITypeLib::GetDocumentation
4786 * Retrieves the library's documentation string, the complete Help file name
4787 * and path, and the context identifier for the library Help topic in the Help
4790 * On a successful return all non-null BSTR pointers will have been set,
4793 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4797 BSTR
*pBstrDocString
,
4798 DWORD
*pdwHelpContext
,
4799 BSTR
*pBstrHelpFile
)
4801 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4802 HRESULT result
= E_INVALIDARG
;
4805 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4807 pBstrName
, pBstrDocString
,
4808 pdwHelpContext
, pBstrHelpFile
);
4812 /* documentation for the typelib */
4817 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4825 if (This
->DocString
)
4827 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4830 else if (This
->Name
)
4832 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->Name
))))
4836 *pBstrDocString
= NULL
;
4840 *pdwHelpContext
= This
->dwHelpContext
;
4846 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4850 *pBstrHelpFile
= NULL
;
4857 /* for a typeinfo */
4858 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4860 if(SUCCEEDED(result
))
4862 result
= ITypeInfo_GetDocumentation(pTInfo
,
4866 pdwHelpContext
, pBstrHelpFile
);
4868 ITypeInfo_Release(pTInfo
);
4873 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4875 if (pBstrName
) SysFreeString (*pBstrName
);
4877 return STG_E_INSUFFICIENTMEMORY
;
4882 * Indicates whether a passed-in string contains the name of a type or member
4883 * described in the library.
4886 static HRESULT WINAPI
ITypeLib2_fnIsName(
4892 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4894 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
4896 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4900 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4901 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4902 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4903 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
4904 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4906 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4907 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
4908 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4909 goto ITypeLib2_fnIsName_exit
;
4912 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
4913 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4914 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4920 ITypeLib2_fnIsName_exit
:
4921 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4922 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4927 /* ITypeLib::FindName
4929 * Finds occurrences of a type description in a type library. This may be used
4930 * to quickly verify that a name exists in a type library.
4933 static HRESULT WINAPI
ITypeLib2_fnFindName(
4937 ITypeInfo
**ppTInfo
,
4941 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4946 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
4948 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
4949 return E_INVALIDARG
;
4951 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
4952 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
4953 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4957 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4958 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
4959 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
4962 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4963 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
4964 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
4965 goto ITypeLib2_fnFindName_exit
;
4969 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
4971 goto ITypeLib2_fnFindName_exit
;
4974 ITypeLib2_fnFindName_exit
:
4975 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4976 ppTInfo
[count
]=(LPTYPEINFO
)pTInfo
;
4979 TRACE("found %d typeinfos\n", count
);
4986 /* ITypeLib::ReleaseTLibAttr
4988 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4991 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4993 TLIBATTR
*pTLibAttr
)
4995 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4996 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
4997 heap_free(pTLibAttr
);
5000 /* ITypeLib2::GetCustData
5002 * gets the custom data
5004 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5009 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5010 TLBCustData
*pCData
;
5012 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5014 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5016 return TYPE_E_ELEMENTNOTFOUND
;
5018 VariantInit(pVarVal
);
5019 VariantCopy(pVarVal
, &pCData
->data
);
5024 /* ITypeLib2::GetLibStatistics
5026 * Returns statistics about a type library that are required for efficient
5027 * sizing of hash tables.
5030 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5032 ULONG
*pcUniqueNames
,
5033 ULONG
*pcchUniqueNames
)
5035 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5037 FIXME("(%p): stub!\n", This
);
5039 if(pcUniqueNames
) *pcUniqueNames
=1;
5040 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5044 /* ITypeLib2::GetDocumentation2
5046 * Retrieves the library's documentation string, the complete Help file name
5047 * and path, the localization context to use, and the context ID for the
5048 * library Help topic in the Help file.
5051 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5055 BSTR
*pbstrHelpString
,
5056 DWORD
*pdwHelpStringContext
,
5057 BSTR
*pbstrHelpStringDll
)
5059 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5063 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5065 /* the help string should be obtained from the helpstringdll,
5066 * using the _DLLGetDocumentation function, based on the supplied
5067 * lcid. Nice to do sometime...
5071 /* documentation for the typelib */
5073 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5074 if(pdwHelpStringContext
)
5075 *pdwHelpStringContext
=This
->dwHelpContext
;
5076 if(pbstrHelpStringDll
)
5077 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5083 /* for a typeinfo */
5084 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5086 if(SUCCEEDED(result
))
5088 ITypeInfo2
* pTInfo2
;
5089 result
= ITypeInfo_QueryInterface(pTInfo
,
5091 (LPVOID
*) &pTInfo2
);
5093 if(SUCCEEDED(result
))
5095 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5099 pdwHelpStringContext
,
5100 pbstrHelpStringDll
);
5102 ITypeInfo2_Release(pTInfo2
);
5105 ITypeInfo_Release(pTInfo
);
5111 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5113 TLBCustData
*pCData
;
5117 ct
= list_count(custdata_list
);
5119 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5120 if(!pCustData
->prgCustData
)
5121 return E_OUTOFMEMORY
;
5123 pCustData
->cCustData
= ct
;
5125 cdi
= pCustData
->prgCustData
;
5126 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5127 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5128 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5136 /* ITypeLib2::GetAllCustData
5138 * Gets all custom data items for the library.
5141 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5143 CUSTDATA
*pCustData
)
5145 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5146 TRACE("(%p)->(%p)\n", This
, pCustData
);
5147 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5150 static const ITypeLib2Vtbl tlbvt
= {
5151 ITypeLib2_fnQueryInterface
,
5153 ITypeLib2_fnRelease
,
5154 ITypeLib2_fnGetTypeInfoCount
,
5155 ITypeLib2_fnGetTypeInfo
,
5156 ITypeLib2_fnGetTypeInfoType
,
5157 ITypeLib2_fnGetTypeInfoOfGuid
,
5158 ITypeLib2_fnGetLibAttr
,
5159 ITypeLib2_fnGetTypeComp
,
5160 ITypeLib2_fnGetDocumentation
,
5162 ITypeLib2_fnFindName
,
5163 ITypeLib2_fnReleaseTLibAttr
,
5165 ITypeLib2_fnGetCustData
,
5166 ITypeLib2_fnGetLibStatistics
,
5167 ITypeLib2_fnGetDocumentation2
,
5168 ITypeLib2_fnGetAllCustData
5172 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5174 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5176 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5179 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5181 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5183 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5186 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5188 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5190 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5193 static HRESULT WINAPI
ITypeLibComp_fnBind(
5198 ITypeInfo
** ppTInfo
,
5199 DESCKIND
* pDescKind
,
5202 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5203 int typemismatch
=0, i
;
5205 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5207 *pDescKind
= DESCKIND_NONE
;
5208 pBindPtr
->lptcomp
= NULL
;
5211 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5212 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5213 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5215 /* FIXME: check wFlags here? */
5216 /* FIXME: we should use a hash table to look this info up using lHash
5217 * instead of an O(n) search */
5218 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5219 (pTypeInfo
->typekind
== TKIND_MODULE
))
5221 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5223 *pDescKind
= DESCKIND_TYPECOMP
;
5224 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5225 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5226 TRACE("module or enum: %s\n", debugstr_w(szName
));
5231 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5232 (pTypeInfo
->typekind
== TKIND_ENUM
))
5234 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5237 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5238 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5240 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5243 else if (hr
== TYPE_E_TYPEMISMATCH
)
5247 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5248 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5250 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5252 ITypeInfo
*subtypeinfo
;
5254 DESCKIND subdesckind
;
5256 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5257 &subtypeinfo
, &subdesckind
, &subbindptr
);
5258 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5260 TYPEDESC tdesc_appobject
;
5261 const VARDESC vardesc_appobject
=
5264 NULL
, /* lpstrSchema */
5279 VAR_STATIC
/* varkind */
5282 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5283 tdesc_appobject
.vt
= VT_USERDEFINED
;
5285 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5287 /* cleanup things filled in by Bind call so we can put our
5288 * application object data in there instead */
5289 switch (subdesckind
)
5291 case DESCKIND_FUNCDESC
:
5292 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5294 case DESCKIND_VARDESC
:
5295 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5300 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5302 if (pTypeInfo
->hreftype
== -1)
5303 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5305 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5309 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5310 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
5311 ITypeInfo_AddRef(*ppTInfo
);
5314 else if (hr
== TYPE_E_TYPEMISMATCH
)
5321 TRACE("type mismatch %s\n", debugstr_w(szName
));
5322 return TYPE_E_TYPEMISMATCH
;
5326 TRACE("name not found %s\n", debugstr_w(szName
));
5331 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5335 ITypeInfo
** ppTInfo
,
5336 ITypeComp
** ppTComp
)
5338 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5339 ITypeInfoImpl
*info
;
5341 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5343 if(!szName
|| !ppTInfo
|| !ppTComp
)
5344 return E_INVALIDARG
;
5346 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5353 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5354 ITypeInfo_AddRef(*ppTInfo
);
5355 *ppTComp
= &info
->ITypeComp_iface
;
5356 ITypeComp_AddRef(*ppTComp
);
5361 static const ITypeCompVtbl tlbtcvt
=
5364 ITypeLibComp_fnQueryInterface
,
5365 ITypeLibComp_fnAddRef
,
5366 ITypeLibComp_fnRelease
,
5368 ITypeLibComp_fnBind
,
5369 ITypeLibComp_fnBindType
5372 /*================== ITypeInfo(2) Methods ===================================*/
5373 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5375 ITypeInfoImpl
*pTypeInfoImpl
;
5377 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5380 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5381 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5382 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5383 pTypeInfoImpl
->ref
= 0;
5384 pTypeInfoImpl
->hreftype
= -1;
5385 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5386 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5387 list_init(&pTypeInfoImpl
->custdata_list
);
5389 TRACE("(%p)\n", pTypeInfoImpl
);
5390 return pTypeInfoImpl
;
5393 /* ITypeInfo::QueryInterface
5395 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5400 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5402 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5405 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5406 IsEqualIID(riid
,&IID_ITypeInfo
)||
5407 IsEqualIID(riid
,&IID_ITypeInfo2
))
5409 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5410 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5411 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5414 ITypeInfo2_AddRef(iface
);
5415 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5418 TRACE("-- Interface: E_NOINTERFACE\n");
5419 return E_NOINTERFACE
;
5422 /* ITypeInfo::AddRef
5424 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5426 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5427 ULONG ref
= InterlockedIncrement(&This
->ref
);
5429 TRACE("(%p)->ref is %u\n",This
, ref
);
5431 if (ref
== 1 /* incremented from 0 */)
5432 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5437 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5441 TRACE("destroying ITypeInfo(%p)\n",This
);
5443 for (i
= 0; i
< This
->cFuncs
; ++i
)
5446 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5447 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5449 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5450 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5452 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5453 heap_free(elemdesc
->u
.paramdesc
.pparamdescex
);
5455 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5457 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5458 heap_free(pFInfo
->pParamDesc
);
5459 TLB_FreeCustData(&pFInfo
->custdata_list
);
5461 heap_free(This
->funcdescs
);
5463 for(i
= 0; i
< This
->cVars
; ++i
)
5465 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5466 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5468 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5469 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5471 TLB_FreeCustData(&pVInfo
->custdata_list
);
5473 heap_free(This
->vardescs
);
5475 if(This
->impltypes
){
5476 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5477 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5478 TLB_FreeCustData(&pImpl
->custdata_list
);
5480 heap_free(This
->impltypes
);
5483 TLB_FreeCustData(&This
->custdata_list
);
5488 /* ITypeInfo::Release
5490 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5492 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5493 ULONG ref
= InterlockedDecrement(&This
->ref
);
5495 TRACE("(%p)->(%u)\n",This
, ref
);
5499 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5500 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5501 if (not_attached_to_typelib
)
5503 /* otherwise This will be freed when typelib is freed */
5509 /* ITypeInfo::GetTypeAttr
5511 * Retrieves a TYPEATTR structure that contains the attributes of the type
5515 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5516 LPTYPEATTR
*ppTypeAttr
)
5518 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5521 TRACE("(%p)\n",This
);
5523 size
= sizeof(**ppTypeAttr
);
5524 if (This
->typekind
== TKIND_ALIAS
)
5525 size
+= TLB_SizeTypeDesc(&This
->tdescAlias
, FALSE
);
5527 *ppTypeAttr
= heap_alloc(size
);
5529 return E_OUTOFMEMORY
;
5531 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5532 (*ppTypeAttr
)->lcid
= This
->lcid
;
5533 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5534 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5535 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5536 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5537 (*ppTypeAttr
)->typekind
= This
->typekind
;
5538 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5539 (*ppTypeAttr
)->cVars
= This
->cVars
;
5540 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5541 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5542 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5543 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5544 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5545 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5546 (*ppTypeAttr
)->tdescAlias
= This
->tdescAlias
;
5547 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5549 if (This
->typekind
== TKIND_ALIAS
)
5550 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5551 &This
->tdescAlias
, *ppTypeAttr
+ 1);
5553 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5554 /* This should include all the inherited funcs */
5555 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5556 /* This is always the size of IDispatch's vtbl */
5557 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5558 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5563 /* ITypeInfo::GetTypeComp
5565 * Retrieves the ITypeComp interface for the type description, which enables a
5566 * client compiler to bind to the type description's members.
5569 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5570 ITypeComp
* *ppTComp
)
5572 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5574 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5576 *ppTComp
= &This
->ITypeComp_iface
;
5577 ITypeComp_AddRef(*ppTComp
);
5581 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5583 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5584 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5585 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5589 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5592 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5593 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5595 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5596 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5597 *buffer
+= sizeof(PARAMDESCEX
);
5598 *pparamdescex_dest
= *pparamdescex_src
;
5599 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5600 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5601 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5602 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5605 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5609 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5611 UINT len
= SysStringLen(str
), i
;
5612 for (i
= 0; i
< len
; ++i
)
5618 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5620 if (V_VT(var
) == VT_INT
)
5621 return VariantChangeType(var
, var
, 0, VT_I4
);
5622 else if (V_VT(var
) == VT_UINT
)
5623 return VariantChangeType(var
, var
, 0, VT_UI4
);
5624 else if (V_VT(var
) == VT_BSTR
)
5625 return TLB_SanitizeBSTR(V_BSTR(var
));
5630 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5632 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5633 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5636 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5640 SIZE_T size
= sizeof(*src
);
5644 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5645 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5646 for (i
= 0; i
< src
->cParams
; i
++)
5648 size
+= sizeof(ELEMDESC
);
5649 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5652 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5653 if (!dest
) return E_OUTOFMEMORY
;
5656 if (dispinterface
) /* overwrite funckind */
5657 dest
->funckind
= FUNC_DISPATCH
;
5658 buffer
= (char *)(dest
+ 1);
5660 dest
->oVft
= dest
->oVft
& 0xFFFC;
5662 if (dest
->cScodes
) {
5663 dest
->lprgscode
= (SCODE
*)buffer
;
5664 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5665 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5667 dest
->lprgscode
= NULL
;
5669 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5672 SysFreeString((BSTR
)dest
);
5676 if (dest
->cParams
) {
5677 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5678 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5679 for (i
= 0; i
< src
->cParams
; i
++)
5681 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5687 /* undo the above actions */
5688 for (i
= i
- 1; i
>= 0; i
--)
5689 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5690 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5691 SysFreeString((BSTR
)dest
);
5695 dest
->lprgelemdescParam
= NULL
;
5697 /* special treatment for dispinterfaces: this makes functions appear
5698 * to return their [retval] value when it is really returning an
5700 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5702 if (dest
->cParams
&&
5703 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5705 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5706 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5708 ERR("elemdesc should have started with VT_PTR instead of:\n");
5710 dump_ELEMDESC(elemdesc
);
5711 return E_UNEXPECTED
;
5714 /* copy last parameter to the return value. we are using a flat
5715 * buffer so there is no danger of leaking memory in
5717 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5719 /* remove the last parameter */
5723 /* otherwise this function is made to appear to have no return
5725 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5733 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5735 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5737 if (index
>= This
->cFuncs
)
5738 return TYPE_E_ELEMENTNOTFOUND
;
5740 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5744 /* internal function to make the inherited interfaces' methods appear
5745 * part of the interface */
5746 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5747 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5749 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5751 UINT implemented_funcs
= 0;
5756 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5760 ITypeInfo
*pSubTypeInfo
;
5763 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5767 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5770 &sub_funcs
, hrefoffset
);
5771 implemented_funcs
+= sub_funcs
;
5772 ITypeInfo_Release(pSubTypeInfo
);
5775 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5779 *funcs
= implemented_funcs
+ This
->cFuncs
;
5783 if (index
< implemented_funcs
)
5784 return E_INVALIDARG
;
5785 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5789 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5791 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5794 switch (pTypeDesc
->vt
)
5796 case VT_USERDEFINED
:
5797 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5801 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5804 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5812 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5815 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5816 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5817 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5820 /* ITypeInfo::GetFuncDesc
5822 * Retrieves the FUNCDESC structure that contains information about a
5823 * specified function.
5826 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5827 LPFUNCDESC
*ppFuncDesc
)
5829 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5830 const FUNCDESC
*internal_funcdesc
;
5832 UINT hrefoffset
= 0;
5834 TRACE("(%p) index %d\n", This
, index
);
5837 return E_INVALIDARG
;
5839 if (This
->needs_layout
)
5840 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5842 if (This
->typekind
== TKIND_DISPATCH
)
5843 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5844 &internal_funcdesc
, NULL
,
5847 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5848 &internal_funcdesc
);
5851 WARN("description for function %d not found\n", index
);
5855 hr
= TLB_AllocAndInitFuncDesc(
5858 This
->typekind
== TKIND_DISPATCH
);
5860 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
5861 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5863 TRACE("-- 0x%08x\n", hr
);
5867 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5871 SIZE_T size
= sizeof(*src
);
5874 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5875 if (src
->varkind
== VAR_CONST
)
5876 size
+= sizeof(VARIANT
);
5877 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5879 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5880 if (!dest
) return E_OUTOFMEMORY
;
5883 buffer
= (char *)(dest
+ 1);
5884 if (src
->lpstrSchema
)
5887 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5888 len
= strlenW(src
->lpstrSchema
);
5889 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5890 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5893 if (src
->varkind
== VAR_CONST
)
5897 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5898 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5899 buffer
+= sizeof(VARIANT
);
5900 VariantInit(dest
->u
.lpvarValue
);
5901 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5904 SysFreeString((BSTR
)dest
);
5908 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5911 if (src
->varkind
== VAR_CONST
)
5912 VariantClear(dest
->u
.lpvarValue
);
5913 SysFreeString((BSTR
)dest
);
5920 /* ITypeInfo::GetVarDesc
5922 * Retrieves a VARDESC structure that describes the specified variable.
5925 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5926 LPVARDESC
*ppVarDesc
)
5928 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5929 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5931 TRACE("(%p) index %d\n", This
, index
);
5933 if(index
>= This
->cVars
)
5934 return TYPE_E_ELEMENTNOTFOUND
;
5936 if (This
->needs_layout
)
5937 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5939 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5942 /* ITypeInfo_GetNames
5944 * Retrieves the variable with the specified member ID (or the name of the
5945 * property or method and its parameters) that correspond to the specified
5948 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5949 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5951 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5952 const TLBFuncDesc
*pFDesc
;
5953 const TLBVarDesc
*pVDesc
;
5955 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5956 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
5959 /* function found, now return function and parameter names */
5960 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5963 *rgBstrNames
=SysAllocString(TLB_get_bstr(pFDesc
->Name
));
5965 rgBstrNames
[i
]=SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
-1].Name
));
5971 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
5974 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
5979 if(This
->impltypes
&&
5980 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
5981 /* recursive search */
5984 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5985 if(SUCCEEDED(result
))
5987 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5988 ITypeInfo_Release(pTInfo
);
5991 WARN("Could not search inherited interface!\n");
5995 WARN("no names found\n");
5998 return TYPE_E_ELEMENTNOTFOUND
;
6005 /* ITypeInfo::GetRefTypeOfImplType
6007 * If a type description describes a COM class, it retrieves the type
6008 * description of the implemented interface types. For an interface,
6009 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6013 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6018 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6021 TRACE("(%p) index %d\n", This
, index
);
6022 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6026 /* only valid on dual interfaces;
6027 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6030 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6036 hr
= TYPE_E_ELEMENTNOTFOUND
;
6039 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6041 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6042 *pRefType
= This
->pTypeLib
->dispatch_href
;
6046 if(index
>= This
->cImplTypes
)
6047 hr
= TYPE_E_ELEMENTNOTFOUND
;
6049 *pRefType
= This
->impltypes
[index
].hRef
;
6055 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6057 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6063 /* ITypeInfo::GetImplTypeFlags
6065 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6066 * or base interface in a type description.
6068 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6069 UINT index
, INT
*pImplTypeFlags
)
6071 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6073 TRACE("(%p) index %d\n", This
, index
);
6076 return E_INVALIDARG
;
6078 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6079 *pImplTypeFlags
= 0;
6083 if(index
>= This
->cImplTypes
)
6084 return TYPE_E_ELEMENTNOTFOUND
;
6086 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6092 * Maps between member names and member IDs, and parameter names and
6095 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6096 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6098 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6099 const TLBVarDesc
*pVDesc
;
6103 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6106 /* init out parameters in case of failure */
6107 for (i
= 0; i
< cNames
; i
++)
6108 pMemId
[i
] = MEMBERID_NIL
;
6110 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6112 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6113 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6114 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6115 for(i
=1; i
< cNames
; i
++){
6116 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6117 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6119 if( j
<pFDesc
->funcdesc
.cParams
)
6122 ret
=DISP_E_UNKNOWNNAME
;
6124 TRACE("-- 0x%08x\n", ret
);
6128 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6131 *pMemId
= pVDesc
->vardesc
.memid
;
6134 /* not found, see if it can be found in an inherited interface */
6135 if(This
->impltypes
) {
6136 /* recursive search */
6138 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6140 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6141 ITypeInfo_Release(pTInfo
);
6144 WARN("Could not search inherited interface!\n");
6146 WARN("no names found\n");
6147 return DISP_E_UNKNOWNNAME
;
6153 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6154 __ASM_GLOBAL_FUNC( call_method
,
6156 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6157 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6158 "movl %esp,%ebp\n\t"
6159 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6161 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6163 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6164 "movl 12(%ebp),%edx\n\t"
6165 "movl %esp,%edi\n\t"
6168 "subl %edx,%edi\n\t"
6169 "andl $~15,%edi\n\t"
6170 "movl %edi,%esp\n\t"
6171 "movl 12(%ebp),%ecx\n\t"
6172 "movl 16(%ebp),%esi\n\t"
6175 "1:\tcall *8(%ebp)\n\t"
6176 "subl %esp,%edi\n\t"
6177 "movl 20(%ebp),%ecx\n\t"
6178 "movl %edi,(%ecx)\n\t"
6179 "leal -8(%ebp),%esp\n\t"
6181 __ASM_CFI(".cfi_same_value %edi\n\t")
6183 __ASM_CFI(".cfi_same_value %esi\n\t")
6185 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6186 __ASM_CFI(".cfi_same_value %ebp\n\t")
6189 /* same function but returning floating point */
6190 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6192 /* ITypeInfo::Invoke
6194 * Invokes a method, or accesses a property of an object, that implements the
6195 * interface described by the type description.
6198 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6202 if (TRACE_ON(ole
)) {
6204 TRACE("Calling %p(",func
);
6205 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6206 if (nrargs
> 30) TRACE("...");
6213 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6216 FIXME("unsupported calling convention %d\n",callconv
);
6220 TRACE("returns %08x\n",res
);
6224 #elif defined(__x86_64__)
6226 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6227 __ASM_GLOBAL_FUNC( call_method
,
6229 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6230 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6231 "movq %rsp,%rbp\n\t"
6232 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6234 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6236 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6237 "movq %rcx,%rax\n\t"
6240 "cmovgq %rdx,%rcx\n\t"
6241 "leaq 0(,%rcx,8),%rdx\n\t"
6242 "subq %rdx,%rsp\n\t"
6243 "andq $~15,%rsp\n\t"
6244 "movq %rsp,%rdi\n\t"
6247 "movq 0(%rsp),%rcx\n\t"
6248 "movq 8(%rsp),%rdx\n\t"
6249 "movq 16(%rsp),%r8\n\t"
6250 "movq 24(%rsp),%r9\n\t"
6251 "movq %rcx,%xmm0\n\t"
6252 "movq %rdx,%xmm1\n\t"
6253 "movq %r8,%xmm2\n\t"
6254 "movq %r9,%xmm3\n\t"
6256 "leaq -16(%rbp),%rsp\n\t"
6258 __ASM_CFI(".cfi_same_value %rdi\n\t")
6260 __ASM_CFI(".cfi_same_value %rsi\n\t")
6261 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6263 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6264 __ASM_CFI(".cfi_same_value %rbp\n\t")
6267 /* same function but returning floating point */
6268 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6270 #endif /* __x86_64__ */
6272 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6275 ITypeInfo
*tinfo2
= NULL
;
6276 TYPEATTR
*tattr
= NULL
;
6278 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6281 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6283 tdesc
->u
.hreftype
, hr
);
6286 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6289 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6290 ITypeInfo_Release(tinfo2
);
6294 switch (tattr
->typekind
)
6301 tdesc
= &tattr
->tdescAlias
;
6302 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6305 case TKIND_INTERFACE
:
6306 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6312 case TKIND_DISPATCH
:
6321 FIXME("TKIND_RECORD unhandled.\n");
6326 FIXME("TKIND_UNION unhandled.\n");
6331 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6335 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6336 ITypeInfo_Release(tinfo2
);
6340 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6344 /* enforce only one level of pointer indirection */
6345 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6347 tdesc
= tdesc
->u
.lptdesc
;
6349 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6350 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6351 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6352 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6353 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6355 VARTYPE vt_userdefined
= 0;
6356 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6357 if (tdesc
->vt
== VT_PTR
)
6359 vt_userdefined
= VT_BYREF
;
6360 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6362 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6364 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6365 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6367 *vt
|= vt_userdefined
;
6379 case VT_USERDEFINED
:
6380 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6387 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6388 hr
= DISP_E_BADVARTYPE
;
6392 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6407 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6413 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6417 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6419 ITypeInfo_Release(tinfo2
);
6423 switch(tattr
->typekind
) {
6425 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6428 case TKIND_INTERFACE
:
6429 case TKIND_DISPATCH
:
6430 *guid
= tattr
->guid
;
6434 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6435 hres
= E_UNEXPECTED
;
6438 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6439 ITypeInfo_Release(tinfo2
);
6443 /***********************************************************************
6444 * DispCallFunc (OLEAUT32.@)
6446 * Invokes a function of the specified calling convention, passing the
6447 * specified arguments and returns the result.
6450 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6451 * oVft [I] The offset in the vtable. See notes.
6452 * cc [I] Calling convention of the function to call.
6453 * vtReturn [I] The return type of the function.
6454 * cActuals [I] Number of parameters.
6455 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6456 * prgpvarg [I] The arguments to pass.
6457 * pvargResult [O] The return value of the function. Can be NULL.
6461 * Failure: HRESULT code.
6464 * The HRESULT return value of this function is not affected by the return
6465 * value of the user supplied function, which is returned in pvargResult.
6467 * If pvInstance is NULL then a non-object function is to be called and oVft
6468 * is the address of the function to call.
6470 * The cc parameter can be one of the following values:
6483 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6484 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6487 int argspos
, stack_offset
;
6492 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6493 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6494 pvargResult
, V_VT(pvargResult
));
6496 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6498 FIXME("unsupported calling convention %d\n",cc
);
6499 return E_INVALIDARG
;
6502 /* maximum size for an argument is sizeof(VARIANT) */
6503 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6505 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6509 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6510 func
= vtable
[oVft
/sizeof(void *)];
6511 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6513 else func
= (void *)oVft
;
6515 for (i
= 0; i
< cActuals
; i
++)
6517 VARIANT
*arg
= prgpvarg
[i
];
6528 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6529 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6533 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6534 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6536 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6537 args
[argspos
++] = V_BOOL(arg
);
6540 args
[argspos
++] = V_UI4(arg
);
6543 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6550 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6553 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6557 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6561 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6562 call_method( func
, argspos
, args
, &stack_offset
);
6567 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6570 WARN("invalid return type %u\n", vtReturn
);
6572 return E_INVALIDARG
;
6574 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6578 if (stack_offset
&& cc
== CC_STDCALL
)
6580 WARN( "stack pointer off by %d\n", stack_offset
);
6581 return DISP_E_BADCALLEE
;
6583 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6584 TRACE("retval: "); dump_Variant(pvargResult
);
6587 #elif defined(__x86_64__)
6593 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6594 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6595 pvargResult
, V_VT(pvargResult
));
6597 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6599 FIXME("unsupported calling convention %d\n",cc
);
6600 return E_INVALIDARG
;
6603 /* maximum size for an argument is sizeof(DWORD_PTR) */
6604 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6606 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6610 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6611 func
= vtable
[oVft
/sizeof(void *)];
6612 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6614 else func
= (void *)oVft
;
6616 for (i
= 0; i
< cActuals
; i
++)
6618 VARIANT
*arg
= prgpvarg
[i
];
6624 args
[argspos
++] = (ULONG_PTR
)arg
;
6626 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6627 args
[argspos
++] = V_BOOL(arg
);
6630 args
[argspos
++] = V_UI8(arg
);
6633 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6640 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6644 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6648 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6649 call_method( func
, argspos
, args
);
6652 WARN("invalid return type %u\n", vtReturn
);
6654 return E_INVALIDARG
;
6656 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6660 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6661 TRACE("retval: "); dump_Variant(pvargResult
);
6665 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6666 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6671 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6673 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6676 #define INVBUF_ELEMENT_SIZE \
6677 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6678 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6679 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6680 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6681 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6682 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6683 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6684 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6686 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6691 DISPPARAMS
*pDispParams
,
6692 VARIANT
*pVarResult
,
6693 EXCEPINFO
*pExcepInfo
,
6696 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6698 unsigned int var_index
;
6701 const TLBFuncDesc
*pFuncInfo
;
6704 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6705 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6708 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6709 return DISP_E_MEMBERNOTFOUND
;
6713 ERR("NULL pDispParams not allowed\n");
6714 return E_INVALIDARG
;
6717 dump_DispParms(pDispParams
);
6719 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6721 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6722 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6723 return E_INVALIDARG
;
6726 /* we do this instead of using GetFuncDesc since it will return a fake
6727 * FUNCDESC for dispinterfaces and we want the real function description */
6728 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6729 pFuncInfo
= &This
->funcdescs
[fdc
];
6730 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6731 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6732 !func_restricted( &pFuncInfo
->funcdesc
))
6736 if (fdc
< This
->cFuncs
) {
6737 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6741 TRACE("invoking:\n");
6742 dump_TLBFuncDescOne(pFuncInfo
);
6745 switch (func_desc
->funckind
) {
6746 case FUNC_PUREVIRTUAL
:
6747 case FUNC_VIRTUAL
: {
6748 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6750 VARIANT retval
; /* pointer for storing byref retvals in */
6751 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6752 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6753 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6754 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6755 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6756 UINT vargs_converted
=0;
6760 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6762 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6764 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6765 hres
= DISP_E_PARAMNOTFOUND
;
6770 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6772 ERR("functions with the vararg attribute do not support named arguments\n");
6773 hres
= DISP_E_NONAMEDARGS
;
6777 for (i
= 0; i
< func_desc
->cParams
; i
++)
6779 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6780 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6785 TRACE("changing args\n");
6786 for (i
= 0; i
< func_desc
->cParams
; i
++)
6788 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6789 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6790 VARIANTARG
*src_arg
;
6792 if (wParamFlags
& PARAMFLAG_FLCID
)
6795 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6797 V_I4(arg
) = This
->pTypeLib
->lcid
;
6806 for (j
= 0; j
< cNamedArgs
; j
++)
6807 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6809 src_arg
= &pDispParams
->rgvarg
[j
];
6814 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6816 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6820 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6822 /* under most conditions the caller is not allowed to
6823 * pass in a dispparam arg in the index of what would be
6824 * the retval parameter. however, there is an exception
6825 * where the extra parameter is used in an extra
6826 * IDispatch::Invoke below */
6827 if ((i
< pDispParams
->cArgs
) &&
6828 ((func_desc
->cParams
!= 1) || !pVarResult
||
6829 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6831 hres
= DISP_E_BADPARAMCOUNT
;
6835 /* note: this check is placed so that if the caller passes
6836 * in a VARIANTARG for the retval we just ignore it, like
6838 if (i
== func_desc
->cParams
- 1)
6841 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6842 memset(arg
, 0, sizeof(*arg
));
6843 V_VT(arg
) = rgvt
[i
];
6844 memset(&retval
, 0, sizeof(retval
));
6845 V_BYREF(arg
) = &retval
;
6849 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6850 hres
= E_UNEXPECTED
;
6856 dump_Variant(src_arg
);
6858 if(rgvt
[i
]!=V_VT(src_arg
))
6860 if (rgvt
[i
] == VT_VARIANT
)
6861 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6862 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6864 if (rgvt
[i
] == V_VT(src_arg
))
6865 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6868 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6869 if (wParamFlags
& PARAMFLAG_FIN
)
6870 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6871 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6873 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6875 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6878 SAFEARRAYBOUND bound
;
6882 bound
.cElements
= pDispParams
->cArgs
-i
;
6883 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6885 ERR("SafeArrayCreate failed\n");
6888 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6891 ERR("SafeArrayAccessData failed with %x\n", hres
);
6892 SafeArrayDestroy(a
);
6895 for (j
= 0; j
< bound
.cElements
; j
++)
6896 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6897 hres
= SafeArrayUnaccessData(a
);
6900 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6901 SafeArrayDestroy(a
);
6904 V_ARRAY(&rgvarg
[i
]) = a
;
6905 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6907 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6909 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6910 if (wParamFlags
& PARAMFLAG_FIN
)
6911 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6913 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6914 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6915 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6917 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6919 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6920 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6924 /* FIXME: this doesn't work for VT_BYREF arguments if
6925 * they are not the same type as in the paramdesc */
6926 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6927 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6928 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6933 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6934 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6935 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6938 prgpvarg
[i
] = &rgvarg
[i
];
6942 prgpvarg
[i
] = src_arg
;
6945 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
6946 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
6947 && V_UNKNOWN(prgpvarg
[i
])) {
6948 IUnknown
*userdefined_iface
;
6951 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
6955 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
6957 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
6961 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
6962 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
6965 else if (wParamFlags
& PARAMFLAG_FOPT
)
6968 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6969 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6971 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6977 VARIANTARG
*missing_arg
;
6978 /* if the function wants a pointer to a variant then
6979 * set that up, otherwise just pass the VT_ERROR in
6980 * the argument by value */
6981 if (rgvt
[i
] & VT_BYREF
)
6983 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6984 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6985 V_VARIANTREF(arg
) = missing_arg
;
6989 V_VT(missing_arg
) = VT_ERROR
;
6990 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6995 hres
= DISP_E_BADPARAMCOUNT
;
6999 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7001 /* VT_VOID is a special case for return types, so it is not
7002 * handled in the general function */
7003 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7004 V_VT(&varresult
) = VT_EMPTY
;
7007 V_VT(&varresult
) = 0;
7008 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7009 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7012 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7013 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7014 prgpvarg
, &varresult
);
7016 vargs_converted
= 0;
7018 for (i
= 0; i
< func_desc
->cParams
; i
++)
7020 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7021 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7023 if (wParamFlags
& PARAMFLAG_FLCID
)
7025 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7029 TRACE("[retval] value: ");
7030 dump_Variant(prgpvarg
[i
]);
7035 VariantInit(pVarResult
);
7036 /* deref return value */
7037 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7040 VARIANT_ClearInd(prgpvarg
[i
]);
7042 else if (vargs_converted
< pDispParams
->cArgs
)
7044 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7045 if (wParamFlags
& PARAMFLAG_FOUT
)
7047 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7049 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7053 ERR("failed to convert param %d to vt %d\n", i
,
7054 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7059 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7060 func_desc
->cParamsOpt
< 0 &&
7061 i
== func_desc
->cParams
-1)
7063 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7066 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7069 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7072 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7075 ERR("SafeArrayAccessData failed with %x\n", hres
);
7078 for (j
= 0; j
<= ubound
; j
++)
7079 VariantClear(&v
[j
]);
7080 hres
= SafeArrayUnaccessData(a
);
7083 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7087 VariantClear(&rgvarg
[i
]);
7090 else if (wParamFlags
& PARAMFLAG_FOPT
)
7092 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7093 VariantClear(&rgvarg
[i
]);
7096 VariantClear(&missing_arg
[i
]);
7099 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7101 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7102 hres
= DISP_E_EXCEPTION
;
7105 IErrorInfo
*pErrorInfo
;
7106 pExcepInfo
->scode
= V_ERROR(&varresult
);
7107 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7109 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7110 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7111 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7112 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7114 IErrorInfo_Release(pErrorInfo
);
7118 if (V_VT(&varresult
) != VT_ERROR
)
7120 TRACE("varresult value: ");
7121 dump_Variant(&varresult
);
7125 VariantClear(pVarResult
);
7126 *pVarResult
= varresult
;
7129 VariantClear(&varresult
);
7132 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7133 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7134 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7135 (pDispParams
->cArgs
!= 0))
7137 if (V_VT(pVarResult
) == VT_DISPATCH
)
7139 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7140 /* Note: not VariantClear; we still need the dispatch
7141 * pointer to be valid */
7142 VariantInit(pVarResult
);
7143 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7144 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7145 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7146 IDispatch_Release(pDispatch
);
7150 VariantClear(pVarResult
);
7151 hres
= DISP_E_NOTACOLLECTION
;
7159 case FUNC_DISPATCH
: {
7162 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7163 if (SUCCEEDED(hres
)) {
7164 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7165 hres
= IDispatch_Invoke(
7166 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7167 pVarResult
,pExcepInfo
,pArgErr
7170 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7171 IDispatch_Release(disp
);
7173 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7177 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7182 TRACE("-- 0x%08x\n", hres
);
7185 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7188 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7189 if(FAILED(hres
)) return hres
;
7191 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7192 dump_VARDESC(var_desc
);
7193 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7197 /* not found, look for it in inherited interfaces */
7198 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7199 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7200 if(This
->impltypes
) {
7201 /* recursive search */
7203 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7204 if(SUCCEEDED(hres
)){
7205 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7206 ITypeInfo_Release(pTInfo
);
7209 WARN("Could not search inherited interface!\n");
7212 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7213 return DISP_E_MEMBERNOTFOUND
;
7216 /* ITypeInfo::GetDocumentation
7218 * Retrieves the documentation string, the complete Help file name and path,
7219 * and the context ID for the Help topic for a specified type description.
7221 * (Can be tested by the Visual Basic Editor in Word for instance.)
7223 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7224 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7225 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7227 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7228 const TLBFuncDesc
*pFDesc
;
7229 const TLBVarDesc
*pVDesc
;
7230 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7231 " HelpContext(%p) HelpFile(%p)\n",
7232 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7233 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7235 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7237 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7239 *pdwHelpContext
=This
->dwHelpContext
;
7241 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7243 }else {/* for a member */
7244 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7247 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7249 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7251 *pdwHelpContext
=pFDesc
->helpcontext
;
7253 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7256 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7259 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7261 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7263 *pdwHelpContext
=pVDesc
->HelpContext
;
7265 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7270 if(This
->impltypes
&&
7271 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7272 /* recursive search */
7275 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7276 if(SUCCEEDED(result
)) {
7277 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7278 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7279 ITypeInfo_Release(pTInfo
);
7282 WARN("Could not search inherited interface!\n");
7285 WARN("member %d not found\n", memid
);
7286 return TYPE_E_ELEMENTNOTFOUND
;
7289 /* ITypeInfo::GetDllEntry
7291 * Retrieves a description or specification of an entry point for a function
7294 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7295 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7298 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7299 const TLBFuncDesc
*pFDesc
;
7301 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7303 if (pBstrDllName
) *pBstrDllName
= NULL
;
7304 if (pBstrName
) *pBstrName
= NULL
;
7305 if (pwOrdinal
) *pwOrdinal
= 0;
7307 if (This
->typekind
!= TKIND_MODULE
)
7308 return TYPE_E_BADMODULEKIND
;
7310 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7312 dump_TypeInfo(This
);
7314 dump_TLBFuncDescOne(pFDesc
);
7317 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7319 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7321 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7329 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7332 return TYPE_E_ELEMENTNOTFOUND
;
7335 /* internal function to make the inherited interfaces' methods appear
7336 * part of the interface */
7337 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7338 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7340 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7343 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7345 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7347 ITypeInfo
*pSubTypeInfo
;
7349 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7353 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7355 ITypeInfo_Release(pSubTypeInfo
);
7359 *hRefType
-= DISPATCH_HREF_OFFSET
;
7361 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7362 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7367 /* ITypeInfo::GetRefTypeInfo
7369 * If a type description references other type descriptions, it retrieves
7370 * the referenced type descriptions.
7372 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7375 ITypeInfo
**ppTInfo
)
7377 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7378 HRESULT result
= E_FAIL
;
7381 return E_INVALIDARG
;
7383 if ((INT
)hRefType
< 0) {
7384 ITypeInfoImpl
*pTypeInfoImpl
;
7386 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7387 !(This
->typekind
== TKIND_INTERFACE
||
7388 This
->typekind
== TKIND_DISPATCH
))
7389 return TYPE_E_ELEMENTNOTFOUND
;
7391 /* when we meet a DUAL typeinfo, we must create the alternate
7394 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7396 *pTypeInfoImpl
= *This
;
7397 pTypeInfoImpl
->ref
= 0;
7399 if (This
->typekind
== TKIND_INTERFACE
)
7400 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7402 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7404 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7405 /* the AddRef implicitly adds a reference to the parent typelib, which
7406 * stops the copied data from being destroyed until the new typeinfo's
7407 * refcount goes to zero, but we need to signal to the new instance to
7408 * not free its data structures when it is destroyed */
7409 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7411 ITypeInfo_AddRef(*ppTInfo
);
7414 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7415 (This
->typekind
== TKIND_DISPATCH
))
7417 HREFTYPE href_dispatch
= hRefType
;
7418 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7420 TLBRefType
*ref_type
;
7421 ITypeLib
*pTLib
= NULL
;
7424 if(!(hRefType
& 0x1)){
7425 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7427 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7430 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7431 ITypeInfo_AddRef(*ppTInfo
);
7435 result
= TYPE_E_ELEMENTNOTFOUND
;
7439 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7441 if(ref_type
->reference
== (hRefType
& (~0x3)))
7444 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7446 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7450 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7452 TRACE("internal reference\n");
7453 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7455 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7456 TRACE("typeinfo in imported typelib that is already loaded\n");
7457 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7458 ITypeLib_AddRef(pTLib
);
7461 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7462 result
= LoadRegTypeLib( TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7463 ref_type
->pImpTLInfo
->wVersionMajor
,
7464 ref_type
->pImpTLInfo
->wVersionMinor
,
7465 ref_type
->pImpTLInfo
->lcid
,
7468 if(FAILED(result
)) {
7469 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
7470 result
=LoadTypeLib(libnam
, &pTLib
);
7471 SysFreeString(libnam
);
7473 if(SUCCEEDED(result
)) {
7474 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7475 ITypeLib_AddRef(pTLib
);
7479 if(SUCCEEDED(result
)) {
7480 if(ref_type
->index
== TLB_REF_USE_GUID
)
7481 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7483 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7486 ITypeLib_Release(pTLib
);
7490 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7491 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7495 /* ITypeInfo::AddressOfMember
7497 * Retrieves the addresses of static functions or variables, such as those
7500 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7501 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7503 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7509 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7511 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7515 module
= LoadLibraryW(dll
);
7518 ERR("couldn't load %s\n", debugstr_w(dll
));
7520 SysFreeString(entry
);
7521 return STG_E_FILENOTFOUND
;
7523 /* FIXME: store library somewhere where we can free it */
7528 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7529 entryA
= heap_alloc(len
);
7530 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7532 *ppv
= GetProcAddress(module
, entryA
);
7534 ERR("function not found %s\n", debugstr_a(entryA
));
7540 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7542 ERR("function not found %d\n", ordinal
);
7546 SysFreeString(entry
);
7549 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7554 /* ITypeInfo::CreateInstance
7556 * Creates a new instance of a type that describes a component object class
7559 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7560 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7562 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7566 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7572 WARN("Not able to aggregate\n");
7573 return CLASS_E_NOAGGREGATION
;
7576 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7577 if(FAILED(hr
)) return hr
;
7579 if(pTA
->typekind
!= TKIND_COCLASS
)
7581 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7587 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7590 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7591 TRACE("GetActiveObject rets %08x\n", hr
);
7594 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7595 IUnknown_Release(pUnk
);
7600 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7601 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7605 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7609 /* ITypeInfo::GetMops
7611 * Retrieves marshalling information.
7613 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7616 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7617 FIXME("(%p %d) stub!\n", This
, memid
);
7622 /* ITypeInfo::GetContainingTypeLib
7624 * Retrieves the containing type library and the index of the type description
7625 * within that type library.
7627 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7628 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7630 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7632 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7634 *pIndex
=This
->index
;
7635 TRACE("returning pIndex=%d\n", *pIndex
);
7639 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7640 ITypeLib_AddRef(*ppTLib
);
7641 TRACE("returning ppTLib=%p\n", *ppTLib
);
7647 /* ITypeInfo::ReleaseTypeAttr
7649 * Releases a TYPEATTR previously returned by Get
7652 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7653 TYPEATTR
* pTypeAttr
)
7655 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7656 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7657 heap_free(pTypeAttr
);
7660 /* ITypeInfo::ReleaseFuncDesc
7662 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7664 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7666 FUNCDESC
*pFuncDesc
)
7668 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7671 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7673 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7674 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7675 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7677 SysFreeString((BSTR
)pFuncDesc
);
7680 /* ITypeInfo::ReleaseVarDesc
7682 * Releases a VARDESC previously returned by GetVarDesc.
7684 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7687 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7688 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7690 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
7691 if (pVarDesc
->varkind
== VAR_CONST
)
7692 VariantClear(pVarDesc
->u
.lpvarValue
);
7693 SysFreeString((BSTR
)pVarDesc
);
7696 /* ITypeInfo2::GetTypeKind
7698 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7701 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7702 TYPEKIND
*pTypeKind
)
7704 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7705 *pTypeKind
=This
->typekind
;
7706 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7710 /* ITypeInfo2::GetTypeFlags
7712 * Returns the type flags without any allocations. This returns a DWORD type
7713 * flag, which expands the type flags without growing the TYPEATTR (type
7717 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7719 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7720 *pTypeFlags
=This
->wTypeFlags
;
7721 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7725 /* ITypeInfo2::GetFuncIndexOfMemId
7726 * Binds to a specific member based on a known DISPID, where the member name
7727 * is not known (for example, when binding to a default member).
7730 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7731 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7733 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7737 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7738 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7739 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7742 if(fdc
< This
->cFuncs
) {
7746 result
= TYPE_E_ELEMENTNOTFOUND
;
7748 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7749 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7753 /* TypeInfo2::GetVarIndexOfMemId
7755 * Binds to a specific member based on a known DISPID, where the member name
7756 * is not known (for example, when binding to a default member).
7759 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7760 MEMBERID memid
, UINT
*pVarIndex
)
7762 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7763 TLBVarDesc
*pVarInfo
;
7765 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7767 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7769 return TYPE_E_ELEMENTNOTFOUND
;
7771 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7776 /* ITypeInfo2::GetCustData
7778 * Gets the custom data
7780 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7785 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7786 TLBCustData
*pCData
;
7788 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7790 if(!guid
|| !pVarVal
)
7791 return E_INVALIDARG
;
7793 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
7795 VariantInit( pVarVal
);
7797 VariantCopy( pVarVal
, &pCData
->data
);
7799 VariantClear( pVarVal
);
7803 /* ITypeInfo2::GetFuncCustData
7805 * Gets the custom data
7807 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7813 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7814 TLBCustData
*pCData
;
7815 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7817 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7819 if(index
>= This
->cFuncs
)
7820 return TYPE_E_ELEMENTNOTFOUND
;
7822 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7824 return TYPE_E_ELEMENTNOTFOUND
;
7826 VariantInit(pVarVal
);
7827 VariantCopy(pVarVal
, &pCData
->data
);
7832 /* ITypeInfo2::GetParamCustData
7834 * Gets the custom data
7836 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7843 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7844 TLBCustData
*pCData
;
7845 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7847 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7848 debugstr_guid(guid
), pVarVal
);
7850 if(indexFunc
>= This
->cFuncs
)
7851 return TYPE_E_ELEMENTNOTFOUND
;
7853 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7854 return TYPE_E_ELEMENTNOTFOUND
;
7856 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7858 return TYPE_E_ELEMENTNOTFOUND
;
7860 VariantInit(pVarVal
);
7861 VariantCopy(pVarVal
, &pCData
->data
);
7866 /* ITypeInfo2::GetVarCustData
7868 * Gets the custom data
7870 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7876 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7877 TLBCustData
*pCData
;
7878 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7880 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7882 if(index
>= This
->cVars
)
7883 return TYPE_E_ELEMENTNOTFOUND
;
7885 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7887 return TYPE_E_ELEMENTNOTFOUND
;
7889 VariantInit(pVarVal
);
7890 VariantCopy(pVarVal
, &pCData
->data
);
7895 /* ITypeInfo2::GetImplCustData
7897 * Gets the custom data
7899 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7905 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7906 TLBCustData
*pCData
;
7907 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7909 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7911 if(index
>= This
->cImplTypes
)
7912 return TYPE_E_ELEMENTNOTFOUND
;
7914 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7916 return TYPE_E_ELEMENTNOTFOUND
;
7918 VariantInit(pVarVal
);
7919 VariantCopy(pVarVal
, &pCData
->data
);
7924 /* ITypeInfo2::GetDocumentation2
7926 * Retrieves the documentation string, the complete Help file name and path,
7927 * the localization context to use, and the context ID for the library Help
7928 * topic in the Help file.
7931 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7935 BSTR
*pbstrHelpString
,
7936 DWORD
*pdwHelpStringContext
,
7937 BSTR
*pbstrHelpStringDll
)
7939 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7940 const TLBFuncDesc
*pFDesc
;
7941 const TLBVarDesc
*pVDesc
;
7942 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7943 "HelpStringContext(%p) HelpStringDll(%p)\n",
7944 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7945 pbstrHelpStringDll
);
7946 /* the help string should be obtained from the helpstringdll,
7947 * using the _DLLGetDocumentation function, based on the supplied
7948 * lcid. Nice to do sometime...
7950 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7952 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
7953 if(pdwHelpStringContext
)
7954 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7955 if(pbstrHelpStringDll
)
7956 *pbstrHelpStringDll
=
7957 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7959 }else {/* for a member */
7960 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7963 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7964 if(pdwHelpStringContext
)
7965 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7966 if(pbstrHelpStringDll
)
7967 *pbstrHelpStringDll
=
7968 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7971 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7974 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7975 if(pdwHelpStringContext
)
7976 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7977 if(pbstrHelpStringDll
)
7978 *pbstrHelpStringDll
=
7979 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7983 return TYPE_E_ELEMENTNOTFOUND
;
7986 /* ITypeInfo2::GetAllCustData
7988 * Gets all custom data items for the Type info.
7991 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7993 CUSTDATA
*pCustData
)
7995 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7997 TRACE("%p %p\n", This
, pCustData
);
7999 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
8002 /* ITypeInfo2::GetAllFuncCustData
8004 * Gets all custom data items for the specified Function
8007 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8010 CUSTDATA
*pCustData
)
8012 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8013 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8015 TRACE("%p %u %p\n", This
, index
, pCustData
);
8017 if(index
>= This
->cFuncs
)
8018 return TYPE_E_ELEMENTNOTFOUND
;
8020 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8023 /* ITypeInfo2::GetAllParamCustData
8025 * Gets all custom data items for the Functions
8028 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8029 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8031 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8032 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8034 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8036 if(indexFunc
>= This
->cFuncs
)
8037 return TYPE_E_ELEMENTNOTFOUND
;
8039 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8040 return TYPE_E_ELEMENTNOTFOUND
;
8042 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8045 /* ITypeInfo2::GetAllVarCustData
8047 * Gets all custom data items for the specified Variable
8050 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8051 UINT index
, CUSTDATA
*pCustData
)
8053 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8054 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8056 TRACE("%p %u %p\n", This
, index
, pCustData
);
8058 if(index
>= This
->cVars
)
8059 return TYPE_E_ELEMENTNOTFOUND
;
8061 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8064 /* ITypeInfo2::GetAllImplCustData
8066 * Gets all custom data items for the specified implementation type
8069 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8072 CUSTDATA
*pCustData
)
8074 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8075 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8077 TRACE("%p %u %p\n", This
, index
, pCustData
);
8079 if(index
>= This
->cImplTypes
)
8080 return TYPE_E_ELEMENTNOTFOUND
;
8082 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8085 static const ITypeInfo2Vtbl tinfvt
=
8088 ITypeInfo_fnQueryInterface
,
8090 ITypeInfo_fnRelease
,
8092 ITypeInfo_fnGetTypeAttr
,
8093 ITypeInfo_fnGetTypeComp
,
8094 ITypeInfo_fnGetFuncDesc
,
8095 ITypeInfo_fnGetVarDesc
,
8096 ITypeInfo_fnGetNames
,
8097 ITypeInfo_fnGetRefTypeOfImplType
,
8098 ITypeInfo_fnGetImplTypeFlags
,
8099 ITypeInfo_fnGetIDsOfNames
,
8101 ITypeInfo_fnGetDocumentation
,
8102 ITypeInfo_fnGetDllEntry
,
8103 ITypeInfo_fnGetRefTypeInfo
,
8104 ITypeInfo_fnAddressOfMember
,
8105 ITypeInfo_fnCreateInstance
,
8106 ITypeInfo_fnGetMops
,
8107 ITypeInfo_fnGetContainingTypeLib
,
8108 ITypeInfo_fnReleaseTypeAttr
,
8109 ITypeInfo_fnReleaseFuncDesc
,
8110 ITypeInfo_fnReleaseVarDesc
,
8112 ITypeInfo2_fnGetTypeKind
,
8113 ITypeInfo2_fnGetTypeFlags
,
8114 ITypeInfo2_fnGetFuncIndexOfMemId
,
8115 ITypeInfo2_fnGetVarIndexOfMemId
,
8116 ITypeInfo2_fnGetCustData
,
8117 ITypeInfo2_fnGetFuncCustData
,
8118 ITypeInfo2_fnGetParamCustData
,
8119 ITypeInfo2_fnGetVarCustData
,
8120 ITypeInfo2_fnGetImplTypeCustData
,
8121 ITypeInfo2_fnGetDocumentation2
,
8122 ITypeInfo2_fnGetAllCustData
,
8123 ITypeInfo2_fnGetAllFuncCustData
,
8124 ITypeInfo2_fnGetAllParamCustData
,
8125 ITypeInfo2_fnGetAllVarCustData
,
8126 ITypeInfo2_fnGetAllImplTypeCustData
,
8129 /******************************************************************************
8130 * CreateDispTypeInfo [OLEAUT32.31]
8132 * Build type information for an object so it can be called through an
8133 * IDispatch interface.
8136 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8137 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8140 * This call allows an objects methods to be accessed through IDispatch, by
8141 * building an ITypeInfo object that IDispatch can use to call through.
8143 HRESULT WINAPI
CreateDispTypeInfo(
8144 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8145 LCID lcid
, /* [I] Locale Id */
8146 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8148 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8149 ITypeLibImpl
*pTypeLibImpl
;
8150 unsigned int param
, func
;
8151 TLBFuncDesc
*pFuncDesc
;
8155 pTypeLibImpl
= TypeLibImpl_Constructor();
8156 if (!pTypeLibImpl
) return E_FAIL
;
8158 pTypeLibImpl
->TypeInfoCount
= 2;
8159 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8161 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8162 pTIIface
->pTypeLib
= pTypeLibImpl
;
8163 pTIIface
->index
= 0;
8164 pTIIface
->Name
= NULL
;
8165 pTIIface
->dwHelpContext
= -1;
8166 pTIIface
->guid
= NULL
;
8167 pTIIface
->lcid
= lcid
;
8168 pTIIface
->typekind
= TKIND_INTERFACE
;
8169 pTIIface
->wMajorVerNum
= 0;
8170 pTIIface
->wMinorVerNum
= 0;
8171 pTIIface
->cbAlignment
= 2;
8172 pTIIface
->cbSizeInstance
= -1;
8173 pTIIface
->cbSizeVft
= -1;
8174 pTIIface
->cFuncs
= 0;
8175 pTIIface
->cImplTypes
= 0;
8176 pTIIface
->cVars
= 0;
8177 pTIIface
->wTypeFlags
= 0;
8178 pTIIface
->hreftype
= 0;
8180 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8181 pFuncDesc
= pTIIface
->funcdescs
;
8182 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8183 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8184 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8185 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8186 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8187 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8188 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8189 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8190 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8191 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8192 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8193 pFuncDesc
->funcdesc
.cScodes
= 0;
8194 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8195 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8196 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8197 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8198 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8199 md
->cArgs
* sizeof(ELEMDESC
));
8200 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8201 for(param
= 0; param
< md
->cArgs
; param
++) {
8202 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8203 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8205 pFuncDesc
->helpcontext
= 0;
8206 pFuncDesc
->HelpStringContext
= 0;
8207 pFuncDesc
->HelpString
= NULL
;
8208 pFuncDesc
->Entry
= NULL
;
8209 list_init(&pFuncDesc
->custdata_list
);
8214 dump_TypeInfo(pTIIface
);
8216 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8217 pTIClass
->pTypeLib
= pTypeLibImpl
;
8218 pTIClass
->index
= 1;
8219 pTIClass
->Name
= NULL
;
8220 pTIClass
->dwHelpContext
= -1;
8221 pTIClass
->guid
= NULL
;
8222 pTIClass
->lcid
= lcid
;
8223 pTIClass
->typekind
= TKIND_COCLASS
;
8224 pTIClass
->wMajorVerNum
= 0;
8225 pTIClass
->wMinorVerNum
= 0;
8226 pTIClass
->cbAlignment
= 2;
8227 pTIClass
->cbSizeInstance
= -1;
8228 pTIClass
->cbSizeVft
= -1;
8229 pTIClass
->cFuncs
= 0;
8230 pTIClass
->cImplTypes
= 1;
8231 pTIClass
->cVars
= 0;
8232 pTIClass
->wTypeFlags
= 0;
8233 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8235 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8237 ref
= heap_alloc_zero(sizeof(*ref
));
8238 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8239 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8241 dump_TypeInfo(pTIClass
);
8243 *pptinfo
= (ITypeInfo
*)pTIClass
;
8245 ITypeInfo_AddRef(*pptinfo
);
8246 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8252 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8254 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8256 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
8259 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8261 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8263 return ITypeInfo_AddRef((ITypeInfo
*)This
);
8266 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8268 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8270 return ITypeInfo_Release((ITypeInfo
*)This
);
8273 static HRESULT WINAPI
ITypeComp_fnBind(
8278 ITypeInfo
** ppTInfo
,
8279 DESCKIND
* pDescKind
,
8282 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8283 const TLBFuncDesc
*pFDesc
;
8284 const TLBVarDesc
*pVDesc
;
8285 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8288 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8290 *pDescKind
= DESCKIND_NONE
;
8291 pBindPtr
->lpfuncdesc
= NULL
;
8294 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8295 pFDesc
= &This
->funcdescs
[fdc
];
8296 if (!strcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8297 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8300 /* name found, but wrong flags */
8301 hr
= TYPE_E_TYPEMISMATCH
;
8305 if (fdc
< This
->cFuncs
)
8307 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8309 &pBindPtr
->lpfuncdesc
,
8310 This
->typekind
== TKIND_DISPATCH
);
8313 *pDescKind
= DESCKIND_FUNCDESC
;
8314 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8315 ITypeInfo_AddRef(*ppTInfo
);
8318 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8320 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8323 *pDescKind
= DESCKIND_VARDESC
;
8324 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8325 ITypeInfo_AddRef(*ppTInfo
);
8329 /* FIXME: search each inherited interface, not just the first */
8330 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8331 /* recursive search */
8335 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8338 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8339 ITypeInfo_Release(pTInfo
);
8343 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8344 ITypeComp_Release(pTComp
);
8347 WARN("Could not search inherited interface!\n");
8349 if (hr
== DISP_E_MEMBERNOTFOUND
)
8351 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8355 static HRESULT WINAPI
ITypeComp_fnBindType(
8359 ITypeInfo
** ppTInfo
,
8360 ITypeComp
** ppTComp
)
8362 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8364 /* strange behaviour (does nothing) but like the
8367 if (!ppTInfo
|| !ppTComp
)
8376 static const ITypeCompVtbl tcompvt
=
8379 ITypeComp_fnQueryInterface
,
8381 ITypeComp_fnRelease
,
8384 ITypeComp_fnBindType
8387 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8388 REFIID riid
, void **object
)
8390 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8392 return ITypeLib2_QueryInterface((ITypeLib2
*)This
, riid
, object
);
8395 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8397 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8399 return ITypeLib2_AddRef((ITypeLib2
*)This
);
8402 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8404 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8406 return ITypeLib2_Release((ITypeLib2
*)This
);
8409 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8410 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8412 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8413 ITypeInfoImpl
*info
;
8416 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8418 if (!ctinfo
|| !name
)
8419 return E_INVALIDARG
;
8421 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8423 return TYPE_E_NAMECONFLICT
;
8425 if (This
->typeinfos
)
8426 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8427 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8429 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8431 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8433 info
->pTypeLib
= This
;
8434 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8435 info
->index
= This
->TypeInfoCount
;
8436 info
->typekind
= kind
;
8437 info
->cbAlignment
= 4;
8439 switch(info
->typekind
) {
8441 case TKIND_INTERFACE
:
8442 case TKIND_DISPATCH
:
8444 info
->cbSizeInstance
= 4;
8448 info
->cbSizeInstance
= 0;
8451 info
->cbSizeInstance
= 2;
8454 info
->cbSizeInstance
= -0x75;
8457 FIXME("unrecognized typekind %d\n", info
->typekind
);
8458 info
->cbSizeInstance
= 0xdeadbeef;
8462 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8463 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8465 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8469 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8471 ++This
->TypeInfoCount
;
8476 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8479 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8481 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8484 return E_INVALIDARG
;
8486 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8491 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8492 WORD majorVerNum
, WORD minorVerNum
)
8494 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8496 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8498 This
->ver_major
= majorVerNum
;
8499 This
->ver_minor
= minorVerNum
;
8504 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8507 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8509 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8511 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
);
8516 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8519 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8521 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8524 return E_INVALIDARG
;
8526 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8531 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8532 LPOLESTR helpFileName
)
8534 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8536 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8539 return E_INVALIDARG
;
8541 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8546 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8549 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8551 TRACE("%p %d\n", This
, helpContext
);
8553 This
->dwHelpContext
= helpContext
;
8558 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8561 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8563 TRACE("%p %x\n", This
, lcid
);
8565 This
->set_lcid
= lcid
;
8570 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8573 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8575 TRACE("%p %x\n", This
, libFlags
);
8577 This
->libflags
= libFlags
;
8582 typedef struct tagWMSFT_SegContents
{
8585 } WMSFT_SegContents
;
8587 typedef struct tagWMSFT_TLBFile
{
8589 WMSFT_SegContents typeinfo_seg
;
8590 WMSFT_SegContents impfile_seg
;
8591 WMSFT_SegContents impinfo_seg
;
8592 WMSFT_SegContents ref_seg
;
8593 WMSFT_SegContents lib_seg
;
8594 WMSFT_SegContents guid_seg
;
8595 WMSFT_SegContents res07_seg
;
8596 WMSFT_SegContents name_seg
;
8597 WMSFT_SegContents string_seg
;
8598 WMSFT_SegContents typdesc_seg
;
8599 WMSFT_SegContents arraydesc_seg
;
8600 WMSFT_SegContents custdata_seg
;
8601 WMSFT_SegContents cdguids_seg
;
8603 WMSFT_SegContents aux_seg
;
8606 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8607 WMSFT_TLBFile
*file
)
8613 file
->string_seg
.len
= 0;
8614 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8617 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8619 return E_UNEXPECTED
;
8621 size
+= sizeof(INT16
);
8623 size
= (size
+ 4) & ~0x3;
8627 file
->string_seg
.len
+= size
;
8629 /* temporarily use str->offset to store the length of the aligned,
8630 * converted string */
8634 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8637 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8640 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8641 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8643 heap_free(file
->string_seg
.data
);
8644 return E_UNEXPECTED
;
8647 *((INT16
*)data
) = size
;
8649 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8653 str
->offset
= last_offs
;
8660 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8661 WMSFT_TLBFile
*file
)
8666 MSFT_NameIntro
*last_intro
= NULL
;
8668 file
->header
.nametablecount
= 0;
8669 file
->header
.nametablechars
= 0;
8671 file
->name_seg
.len
= 0;
8672 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8675 size
= strlenW(str
->str
);
8676 file
->header
.nametablechars
+= size
;
8677 file
->header
.nametablecount
++;
8679 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8681 return E_UNEXPECTED
;
8683 size
+= sizeof(MSFT_NameIntro
);
8685 size
= (size
+ 4) & ~0x3;
8689 file
->name_seg
.len
+= size
;
8691 /* temporarily use str->offset to store the length of the aligned,
8692 * converted string */
8696 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
);
8699 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8701 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8703 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8704 data
+ sizeof(MSFT_NameIntro
),
8705 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8707 heap_free(file
->name_seg
.data
);
8708 return E_UNEXPECTED
;
8710 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8712 intro
->hreftype
= -1; /* TODO? */
8713 intro
->next_hash
= -1;
8714 intro
->namelen
= size
& 0xFF;
8715 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8716 intro
->namelen
|= LHashValOfNameSysA(This
->syskind
,
8717 This
->lcid
, data
+ sizeof(MSFT_NameIntro
)) << 16;
8719 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8720 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8722 /* update str->offset to actual value to use in other
8723 * compilation functions that require positions within
8724 * the string table */
8728 str
->offset
= last_offs
;
8733 last_intro
->hreftype
= 0; /* last one is 0? */
8738 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8741 MSFT_GuidEntry
*entry
;
8744 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8745 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8747 entry
= file
->guid_seg
.data
;
8749 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
8750 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
8751 entry
->hreftype
= 0xFFFFFFFF; /* TODO */
8752 entry
->next_hash
= 0xFFFFFFFF; /* TODO? */
8754 guid
->offset
= offs
;
8756 offs
+= sizeof(MSFT_GuidEntry
);
8761 entry
->next_hash
= 0; /* last one has 0? */
8766 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
8769 VARTYPE arg_type
= V_VT(value
);
8772 DWORD ret
= file
->custdata_seg
.len
;
8774 if(arg_type
== VT_INT
)
8776 if(arg_type
== VT_UINT
)
8780 if(V_VT(value
) != arg_type
) {
8781 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
8783 ERR("VariantChangeType failed: %08x\n", hres
);
8788 /* Check if default value can be stored in-place */
8793 if(V_UI4(&v
) > 0x3ffffff)
8806 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
8809 /* have to allocate space in custdata_seg */
8818 /* Construct the data to be allocated */
8821 if(file
->custdata_seg
.data
){
8822 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
8823 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
8824 file
->custdata_seg
.len
+= sizeof(int) * 2;
8826 file
->custdata_seg
.len
= sizeof(int) * 2;
8827 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
8830 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
8831 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
8833 /* TODO: Check if the encoded data is already present in custdata_seg */
8839 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
8842 if(file
->custdata_seg
.data
){
8843 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
8844 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
8845 file
->custdata_seg
.len
+= len
;
8847 file
->custdata_seg
.len
= len
;
8848 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
8851 *((unsigned short *)data
) = V_VT(value
);
8852 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
8853 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
8854 if(V_BSTR(&v
)[i
] <= 0x7f)
8855 data
[i
+6] = V_BSTR(&v
)[i
];
8859 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
8860 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
8863 /* TODO: Check if the encoded data is already present in custdata_seg */
8868 FIXME("Argument type not yet handled\n");
8873 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
8875 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
8877 DWORD offs
= file
->arraydesc_seg
.len
;
8881 /* TODO: we should check for duplicates, but that's harder because each
8882 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8883 * at the library-level) */
8885 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
8886 if(!file
->arraydesc_seg
.data
)
8887 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
8889 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
8890 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
8892 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
8893 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
8894 for(i
= 0; i
< desc
->cDims
; ++i
){
8895 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
8896 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
8902 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
8908 VARTYPE vt
= desc
->vt
& VT_TYPEMASK
, subtype
;
8949 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
8952 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
8954 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
8955 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
8957 *out_size
+= 2 * sizeof(DWORD
);
8958 }else if(vt
== VT_CARRAY
){
8959 encoded
[0] = desc
->vt
| (0x7FFE << 16);
8960 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
8962 }else if(vt
== VT_USERDEFINED
){
8963 encoded
[0] = desc
->vt
| (0x7FFF << 16);
8964 encoded
[1] = desc
->u
.hreftype
;
8965 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
8967 FIXME("Don't know what to do! VT: 0x%x\n", desc
->vt
);
8968 *out_mix
= desc
->vt
;
8969 return 0x80000000 | (desc
->vt
<< 16) | desc
->vt
;
8972 data
= file
->typdesc_seg
.data
;
8973 while(offs
< file
->typdesc_seg
.len
){
8974 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
8976 offs
+= sizeof(encoded
);
8979 file
->typdesc_seg
.len
+= sizeof(encoded
);
8980 if(!file
->typdesc_seg
.data
)
8981 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
8983 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
8985 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
8990 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
8992 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
8993 DWORD ret
= cdguids_seg
->len
, offs
;
8994 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
8997 if(list_empty(custdata_list
))
9000 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9001 if(!cdguids_seg
->data
){
9002 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9004 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9006 offs
= ret
+ sizeof(MSFT_CDGuid
);
9007 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9008 cdguid
->GuidOffset
= cd
->guid
->offset
;
9009 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9010 cdguid
->next
= offs
;
9011 offs
+= sizeof(MSFT_CDGuid
);
9021 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9022 WMSFT_TLBFile
*file
)
9024 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9025 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9026 MSFT_VarRecord
*varrecord
;
9027 MSFT_FuncRecord
*funcrecord
;
9029 DWORD
*name
, *offsets
, offs
;
9031 for(i
= 0; i
< info
->cFuncs
; ++i
){
9032 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9034 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9036 /* optional fields */
9037 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9038 if(!list_empty(&desc
->custdata_list
))
9039 recorded_size
+= 7 * sizeof(INT
);
9040 else if(desc
->HelpStringContext
!= 0)
9041 recorded_size
+= 6 * sizeof(INT
);
9043 else if(desc
->Entry
)
9044 recorded_size
+= 3 * sizeof(INT
);
9045 else if(desc
->HelpString
)
9046 recorded_size
+= 2 * sizeof(INT
);
9047 else if(desc
->helpcontext
)
9048 recorded_size
+= sizeof(INT
);
9050 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9052 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9053 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9054 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9059 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9062 for(i
= 0; i
< info
->cVars
; ++i
){
9063 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9065 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9067 /* optional fields */
9068 if(desc
->HelpStringContext
!= 0)
9069 recorded_size
+= 5 * sizeof(INT
);
9070 else if(!list_empty(&desc
->custdata_list
))
9071 recorded_size
+= 4 * sizeof(INT
);
9073 else if(desc
->HelpString
)
9074 recorded_size
+= 2 * sizeof(INT
);
9075 else if(desc
->HelpContext
!= 0)
9076 recorded_size
+= sizeof(INT
);
9078 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9081 if(!recorded_size
&& !extra_size
)
9084 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9086 aux_seg
->len
+= recorded_size
+ extra_size
;
9088 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9091 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9093 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9095 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9097 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9100 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9101 for(i
= 0; i
< info
->cFuncs
; ++i
){
9102 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9103 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9105 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9106 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9107 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9108 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9111 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9116 * ^has_param_defaults
9117 * ^oEntry_is_intresource
9119 funcrecord
->FKCCIC
=
9120 desc
->funcdesc
.funckind
|
9121 (desc
->funcdesc
.invkind
<< 3) |
9122 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9123 (desc
->funcdesc
.callconv
<< 8);
9125 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9126 funcrecord
->FKCCIC
|= 0x2000;
9128 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9129 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9130 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9131 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9134 if(paramdefault_size
> 0)
9135 funcrecord
->FKCCIC
|= 0x1000;
9137 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9138 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9140 /* optional fields */
9142 if(!list_empty(&desc
->custdata_list
)){
9143 size
+= 7 * sizeof(INT
);
9144 funcrecord
->HelpContext
= desc
->helpcontext
;
9145 if(desc
->HelpString
)
9146 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9148 funcrecord
->oHelpString
= -1;
9150 funcrecord
->oEntry
= -1;
9151 else if(IS_INTRESOURCE(desc
->Entry
))
9152 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9154 funcrecord
->oEntry
= desc
->Entry
->offset
;
9155 funcrecord
->res9
= -1;
9156 funcrecord
->resA
= -1;
9157 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9158 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9159 }else if(desc
->HelpStringContext
!= 0){
9160 size
+= 6 * sizeof(INT
);
9161 funcrecord
->HelpContext
= desc
->helpcontext
;
9162 if(desc
->HelpString
)
9163 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9165 funcrecord
->oHelpString
= -1;
9167 funcrecord
->oEntry
= -1;
9168 else if(IS_INTRESOURCE(desc
->Entry
))
9169 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9171 funcrecord
->oEntry
= desc
->Entry
->offset
;
9172 funcrecord
->res9
= -1;
9173 funcrecord
->resA
= -1;
9174 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9175 }else if(desc
->Entry
){
9176 size
+= 3 * sizeof(INT
);
9177 funcrecord
->HelpContext
= desc
->helpcontext
;
9178 if(desc
->HelpString
)
9179 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9181 funcrecord
->oHelpString
= -1;
9183 funcrecord
->oEntry
= -1;
9184 else if(IS_INTRESOURCE(desc
->Entry
))
9185 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9187 funcrecord
->oEntry
= desc
->Entry
->offset
;
9188 }else if(desc
->HelpString
){
9189 size
+= 2 * sizeof(INT
);
9190 funcrecord
->HelpContext
= desc
->helpcontext
;
9191 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9192 }else if(desc
->helpcontext
){
9193 size
+= sizeof(INT
);
9194 funcrecord
->HelpContext
= desc
->helpcontext
;
9197 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9198 size
+= paramdefault_size
;
9200 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9201 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9203 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9204 if(desc
->pParamDesc
[j
].Name
)
9205 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9208 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9210 if(paramdefault_size
){
9211 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9212 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9213 else if(paramdefault_size
)
9218 size
+= sizeof(MSFT_ParameterInfo
);
9221 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9227 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9230 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9231 for(i
= 0; i
< info
->cVars
; ++i
){
9232 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9233 DWORD size
= 5 * sizeof(INT
);
9235 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9236 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9237 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9238 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9240 if(desc
->vardesc
.varkind
== VAR_CONST
){
9241 varrecord
->vardescsize
+= sizeof(VARIANT
);
9242 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9244 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9247 if(desc
->HelpStringContext
!= 0){
9248 size
+= 5 * sizeof(INT
);
9249 varrecord
->HelpContext
= desc
->HelpContext
;
9250 if(desc
->HelpString
)
9251 varrecord
->HelpString
= desc
->HelpString
->offset
;
9253 varrecord
->HelpString
= -1;
9254 varrecord
->res9
= -1;
9255 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9256 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9257 }else if(!list_empty(&desc
->custdata_list
)){
9258 size
+= 4 * sizeof(INT
);
9259 varrecord
->HelpContext
= desc
->HelpContext
;
9260 if(desc
->HelpString
)
9261 varrecord
->HelpString
= desc
->HelpString
->offset
;
9263 varrecord
->HelpString
= -1;
9264 varrecord
->res9
= -1;
9265 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9266 }else if(desc
->HelpString
){
9267 size
+= 2 * sizeof(INT
);
9268 varrecord
->HelpContext
= desc
->HelpContext
;
9269 if(desc
->HelpString
)
9270 varrecord
->HelpString
= desc
->HelpString
->offset
;
9272 varrecord
->HelpString
= -1;
9273 }else if(desc
->HelpContext
!= 0){
9274 size
+= sizeof(INT
);
9275 varrecord
->HelpContext
= desc
->HelpContext
;
9278 varrecord
->Info
= size
| (i
<< 16);
9284 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9287 memid
= (MEMBERID
*)varrecord
;
9288 for(i
= 0; i
< info
->cFuncs
; ++i
){
9289 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9290 *memid
= desc
->funcdesc
.memid
;
9293 for(i
= 0; i
< info
->cVars
; ++i
){
9294 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9295 *memid
= desc
->vardesc
.memid
;
9299 name
= (UINT
*)memid
;
9300 for(i
= 0; i
< info
->cFuncs
; ++i
){
9301 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9303 *name
= desc
->Name
->offset
;
9308 for(i
= 0; i
< info
->cVars
; ++i
){
9309 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9311 *name
= desc
->Name
->offset
;
9320 typedef struct tagWMSFT_RefChunk
{
9327 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9329 DWORD offs
= file
->ref_seg
.len
, i
;
9330 WMSFT_RefChunk
*chunk
;
9332 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9333 if(!file
->ref_seg
.data
)
9334 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9336 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9338 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9340 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9341 chunk
->href
= info
->impltypes
[i
].hRef
;
9342 chunk
->res04
= info
->impltypes
[i
].implflags
;
9344 if(i
< info
->cImplTypes
- 1)
9345 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9354 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9358 size
= sizeof(MSFT_TypeInfoBase
);
9361 MSFT_TypeInfoBase
*base
= (void*)data
;
9362 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9363 base
->typekind
= TKIND_DISPATCH
;
9365 base
->typekind
= info
->typekind
;
9366 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9367 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9368 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9373 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9379 base
->posguid
= info
->guid
->offset
;
9382 base
->flags
= info
->wTypeFlags
;
9384 base
->NameOffset
= info
->Name
->offset
;
9386 base
->NameOffset
= -1;
9387 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9389 base
->docstringoffs
= info
->DocString
->offset
;
9391 base
->docstringoffs
= -1;
9392 base
->helpstringcontext
= info
->dwHelpStringContext
;
9393 base
->helpcontext
= info
->dwHelpContext
;
9394 base
->oCustData
= WMSFT_compile_custdata(&info
->custdata_list
, file
);
9395 base
->cImplTypes
= info
->cImplTypes
;
9396 base
->cbSizeVft
= info
->cbSizeVft
;
9397 base
->size
= info
->cbSizeInstance
;
9398 if(info
->typekind
== TKIND_COCLASS
){
9399 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9400 }else if(info
->typekind
== TKIND_ALIAS
){
9401 base
->datatype1
= WMSFT_append_typedesc(&info
->tdescAlias
, file
, NULL
, NULL
);
9402 }else if(info
->typekind
== TKIND_MODULE
){
9404 base
->datatype1
= info
->DllName
->offset
;
9406 base
->datatype1
= -1;
9408 if(info
->cImplTypes
> 0)
9409 base
->datatype1
= info
->impltypes
[0].hRef
;
9411 base
->datatype1
= -1;
9413 base
->datatype2
= index
; /* FIXME: i think there's more here */
9421 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9425 file
->typeinfo_seg
.len
= 0;
9426 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9427 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9428 *junk
= file
->typeinfo_seg
.len
;
9430 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9433 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9434 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9436 file
->aux_seg
.len
= 0;
9437 file
->aux_seg
.data
= NULL
;
9439 file
->typeinfo_seg
.len
= 0;
9440 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9441 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9442 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9443 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9447 typedef struct tagWMSFT_ImpFile
{
9453 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9456 WMSFT_ImpFile
*impfile
;
9458 DWORD last_offs
= 0;
9460 file
->impfile_seg
.len
= 0;
9461 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9465 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9469 path
= implib
->name
;
9470 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9472 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9475 size
+= sizeof(INT16
);
9477 size
= (size
+ 4) & ~0x3;
9481 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9484 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9486 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9487 int strlen
= 0, size
;
9489 impfile
= (WMSFT_ImpFile
*)data
;
9490 impfile
->guid_offs
= implib
->guid
->offset
;
9491 impfile
->lcid
= implib
->lcid
;
9492 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9494 data
+= sizeof(WMSFT_ImpFile
);
9497 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9501 path
= implib
->name
;
9502 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9503 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9505 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9508 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9510 size
= strlen
+ sizeof(INT16
);
9512 size
= (size
+ 4) & ~0x3;
9515 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9518 implib
->offset
= last_offs
;
9519 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9523 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9526 TLBRefType
*ref_type
;
9529 WMSFT_compile_impfile(This
, file
);
9531 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9532 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9534 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9535 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9536 if(ref_type
->index
== TLB_REF_USE_GUID
){
9537 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9538 info
->oGuid
= ref_type
->guid
->offset
;
9540 info
->oGuid
= ref_type
->index
;
9541 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9547 static void WMSFT_compile_lib(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9549 /* TODO: What actually goes here? */
9550 file
->lib_seg
.len
= 0x80;
9551 file
->lib_seg
.data
= heap_alloc(file
->lib_seg
.len
);
9552 memset(file
->lib_seg
.data
, 0xFF, file
->lib_seg
.len
);
9555 /* sometimes, first element is offset to last guid, for some reason */
9557 *(DWORD
*)file
->lib_seg
.data
=
9558 (list_count(&This
->guid_list
) - 1) * sizeof(MSFT_GuidEntry
);
9562 static void WMSFT_compile_res07(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9564 /* TODO: What actually goes here?
9566 * It's something to do with the Name table (and string table?). When you
9567 * add a new name, the offset to that name from within the Name table gets
9568 * stuck somewhere in res07, apparently starting at the end of the segment
9569 * then moving backwards at a rate of 3 bytes per char in the Name. */
9570 file
->res07_seg
.len
= 0x200;
9571 file
->res07_seg
.data
= heap_alloc(file
->res07_seg
.len
);
9572 memset(file
->res07_seg
.data
, 0xFF, file
->res07_seg
.len
);
9575 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9577 if(contents
&& contents
->len
){
9578 segdir
->offset
= *running_offset
;
9579 segdir
->length
= contents
->len
;
9580 *running_offset
+= segdir
->length
;
9582 segdir
->offset
= -1;
9586 /* TODO: do these ever change? */
9588 segdir
->res0c
= 0xf;
9591 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9595 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9598 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9602 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9604 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9605 base
->memoffset
+= file_len
;
9612 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9614 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9615 HeapFree(GetProcessHeap(), 0, file
->lib_seg
.data
);
9616 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9617 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9618 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9619 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9620 HeapFree(GetProcessHeap(), 0, file
->res07_seg
.data
);
9621 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9622 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9623 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9624 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9625 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9626 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9627 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9630 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9632 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9634 DWORD written
, junk_size
, junk_offs
, running_offset
;
9640 TRACE("%p\n", This
);
9642 memset(&file
, 0, sizeof(file
));
9644 file
.header
.magic1
= 0x5446534D;
9645 file
.header
.magic2
= 0x00010002;
9646 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9647 file
.header
.lcid2
= This
->set_lcid
;
9648 file
.header
.varflags
= 0x41; /* TODO?? */
9650 file
.header
.varflags
|= 0x10;
9651 if (This
->HelpStringDll
)
9652 file
.header
.varflags
|= HELPDLLFLAG
;
9653 file
.header
.version
= (This
->ver_major
<< 16) | This
->ver_minor
;
9654 file
.header
.flags
= This
->libflags
;
9655 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9656 file
.header
.helpcontext
= This
->dwHelpContext
;
9657 file
.header
.res44
= 0x20;
9658 file
.header
.res48
= 0x80;
9659 file
.header
.dispatchpos
= This
->dispatch_href
;
9661 /* do name and string compilation to get offsets for other compilations */
9662 hres
= WMSFT_compile_names(This
, &file
);
9664 WMSFT_free_file(&file
);
9668 hres
= WMSFT_compile_strings(This
, &file
);
9670 WMSFT_free_file(&file
);
9674 hres
= WMSFT_compile_guids(This
, &file
);
9676 WMSFT_free_file(&file
);
9681 file
.header
.helpfile
= This
->HelpFile
->offset
;
9683 file
.header
.helpfile
= -1;
9686 file
.header
.helpstring
= This
->DocString
->offset
;
9688 file
.header
.helpstring
= -1;
9690 /* do some more segment compilation */
9691 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9692 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9695 file
.header
.NameOffset
= This
->Name
->offset
;
9697 file
.header
.NameOffset
= -1;
9699 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9702 file
.header
.posguid
= This
->guid
->offset
;
9704 file
.header
.posguid
= -1;
9706 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9707 if(file
.header
.varflags
& HELPDLLFLAG
)
9708 junk_size
+= sizeof(DWORD
);
9710 junk
= heap_alloc_zero(junk_size
);
9711 if(file
.header
.varflags
& HELPDLLFLAG
){
9712 *junk
= This
->HelpStringDll
->offset
;
9721 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9722 WMSFT_compile_impinfo(This
, &file
);
9723 WMSFT_compile_lib(This
, &file
);
9724 WMSFT_compile_res07(This
, &file
);
9728 TRACE("header at: 0x%x\n", running_offset
);
9729 running_offset
+= sizeof(file
.header
);
9731 TRACE("junk at: 0x%x\n", running_offset
);
9732 running_offset
+= junk_size
;
9734 TRACE("segdir at: 0x%x\n", running_offset
);
9735 running_offset
+= sizeof(file
.segdir
);
9737 TRACE("typeinfo at: 0x%x\n", running_offset
);
9738 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9740 TRACE("libtab at: 0x%x\n", running_offset
);
9741 tmp_fill_segdir_seg(&file
.segdir
.pLibtab
, &file
.lib_seg
, &running_offset
);
9743 TRACE("guidtab at: 0x%x\n", running_offset
);
9744 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9746 TRACE("reftab at: 0x%x\n", running_offset
);
9747 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9749 TRACE("impinfo at: 0x%x\n", running_offset
);
9750 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9752 TRACE("impfiles at: 0x%x\n", running_offset
);
9753 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9755 TRACE("res07 at: 0x%x\n", running_offset
);
9756 tmp_fill_segdir_seg(&file
.segdir
.res07
, &file
.res07_seg
, &running_offset
);
9758 TRACE("nametab at: 0x%x\n", running_offset
);
9759 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9761 TRACE("stringtab at: 0x%x\n", running_offset
);
9762 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9764 TRACE("typdesc at: 0x%x\n", running_offset
);
9765 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
9767 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
9768 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
9770 TRACE("custdata at: 0x%x\n", running_offset
);
9771 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
9773 TRACE("cdguids at: 0x%x\n", running_offset
);
9774 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
9776 TRACE("res0e at: 0x%x\n", running_offset
);
9777 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
9779 TRACE("res0f at: 0x%x\n", running_offset
);
9780 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
9782 TRACE("aux_seg at: 0x%x\n", running_offset
);
9784 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
9786 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
9787 FILE_ATTRIBUTE_NORMAL
, 0);
9788 if (outfile
== INVALID_HANDLE_VALUE
){
9789 WMSFT_free_file(&file
);
9790 return TYPE_E_IOERROR
;
9793 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
9795 WMSFT_free_file(&file
);
9796 CloseHandle(outfile
);
9797 return TYPE_E_IOERROR
;
9800 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
9802 WMSFT_free_file(&file
);
9803 CloseHandle(outfile
);
9804 return TYPE_E_IOERROR
;
9807 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
9809 WMSFT_free_file(&file
);
9810 CloseHandle(outfile
);
9811 return TYPE_E_IOERROR
;
9814 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
9815 WMSFT_write_segment(outfile
, &file
.lib_seg
);
9816 WMSFT_write_segment(outfile
, &file
.guid_seg
);
9817 WMSFT_write_segment(outfile
, &file
.ref_seg
);
9818 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
9819 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
9820 WMSFT_write_segment(outfile
, &file
.res07_seg
);
9821 WMSFT_write_segment(outfile
, &file
.name_seg
);
9822 WMSFT_write_segment(outfile
, &file
.string_seg
);
9823 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
9824 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
9825 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
9826 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
9827 WMSFT_write_segment(outfile
, &file
.aux_seg
);
9829 WMSFT_free_file(&file
);
9831 CloseHandle(outfile
);
9836 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
9839 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9840 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
9844 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
9845 REFGUID guid
, VARIANT
*varVal
)
9847 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9848 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
9852 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
9853 ULONG helpStringContext
)
9855 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9856 FIXME("%p %u - stub\n", This
, helpStringContext
);
9860 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
9863 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9864 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
9867 return E_INVALIDARG
;
9869 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
9874 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
9875 ICreateTypeLib2_fnQueryInterface
,
9876 ICreateTypeLib2_fnAddRef
,
9877 ICreateTypeLib2_fnRelease
,
9878 ICreateTypeLib2_fnCreateTypeInfo
,
9879 ICreateTypeLib2_fnSetName
,
9880 ICreateTypeLib2_fnSetVersion
,
9881 ICreateTypeLib2_fnSetGuid
,
9882 ICreateTypeLib2_fnSetDocString
,
9883 ICreateTypeLib2_fnSetHelpFileName
,
9884 ICreateTypeLib2_fnSetHelpContext
,
9885 ICreateTypeLib2_fnSetLcid
,
9886 ICreateTypeLib2_fnSetLibFlags
,
9887 ICreateTypeLib2_fnSaveAllChanges
,
9888 ICreateTypeLib2_fnDeleteTypeInfo
,
9889 ICreateTypeLib2_fnSetCustData
,
9890 ICreateTypeLib2_fnSetHelpStringContext
,
9891 ICreateTypeLib2_fnSetHelpStringDll
9894 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
9895 REFIID riid
, void **object
)
9897 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9899 return ITypeInfo2_QueryInterface((ITypeInfo2
*)This
, riid
, object
);
9902 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
9904 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9906 return ITypeInfo2_AddRef((ITypeInfo2
*)This
);
9909 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
9911 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9913 return ITypeInfo2_Release((ITypeInfo2
*)This
);
9916 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
9919 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9921 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9923 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
);
9928 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
9931 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9935 TRACE("%p %x\n", This
, typeFlags
);
9937 if (typeFlags
& TYPEFLAG_FDUAL
) {
9938 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9940 ITypeInfo
*dispatch
;
9944 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
9948 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
9949 ITypeLib_Release(stdole
);
9953 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
9954 ITypeInfo_Release(dispatch
);
9959 old_flags
= This
->wTypeFlags
;
9960 This
->wTypeFlags
= typeFlags
;
9962 hres
= ICreateTypeInfo2_LayOut(iface
);
9964 This
->wTypeFlags
= old_flags
;
9971 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
9974 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9976 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9979 return E_INVALIDARG
;
9981 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
9986 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
9989 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9991 TRACE("%p %d\n", This
, helpContext
);
9993 This
->dwHelpContext
= helpContext
;
9998 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
9999 WORD majorVerNum
, WORD minorVerNum
)
10001 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10003 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10005 This
->wMajorVerNum
= majorVerNum
;
10006 This
->wMinorVerNum
= minorVerNum
;
10011 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10012 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10014 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10016 ITypeLib
*container
;
10017 TLBRefType
*ref_type
;
10019 TYPEATTR
*typeattr
;
10023 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10025 if (!typeInfo
|| !refType
)
10026 return E_INVALIDARG
;
10028 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10032 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10033 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10035 ITypeLib_Release(container
);
10037 *refType
= target
->hreftype
;
10042 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10043 if (FAILED(hres
)) {
10044 ITypeLib_Release(container
);
10048 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10049 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10050 implib
->lcid
== libattr
->lcid
&&
10051 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10052 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10056 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10057 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10059 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10060 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10061 implib
->name
= SysAllocString(our_container
->path
);
10063 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10064 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10066 implib
->name
= NULL
;
10067 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10071 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
);
10072 implib
->lcid
= libattr
->lcid
;
10073 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10074 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10076 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10079 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10080 ITypeLib_Release(container
);
10082 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10087 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10088 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10089 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10090 ref_type
->tkind
== typeattr
->typekind
)
10095 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10096 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10098 ref_type
->tkind
= typeattr
->typekind
;
10099 ref_type
->pImpTLInfo
= implib
;
10100 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10102 ref_type
->index
= TLB_REF_USE_GUID
;
10104 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
);
10106 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10109 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10111 *refType
= ref_type
->reference
| 0x1;
10113 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10114 This
->pTypeLib
->dispatch_href
= *refType
;
10119 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10120 UINT index
, FUNCDESC
*funcDesc
)
10122 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10123 TLBFuncDesc tmp_func_desc
, *func_desc
;
10128 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10130 if (!funcDesc
|| funcDesc
->oVft
& 3)
10131 return E_INVALIDARG
;
10133 switch (This
->typekind
) {
10135 if (funcDesc
->funckind
!= FUNC_STATIC
)
10136 return TYPE_E_BADMODULEKIND
;
10138 case TKIND_DISPATCH
:
10139 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10140 return TYPE_E_BADMODULEKIND
;
10143 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10144 return TYPE_E_BADMODULEKIND
;
10147 if (index
> This
->cFuncs
)
10148 return TYPE_E_ELEMENTNOTFOUND
;
10150 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10151 !funcDesc
->cParams
)
10152 return TYPE_E_INCONSISTENTPROPFUNCS
;
10154 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10155 TLBFuncDesc_Constructor(&tmp_func_desc
);
10157 tmp_func_desc
.funcdesc
= *funcDesc
;
10159 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10160 tmp_func_desc
.funcdesc
.oVft
|= 1;
10162 if (funcDesc
->cScodes
) {
10163 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10164 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10166 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10168 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10169 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10170 buf_size
+= sizeof(ELEMDESC
);
10171 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10173 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10174 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10176 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10177 if (FAILED(hres
)) {
10178 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10179 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10183 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10184 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10185 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10186 if (FAILED(hres
)) {
10187 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10188 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10191 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10192 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10193 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10194 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10195 if (FAILED(hres
)) {
10196 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10197 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10203 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10205 if (This
->funcdescs
) {
10206 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10207 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10209 if (index
< This
->cFuncs
) {
10210 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10211 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10212 func_desc
= This
->funcdescs
+ index
;
10214 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10216 /* move custdata lists to the new memory location */
10217 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10219 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10220 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10221 list_init(&fd
->custdata_list
);
10223 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10224 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10229 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10231 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10232 list_init(&func_desc
->custdata_list
);
10236 This
->needs_layout
= TRUE
;
10241 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10242 UINT index
, HREFTYPE refType
)
10244 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10245 TLBImplType
*impl_type
;
10248 TRACE("%p %u %d\n", This
, index
, refType
);
10250 switch(This
->typekind
){
10251 case TKIND_COCLASS
: {
10253 FIXME("Unhandled index: -1\n");
10257 if(index
!= This
->cImplTypes
)
10258 return TYPE_E_ELEMENTNOTFOUND
;
10262 case TKIND_INTERFACE
:
10263 case TKIND_DISPATCH
:
10264 if (index
!= 0 || This
->cImplTypes
)
10265 return TYPE_E_ELEMENTNOTFOUND
;
10268 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10272 if (This
->impltypes
){
10275 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10276 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10278 if (index
< This
->cImplTypes
) {
10279 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10280 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10281 impl_type
= This
->impltypes
+ index
;
10283 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10285 /* move custdata lists to the new memory location */
10286 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10288 TLBImplType
*it
= &This
->impltypes
[i
];
10289 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10290 list_init(&it
->custdata_list
);
10292 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10293 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10298 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10300 memset(impl_type
, 0, sizeof(TLBImplType
));
10301 TLBImplType_Constructor(impl_type
);
10302 impl_type
->hRef
= refType
;
10304 ++This
->cImplTypes
;
10306 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10307 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10309 hres
= ICreateTypeInfo2_LayOut(iface
);
10316 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10317 UINT index
, INT implTypeFlags
)
10319 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10320 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10322 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10324 if (This
->typekind
!= TKIND_COCLASS
)
10325 return TYPE_E_BADMODULEKIND
;
10327 if (index
>= This
->cImplTypes
)
10328 return TYPE_E_ELEMENTNOTFOUND
;
10330 impl_type
->implflags
= implTypeFlags
;
10335 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10338 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10340 TRACE("%p %d\n", This
, alignment
);
10342 This
->cbAlignment
= alignment
;
10347 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10350 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10352 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10355 return E_INVALIDARG
;
10357 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10359 This
->lpstrSchema
= This
->Schema
->str
;
10364 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10365 UINT index
, VARDESC
*varDesc
)
10367 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10368 TLBVarDesc
*var_desc
;
10370 TRACE("%p %u %p\n", This
, index
, varDesc
);
10372 if (This
->vardescs
){
10375 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10376 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10378 if (index
< This
->cVars
) {
10379 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10380 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10381 var_desc
= This
->vardescs
+ index
;
10383 var_desc
= This
->vardescs
+ This
->cVars
;
10385 /* move custdata lists to the new memory location */
10386 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10388 TLBVarDesc
*var
= &This
->vardescs
[i
];
10389 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10390 list_init(&var
->custdata_list
);
10392 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10393 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10398 var_desc
= This
->vardescs
= heap_alloc(sizeof(TLBVarDesc
));
10400 memset(var_desc
, 0, sizeof(TLBVarDesc
));
10401 TLBVarDesc_Constructor(var_desc
);
10402 var_desc
->vardesc
= *varDesc
;
10406 This
->needs_layout
= TRUE
;
10411 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10412 UINT index
, LPOLESTR
*names
, UINT numNames
)
10414 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10415 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10418 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10421 return E_INVALIDARG
;
10423 if (index
>= This
->cFuncs
|| numNames
== 0)
10424 return TYPE_E_ELEMENTNOTFOUND
;
10426 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10427 if(numNames
> func_desc
->funcdesc
.cParams
)
10428 return TYPE_E_ELEMENTNOTFOUND
;
10430 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10431 return TYPE_E_ELEMENTNOTFOUND
;
10433 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10434 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10435 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10436 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10437 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10438 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10440 return TYPE_E_AMBIGUOUSNAME
;
10444 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10446 for (i
= 1; i
< numNames
; ++i
) {
10447 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10448 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10454 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10455 UINT index
, LPOLESTR name
)
10457 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10458 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(name
));
10462 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10463 TYPEDESC
*tdescAlias
)
10465 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10466 FIXME("%p %p - stub\n", This
, tdescAlias
);
10470 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10471 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10473 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10474 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10478 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10479 UINT index
, LPOLESTR docString
)
10481 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10482 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
10486 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10487 UINT index
, LPOLESTR docString
)
10489 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10490 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10492 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10495 return E_INVALIDARG
;
10497 if(index
>= This
->cVars
)
10498 return TYPE_E_ELEMENTNOTFOUND
;
10500 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10505 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10506 UINT index
, DWORD helpContext
)
10508 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10509 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10511 TRACE("%p %u %d\n", This
, index
, helpContext
);
10513 if(index
>= This
->cFuncs
)
10514 return TYPE_E_ELEMENTNOTFOUND
;
10516 func_desc
->helpcontext
= helpContext
;
10521 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10522 UINT index
, DWORD helpContext
)
10524 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10525 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10527 TRACE("%p %u %d\n", This
, index
, helpContext
);
10529 if(index
>= This
->cVars
)
10530 return TYPE_E_ELEMENTNOTFOUND
;
10532 var_desc
->HelpContext
= helpContext
;
10537 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10538 UINT index
, BSTR bstrMops
)
10540 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10541 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10545 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10548 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10550 TRACE("%p %p\n", This
, idlDesc
);
10553 return E_INVALIDARG
;
10555 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10556 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10561 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10563 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10565 TLBFuncDesc
*func_desc
;
10566 UINT user_vft
= 0, i
, depth
= 0;
10567 HRESULT hres
= S_OK
;
10569 TRACE("%p\n", This
);
10571 This
->needs_layout
= FALSE
;
10573 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10577 if (This
->typekind
== TKIND_INTERFACE
) {
10582 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10584 if (SUCCEEDED(hres
)) {
10585 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10587 if (SUCCEEDED(hres
)) {
10588 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10589 if (FAILED(hres
)) {
10590 ITypeInfo_Release(inh
);
10591 ITypeInfo_Release(tinfo
);
10594 This
->cbSizeVft
= attr
->cbSizeVft
* 4 / sizeof(void*);
10595 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10599 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10600 if(SUCCEEDED(hres
)){
10602 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10603 if(SUCCEEDED(hres
)){
10604 ITypeInfo_Release(inh
);
10608 }while(SUCCEEDED(hres
));
10611 ITypeInfo_Release(inh
);
10612 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10613 This
->cbSizeVft
= 0;
10616 ITypeInfo_Release(tinfo
);
10619 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10620 This
->cbSizeVft
= 0;
10623 ITypeInfo_Release(tinfo
);
10626 } else if (This
->typekind
== TKIND_DISPATCH
)
10627 This
->cbSizeVft
= 7 * sizeof(void*);
10629 This
->cbSizeVft
= 0;
10631 func_desc
= This
->funcdescs
;
10633 while (i
< This
->cFuncs
) {
10634 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10635 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10637 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10638 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10640 This
->cbSizeVft
+= sizeof(void*);
10642 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10645 BOOL reset
= FALSE
;
10647 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10649 iter
= This
->funcdescs
;
10650 while (j
< This
->cFuncs
) {
10651 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10653 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10656 ++func_desc
->funcdesc
.memid
;
10657 iter
= This
->funcdescs
;
10670 if (user_vft
> This
->cbSizeVft
)
10671 This
->cbSizeVft
= user_vft
+ sizeof(void*);
10673 ITypeInfo_Release(tinfo
);
10677 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10680 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10681 FIXME("%p %u - stub\n", This
, index
);
10685 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
10686 MEMBERID memid
, INVOKEKIND invKind
)
10688 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10689 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
10693 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
10696 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10697 FIXME("%p %u - stub\n", This
, index
);
10701 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
10704 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10705 FIXME("%p %x - stub\n", This
, memid
);
10709 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
10712 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10713 FIXME("%p %u - stub\n", This
, index
);
10717 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
10718 REFGUID guid
, VARIANT
*varVal
)
10722 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10724 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10726 if (!guid
|| !varVal
)
10727 return E_INVALIDARG
;
10729 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
);
10731 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10734 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
10735 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10737 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10738 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10742 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
10743 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
10745 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10746 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
10750 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
10751 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10753 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10754 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10758 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
10759 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10761 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10762 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10766 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
10767 ULONG helpStringContext
)
10769 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10771 TRACE("%p %u\n", This
, helpStringContext
);
10773 This
->dwHelpStringContext
= helpStringContext
;
10778 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
10779 UINT index
, ULONG helpStringContext
)
10781 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10782 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
10786 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
10787 UINT index
, ULONG helpStringContext
)
10789 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10790 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
10794 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
10796 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10797 FIXME("%p - stub\n", This
);
10801 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
10804 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10806 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
10809 return E_INVALIDARG
;
10811 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10816 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
10817 ICreateTypeInfo2_fnQueryInterface
,
10818 ICreateTypeInfo2_fnAddRef
,
10819 ICreateTypeInfo2_fnRelease
,
10820 ICreateTypeInfo2_fnSetGuid
,
10821 ICreateTypeInfo2_fnSetTypeFlags
,
10822 ICreateTypeInfo2_fnSetDocString
,
10823 ICreateTypeInfo2_fnSetHelpContext
,
10824 ICreateTypeInfo2_fnSetVersion
,
10825 ICreateTypeInfo2_fnAddRefTypeInfo
,
10826 ICreateTypeInfo2_fnAddFuncDesc
,
10827 ICreateTypeInfo2_fnAddImplType
,
10828 ICreateTypeInfo2_fnSetImplTypeFlags
,
10829 ICreateTypeInfo2_fnSetAlignment
,
10830 ICreateTypeInfo2_fnSetSchema
,
10831 ICreateTypeInfo2_fnAddVarDesc
,
10832 ICreateTypeInfo2_fnSetFuncAndParamNames
,
10833 ICreateTypeInfo2_fnSetVarName
,
10834 ICreateTypeInfo2_fnSetTypeDescAlias
,
10835 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
10836 ICreateTypeInfo2_fnSetFuncDocString
,
10837 ICreateTypeInfo2_fnSetVarDocString
,
10838 ICreateTypeInfo2_fnSetFuncHelpContext
,
10839 ICreateTypeInfo2_fnSetVarHelpContext
,
10840 ICreateTypeInfo2_fnSetMops
,
10841 ICreateTypeInfo2_fnSetTypeIdldesc
,
10842 ICreateTypeInfo2_fnLayOut
,
10843 ICreateTypeInfo2_fnDeleteFuncDesc
,
10844 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
10845 ICreateTypeInfo2_fnDeleteVarDesc
,
10846 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
10847 ICreateTypeInfo2_fnDeleteImplType
,
10848 ICreateTypeInfo2_fnSetCustData
,
10849 ICreateTypeInfo2_fnSetFuncCustData
,
10850 ICreateTypeInfo2_fnSetParamCustData
,
10851 ICreateTypeInfo2_fnSetVarCustData
,
10852 ICreateTypeInfo2_fnSetImplTypeCustData
,
10853 ICreateTypeInfo2_fnSetHelpStringContext
,
10854 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
10855 ICreateTypeInfo2_fnSetVarHelpStringContext
,
10856 ICreateTypeInfo2_fnInvalidate
,
10857 ICreateTypeInfo2_fnSetName