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
);
2243 static int TLB_is_propgetput(INVOKEKIND invkind
)
2245 return (invkind
== INVOKE_PROPERTYGET
||
2246 invkind
== INVOKE_PROPERTYPUT
||
2247 invkind
== INVOKE_PROPERTYPUTREF
);
2251 MSFT_DoFuncs(TLBContext
* pcx
,
2256 TLBFuncDesc
** pptfd
)
2259 * member information is stored in a data structure at offset
2260 * indicated by the memoffset field of the typeinfo structure
2261 * There are several distinctive parts.
2262 * The first part starts with a field that holds the total length
2263 * of this (first) part excluding this field. Then follow the records,
2264 * for each member there is one record.
2266 * The first entry is always the length of the record (including this
2268 * The rest of the record depends on the type of the member. If there is
2269 * a field indicating the member type (function, variable, interface, etc)
2270 * I have not found it yet. At this time we depend on the information
2271 * in the type info and the usual order how things are stored.
2273 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2276 * Third is an equal sized array with file offsets to the name entry
2279 * The fourth and last (?) part is an array with offsets to the records
2280 * in the first part of this file segment.
2283 int infolen
, nameoffset
, reclength
, i
;
2284 int recoffset
= offset
+ sizeof(INT
);
2286 char *recbuf
= heap_alloc(0xffff);
2287 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2288 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2290 TRACE_(typelib
)("\n");
2292 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2294 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2296 for ( i
= 0; i
< cFuncs
; i
++ )
2300 /* name, eventually add to a hash table */
2301 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2302 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
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
);
2313 if (pFuncRec
->FKCCIC
& 0x1000)
2314 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2316 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2317 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2319 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2320 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2322 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2324 if (pFuncRec
->FKCCIC
& 0x2000 )
2326 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2327 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2328 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2331 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2334 ptfd
->Entry
= (TLBString
*)-1;
2336 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2337 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2339 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2340 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2342 /* fill the FuncDesc Structure */
2343 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2344 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2346 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2347 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2348 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2349 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2350 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2351 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2352 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2354 /* nameoffset is sometimes -1 on the second half of a propget/propput
2355 * pair of functions */
2356 if ((nameoffset
== -1) && (i
> 0) &&
2357 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2358 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2359 ptfd
->Name
= ptfd_prev
->Name
;
2361 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2365 &ptfd
->funcdesc
.elemdescFunc
.tdesc
,
2367 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2369 /* do the parameters/arguments */
2370 if(pFuncRec
->nrargs
)
2373 MSFT_ParameterInfo paraminfo
;
2375 ptfd
->funcdesc
.lprgelemdescParam
=
2376 heap_alloc_zero(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
2378 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2380 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2381 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2383 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2385 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2392 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2395 if (paraminfo
.oName
== -1)
2396 /* this occurs for [propput] or [propget] methods, so
2397 * we should just set the name of the parameter to the
2398 * name of the method. */
2399 ptfd
->pParamDesc
[j
].Name
= ptfd
->Name
;
2401 ptfd
->pParamDesc
[j
].Name
=
2402 MSFT_ReadName( pcx
, paraminfo
.oName
);
2403 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2405 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
2408 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2409 (pFuncRec
->FKCCIC
& 0x1000) )
2411 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2413 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2415 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2417 pParamDesc
->pparamdescex
= heap_alloc_zero(sizeof(PARAMDESCEX
));
2418 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2420 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2424 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2427 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2428 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2429 pFuncRec
->FKCCIC
& 0x80 )
2432 pFuncRec
->oArgCustData
[j
],
2433 &ptfd
->pParamDesc
[j
].custdata_list
);
2436 /* SEEK value = jump to offset,
2437 * from there jump to the end of record,
2438 * go back by (j-1) arguments
2440 MSFT_ReadLEDWords( ¶minfo
,
2441 sizeof(MSFT_ParameterInfo
), pcx
,
2442 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2443 * sizeof(MSFT_ParameterInfo
)));
2447 /* scode is not used: archaic win16 stuff FIXME: right? */
2448 ptfd
->funcdesc
.cScodes
= 0 ;
2449 ptfd
->funcdesc
.lprgscode
= NULL
;
2453 recoffset
+= reclength
;
2458 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2459 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2461 int infolen
, nameoffset
, reclength
;
2463 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2468 TRACE_(typelib
)("\n");
2470 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2471 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2472 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2473 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2474 recoffset
+= offset
+sizeof(INT
);
2475 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2476 /* name, eventually add to a hash table */
2477 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2478 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2479 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2480 /* read the variable information record */
2481 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2483 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2486 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2487 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2489 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2490 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2492 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2493 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2495 /* fill the VarDesc Structure */
2496 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2497 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2498 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2499 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2500 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2501 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2502 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2503 if(pVarRec
->VarKind
== VAR_CONST
){
2504 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2505 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2506 pVarRec
->OffsValue
, pcx
);
2508 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2509 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptvd
->vardesc
.elemdescVar
.tdesc
);
2510 recoffset
+= reclength
;
2514 /* fill in data for a hreftype (offset). When the referenced type is contained
2515 * in the typelib, it's just an (file) offset in the type info base dir.
2516 * If comes from import, it's an offset+1 in the ImpInfo table
2518 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2523 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2525 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2527 if(ref
->reference
== offset
) return;
2530 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2531 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2533 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2534 /* external typelib */
2535 MSFT_ImpInfo impinfo
;
2538 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2540 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2541 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2543 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2544 if(pImpLib
->offset
==impinfo
.oImpFile
)
2547 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2548 ref
->reference
= offset
& (~0x3);
2549 ref
->pImpTLInfo
= pImpLib
;
2550 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2551 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2552 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2553 ref
->index
= TLB_REF_USE_GUID
;
2555 ref
->index
= impinfo
.oGuid
;
2557 ERR("Cannot find a reference\n");
2558 ref
->reference
= -1;
2559 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2562 /* in this typelib */
2563 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2564 ref
->reference
= offset
;
2565 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2569 /* process Implemented Interfaces of a com class */
2570 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2574 MSFT_RefRecord refrec
;
2577 TRACE_(typelib
)("\n");
2579 pTI
->impltypes
= TLBImplType_Alloc(count
);
2580 pImpl
= pTI
->impltypes
;
2581 for(i
=0;i
<count
;i
++){
2582 if(offset
<0) break; /* paranoia */
2583 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2584 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2585 pImpl
->hRef
= refrec
.reftype
;
2586 pImpl
->implflags
=refrec
.flags
;
2587 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2588 offset
=refrec
.onext
;
2593 * process a typeinfo record
2595 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2598 ITypeLibImpl
* pLibInfo
)
2600 MSFT_TypeInfoBase tiBase
;
2601 ITypeInfoImpl
*ptiRet
;
2603 TRACE_(typelib
)("count=%u\n", count
);
2605 ptiRet
= ITypeInfoImpl_Constructor();
2606 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2607 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2609 /* this is where we are coming from */
2610 ptiRet
->pTypeLib
= pLibInfo
;
2611 ptiRet
->index
=count
;
2613 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2614 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2615 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2616 ptiRet
->cbSizeInstance
=tiBase
.size
;
2617 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2618 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2619 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2620 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2621 ptiRet
->wTypeFlags
=tiBase
.flags
;
2622 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2623 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2624 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2625 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2626 if(ptiRet
->typekind
== TKIND_ALIAS
)
2627 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2628 &ptiRet
->tdescAlias
, ptiRet
);
2631 /* IDLDESC idldescType; *//* never saw this one != zero */
2633 /* name, eventually add to a hash table */
2634 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2635 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2636 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2638 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2639 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2640 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2642 if (ptiRet
->typekind
== TKIND_MODULE
)
2643 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2645 /* note: InfoType's Help file and HelpStringDll come from the containing
2646 * library. Further HelpString and Docstring appear to be the same thing :(
2649 if(ptiRet
->cFuncs
>0 )
2650 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2652 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2654 if(ptiRet
->cVars
>0 )
2655 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2657 tiBase
.memoffset
, &ptiRet
->vardescs
);
2658 if(ptiRet
->cImplTypes
>0 ) {
2659 switch(ptiRet
->typekind
)
2662 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2665 case TKIND_DISPATCH
:
2666 /* This is not -1 when the interface is a non-base dual interface or
2667 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2668 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2672 if (tiBase
.datatype1
!= -1)
2674 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2675 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2676 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2680 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2681 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2682 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2686 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->custdata_list
);
2688 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2689 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2690 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2691 typekind_desc
[ptiRet
->typekind
]);
2692 if (TRACE_ON(typelib
))
2693 dump_TypeInfo(ptiRet
);
2698 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2701 INT16 len_str
, len_piece
;
2702 int offs
= 0, lengthInChars
;
2704 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2708 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2711 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2712 len_piece
= len_str
+ sizeof(INT16
);
2714 len_piece
= (len_piece
+ 4) & ~0x3;
2718 string
= heap_alloc(len_piece
+ 1);
2719 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2720 string
[len_str
] = '\0';
2722 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2723 string
, -1, NULL
, 0);
2724 if (!lengthInChars
) {
2726 return E_UNEXPECTED
;
2729 tlbstr
= heap_alloc(sizeof(TLBString
));
2731 tlbstr
->offset
= offs
;
2732 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2733 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2737 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2743 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2744 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2745 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2748 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2749 static CRITICAL_SECTION cache_section
;
2750 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2752 0, 0, &cache_section
,
2753 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2754 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2756 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2759 typedef struct TLB_PEFile
2761 IUnknown IUnknown_iface
;
2764 HRSRC typelib_resource
;
2765 HGLOBAL typelib_global
;
2766 LPVOID typelib_base
;
2769 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2771 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2774 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2776 if (IsEqualIID(riid
, &IID_IUnknown
))
2779 IUnknown_AddRef(iface
);
2783 return E_NOINTERFACE
;
2786 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2788 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2789 return InterlockedIncrement(&This
->refs
);
2792 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2794 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2795 ULONG refs
= InterlockedDecrement(&This
->refs
);
2798 if (This
->typelib_global
)
2799 FreeResource(This
->typelib_global
);
2801 FreeLibrary(This
->dll
);
2807 static const IUnknownVtbl TLB_PEFile_Vtable
=
2809 TLB_PEFile_QueryInterface
,
2814 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2817 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2819 This
= heap_alloc(sizeof(TLB_PEFile
));
2821 return E_OUTOFMEMORY
;
2823 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2826 This
->typelib_resource
= NULL
;
2827 This
->typelib_global
= NULL
;
2828 This
->typelib_base
= NULL
;
2830 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2831 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2835 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2836 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2837 if (This
->typelib_resource
)
2839 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2840 if (This
->typelib_global
)
2842 This
->typelib_base
= LockResource(This
->typelib_global
);
2844 if (This
->typelib_base
)
2846 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2847 *ppBase
= This
->typelib_base
;
2848 *ppFile
= &This
->IUnknown_iface
;
2854 TRACE("No TYPELIB resource found\n");
2858 TLB_PEFile_Release(&This
->IUnknown_iface
);
2862 typedef struct TLB_NEFile
2864 IUnknown IUnknown_iface
;
2866 LPVOID typelib_base
;
2869 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2871 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2874 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2876 if (IsEqualIID(riid
, &IID_IUnknown
))
2879 IUnknown_AddRef(iface
);
2883 return E_NOINTERFACE
;
2886 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2888 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2889 return InterlockedIncrement(&This
->refs
);
2892 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2894 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2895 ULONG refs
= InterlockedDecrement(&This
->refs
);
2898 heap_free(This
->typelib_base
);
2904 static const IUnknownVtbl TLB_NEFile_Vtable
=
2906 TLB_NEFile_QueryInterface
,
2911 /***********************************************************************
2912 * read_xx_header [internal]
2914 static int read_xx_header( HFILE lzfd
)
2916 IMAGE_DOS_HEADER mzh
;
2919 LZSeek( lzfd
, 0, SEEK_SET
);
2920 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2922 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2925 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2926 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2929 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2931 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2932 return IMAGE_OS2_SIGNATURE
;
2933 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2934 return IMAGE_NT_SIGNATURE
;
2937 WARN("Can't handle %s files.\n", magic
);
2942 /***********************************************************************
2943 * find_ne_resource [internal]
2945 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2946 DWORD
*resLen
, DWORD
*resOff
)
2948 IMAGE_OS2_HEADER nehd
;
2949 NE_TYPEINFO
*typeInfo
;
2950 NE_NAMEINFO
*nameInfo
;
2956 /* Read in NE header */
2957 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2958 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2960 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2963 TRACE("No resources in NE dll\n" );
2967 /* Read in resource table */
2968 resTab
= heap_alloc( resTabSize
);
2969 if ( !resTab
) return FALSE
;
2971 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2972 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2974 heap_free( resTab
);
2979 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2981 if (!IS_INTRESOURCE(typeid)) /* named type */
2983 BYTE len
= strlen( typeid );
2984 while (typeInfo
->type_id
)
2986 if (!(typeInfo
->type_id
& 0x8000))
2988 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2989 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2991 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2992 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2995 else /* numeric type id */
2997 WORD id
= LOWORD(typeid) | 0x8000;
2998 while (typeInfo
->type_id
)
3000 if (typeInfo
->type_id
== id
) goto found_type
;
3001 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3002 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3005 TRACE("No typeid entry found for %p\n", typeid );
3006 heap_free( resTab
);
3010 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3012 if (!IS_INTRESOURCE(resid
)) /* named resource */
3014 BYTE len
= strlen( resid
);
3015 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3017 BYTE
*p
= resTab
+ nameInfo
->id
;
3018 if (nameInfo
->id
& 0x8000) continue;
3019 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3022 else /* numeric resource id */
3024 WORD id
= LOWORD(resid
) | 0x8000;
3025 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3026 if (nameInfo
->id
== id
) goto found_name
;
3028 TRACE("No resid entry found for %p\n", typeid );
3029 heap_free( resTab
);
3033 /* Return resource data */
3034 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3035 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3037 heap_free( resTab
);
3041 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3045 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3048 This
= heap_alloc(sizeof(TLB_NEFile
));
3049 if (!This
) return E_OUTOFMEMORY
;
3051 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3053 This
->typelib_base
= NULL
;
3055 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3056 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3058 DWORD reslen
, offset
;
3059 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3061 This
->typelib_base
= heap_alloc(reslen
);
3062 if( !This
->typelib_base
)
3066 LZSeek( lzfd
, offset
, SEEK_SET
);
3067 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3069 *ppBase
= This
->typelib_base
;
3070 *pdwTLBLength
= reslen
;
3071 *ppFile
= &This
->IUnknown_iface
;
3077 if( lzfd
>= 0) LZClose( lzfd
);
3078 TLB_NEFile_Release(&This
->IUnknown_iface
);
3082 typedef struct TLB_Mapping
3084 IUnknown IUnknown_iface
;
3088 LPVOID typelib_base
;
3091 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3093 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3096 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3098 if (IsEqualIID(riid
, &IID_IUnknown
))
3101 IUnknown_AddRef(iface
);
3105 return E_NOINTERFACE
;
3108 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3110 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3111 return InterlockedIncrement(&This
->refs
);
3114 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3116 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3117 ULONG refs
= InterlockedDecrement(&This
->refs
);
3120 if (This
->typelib_base
)
3121 UnmapViewOfFile(This
->typelib_base
);
3123 CloseHandle(This
->mapping
);
3124 if (This
->file
!= INVALID_HANDLE_VALUE
)
3125 CloseHandle(This
->file
);
3131 static const IUnknownVtbl TLB_Mapping_Vtable
=
3133 TLB_Mapping_QueryInterface
,
3138 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3142 This
= heap_alloc(sizeof(TLB_Mapping
));
3144 return E_OUTOFMEMORY
;
3146 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3148 This
->file
= INVALID_HANDLE_VALUE
;
3149 This
->mapping
= NULL
;
3150 This
->typelib_base
= NULL
;
3152 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3153 if (INVALID_HANDLE_VALUE
!= This
->file
)
3155 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3158 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3159 if(This
->typelib_base
)
3161 /* retrieve file size */
3162 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3163 *ppBase
= This
->typelib_base
;
3164 *ppFile
= &This
->IUnknown_iface
;
3170 IUnknown_Release(&This
->IUnknown_iface
);
3171 return TYPE_E_CANTLOADLIBRARY
;
3174 /****************************************************************************
3177 * find the type of the typelib file and map the typelib resource into
3181 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3182 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3184 ITypeLibImpl
*entry
;
3187 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3188 LPVOID pBase
= NULL
;
3189 DWORD dwTLBLength
= 0;
3190 IUnknown
*pFile
= NULL
;
3194 index_str
= strrchrW(pszFileName
, '\\');
3195 if(index_str
&& *++index_str
!= '\0')
3198 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3199 if(*end_ptr
== '\0')
3201 int str_len
= index_str
- pszFileName
- 1;
3203 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3204 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3209 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3211 if(strchrW(file
, '\\'))
3213 lstrcpyW(pszPath
, file
);
3217 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3218 pszPath
[len
] = '\\';
3219 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3223 if(file
!= pszFileName
) heap_free(file
);
3225 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3227 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3228 EnterCriticalSection(&cache_section
);
3229 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3231 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3233 TRACE("cache hit\n");
3234 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3235 ITypeLib2_AddRef(*ppTypeLib
);
3236 LeaveCriticalSection(&cache_section
);
3240 LeaveCriticalSection(&cache_section
);
3242 /* now actually load and parse the typelib */
3244 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3245 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3246 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3247 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3248 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3251 if (dwTLBLength
>= 4)
3253 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3254 if (dwSignature
== MSFT_SIGNATURE
)
3255 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3256 else if (dwSignature
== SLTG_SIGNATURE
)
3257 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3260 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3261 ret
= TYPE_E_CANTLOADLIBRARY
;
3265 ret
= TYPE_E_CANTLOADLIBRARY
;
3266 IUnknown_Release(pFile
);
3270 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3272 TRACE("adding to cache\n");
3273 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3274 lstrcpyW(impl
->path
, pszPath
);
3275 /* We should really canonicalise the path here. */
3276 impl
->index
= index
;
3278 /* FIXME: check if it has added already in the meantime */
3279 EnterCriticalSection(&cache_section
);
3280 list_add_head(&tlb_cache
, &impl
->entry
);
3281 LeaveCriticalSection(&cache_section
);
3287 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3289 ret
= TYPE_E_CANTLOADLIBRARY
;
3296 /*================== ITypeLib(2) Methods ===================================*/
3298 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3300 ITypeLibImpl
* pTypeLibImpl
;
3302 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3303 if (!pTypeLibImpl
) return NULL
;
3305 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3306 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3307 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3308 pTypeLibImpl
->ref
= 1;
3310 list_init(&pTypeLibImpl
->implib_list
);
3311 list_init(&pTypeLibImpl
->custdata_list
);
3312 list_init(&pTypeLibImpl
->name_list
);
3313 list_init(&pTypeLibImpl
->string_list
);
3314 list_init(&pTypeLibImpl
->guid_list
);
3315 list_init(&pTypeLibImpl
->ref_list
);
3316 pTypeLibImpl
->dispatch_href
= -1;
3318 return pTypeLibImpl
;
3321 /****************************************************************************
3322 * ITypeLib2_Constructor_MSFT
3324 * loading an MSFT typelib from an in-memory image
3326 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3330 MSFT_Header tlbHeader
;
3331 MSFT_SegDir tlbSegDir
;
3332 ITypeLibImpl
* pTypeLibImpl
;
3334 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3336 pTypeLibImpl
= TypeLibImpl_Constructor();
3337 if (!pTypeLibImpl
) return NULL
;
3339 /* get pointer to beginning of typelib data */
3343 cx
.pLibInfo
= pTypeLibImpl
;
3344 cx
.length
= dwTLBLength
;
3347 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3348 TRACE_(typelib
)("header:\n");
3349 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3350 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3351 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3354 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3356 /* there is a small amount of information here until the next important
3358 * the segment directory . Try to calculate the amount of data */
3359 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3361 /* now read the segment directory */
3362 TRACE("read segment directory (at %d)\n",lPSegDir
);
3363 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3364 cx
.pTblDir
= &tlbSegDir
;
3366 /* just check two entries */
3367 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3369 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3370 heap_free(pTypeLibImpl
);
3374 MSFT_ReadAllNames(&cx
);
3375 MSFT_ReadAllStrings(&cx
);
3376 MSFT_ReadAllGuids(&cx
);
3378 /* now fill our internal data */
3379 /* TLIBATTR fields */
3380 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3382 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3383 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3384 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3385 pTypeLibImpl
->libflags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3387 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3388 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3390 /* name, eventually add to a hash table */
3391 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3394 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3395 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3397 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3400 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3401 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3404 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3407 if(tlbHeader
.CustomDataOffset
>= 0)
3409 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3412 /* fill in type descriptions */
3413 if(tlbSegDir
.pTypdescTab
.length
> 0)
3415 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3417 pTypeLibImpl
->ctTypeDesc
= cTD
;
3418 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3419 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3422 /* FIXME: add several sanity checks here */
3423 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3424 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3426 /* FIXME: check safearray */
3428 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3430 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3432 else if(td
[0] == VT_CARRAY
)
3434 /* array descr table here */
3435 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3437 else if(td
[0] == VT_USERDEFINED
)
3439 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3441 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3444 /* second time around to fill the array subscript info */
3447 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3448 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3450 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3451 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3454 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3456 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3458 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3460 for(j
= 0; j
<td
[2]; j
++)
3462 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3463 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3464 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3465 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3470 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3471 ERR("didn't find array description data\n");
3476 /* imported type libs */
3477 if(tlbSegDir
.pImpFiles
.offset
>0)
3480 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3483 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3487 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3488 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3489 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3491 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3492 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3493 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3494 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3497 name
= heap_alloc_zero(size
+1);
3498 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3499 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3502 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3503 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3505 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3509 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3510 if(pTypeLibImpl
->dispatch_href
!= -1)
3511 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3514 if(tlbHeader
.nrtypeinfos
>= 0 )
3516 ITypeInfoImpl
**ppTI
;
3519 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3521 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3523 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3526 (pTypeLibImpl
->TypeInfoCount
)++;
3530 TRACE("(%p)\n", pTypeLibImpl
);
3531 return &pTypeLibImpl
->ITypeLib2_iface
;
3535 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3541 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3542 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3546 guid
->Data4
[0] = s
>> 8;
3547 guid
->Data4
[1] = s
& 0xff;
3550 for(i
= 0; i
< 6; i
++) {
3551 memcpy(b
, str
+ 24 + 2 * i
, 2);
3552 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3557 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3564 bytelen
= *(const WORD
*)ptr
;
3565 if(bytelen
== 0xffff) return 2;
3567 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3568 tmp_str
= SysAllocStringLen(NULL
, len
);
3570 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3571 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3572 SysFreeString(tmp_str
);
3577 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3582 bytelen
= *(const WORD
*)ptr
;
3583 if(bytelen
== 0xffff) return 2;
3584 *str
= heap_alloc(bytelen
+ 1);
3585 memcpy(*str
, ptr
+ 2, bytelen
);
3586 (*str
)[bytelen
] = '\0';
3590 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3595 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3596 if (tlbstr
->offset
== offset
)
3600 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3601 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3602 SysFreeString(tmp_str
);
3607 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3609 char *ptr
= pLibBlk
;
3612 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3613 FIXME("libblk magic = %04x\n", w
);
3618 if((w
= *(WORD
*)ptr
) != 0xffff) {
3619 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3624 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3626 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3628 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3631 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3634 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3635 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3637 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3640 ptr
+= 4; /* skip res12 */
3642 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3645 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3648 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3651 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
);
3652 ptr
+= sizeof(GUID
);
3654 return ptr
- (char*)pLibBlk
;
3657 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3662 } sltg_ref_lookup_t
;
3664 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3665 HREFTYPE
*typelib_ref
)
3667 if(table
&& typeinfo_ref
< table
->num
)
3669 *typelib_ref
= table
->refs
[typeinfo_ref
];
3673 ERR_(typelib
)("Unable to find reference\n");
3678 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3683 if((*pType
& 0xe00) == 0xe00) {
3685 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3686 pTD
= pTD
->u
.lptdesc
;
3688 switch(*pType
& 0x3f) {
3691 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3692 pTD
= pTD
->u
.lptdesc
;
3695 case VT_USERDEFINED
:
3696 pTD
->vt
= VT_USERDEFINED
;
3697 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3703 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3706 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3708 pTD
->vt
= VT_CARRAY
;
3709 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3710 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3711 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3712 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3714 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3720 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3724 pTD
->vt
= VT_SAFEARRAY
;
3725 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3726 pTD
= pTD
->u
.lptdesc
;
3730 pTD
->vt
= *pType
& 0x3f;
3739 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3740 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3742 /* Handle [in/out] first */
3743 if((*pType
& 0xc000) == 0xc000)
3744 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3745 else if(*pType
& 0x8000)
3746 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3747 else if(*pType
& 0x4000)
3748 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3750 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3753 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3756 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3758 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3762 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3767 TLBRefType
*ref_type
;
3768 sltg_ref_lookup_t
*table
;
3769 HREFTYPE typelib_ref
;
3771 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3772 FIXME("Ref magic = %x\n", pRef
->magic
);
3775 name
= ( (char*)pRef
->names
+ pRef
->number
);
3777 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3778 table
->num
= pRef
->number
>> 3;
3780 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3782 /* We don't want the first href to be 0 */
3783 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3785 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3787 unsigned int lib_offs
, type_num
;
3789 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3791 name
+= SLTG_ReadStringA(name
, &refname
);
3792 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3793 FIXME_(typelib
)("Can't sscanf ref\n");
3794 if(lib_offs
!= 0xffff) {
3797 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3798 if(import
->offset
== lib_offs
)
3801 if(&import
->entry
== &pTL
->implib_list
) {
3802 char fname
[MAX_PATH
+1];
3806 import
= heap_alloc_zero(sizeof(*import
));
3807 import
->offset
= lib_offs
;
3808 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3809 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
);
3810 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3811 &import
->wVersionMajor
,
3812 &import
->wVersionMinor
,
3813 &import
->lcid
, fname
) != 4) {
3814 FIXME_(typelib
)("can't sscanf ref %s\n",
3815 pNameTable
+ lib_offs
+ 40);
3817 len
= strlen(fname
);
3818 if(fname
[len
-1] != '#')
3819 FIXME("fname = %s\n", fname
);
3820 fname
[len
-1] = '\0';
3821 import
->name
= TLB_MultiByteToBSTR(fname
);
3822 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3824 ref_type
->pImpTLInfo
= import
;
3826 /* Store a reference to IDispatch */
3827 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3828 pTL
->dispatch_href
= typelib_ref
;
3830 } else { /* internal ref */
3831 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3833 ref_type
->reference
= typelib_ref
;
3834 ref_type
->index
= type_num
;
3837 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3839 table
->refs
[ref
] = typelib_ref
;
3842 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3843 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3844 dump_TLBRefType(pTL
);
3848 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3849 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3851 SLTG_ImplInfo
*info
;
3852 TLBImplType
*pImplType
;
3853 /* I don't really get this structure, usually it's 0x16 bytes
3854 long, but iuser.tlb contains some that are 0x18 bytes long.
3855 That's ok because we can use the next ptr to jump to the next
3856 one. But how do we know the length of the last one? The WORD
3857 at offs 0x8 might be the clue. For now I'm just assuming that
3858 the last one is the regular 0x16 bytes. */
3860 info
= (SLTG_ImplInfo
*)pBlk
;
3863 if(info
->next
== 0xffff)
3865 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3868 info
= (SLTG_ImplInfo
*)pBlk
;
3869 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
3870 pImplType
= pTI
->impltypes
;
3872 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3873 pImplType
->implflags
= info
->impltypeflags
;
3876 if(info
->next
== 0xffff)
3879 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3880 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3882 info
++; /* see comment at top of function */
3886 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3887 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3889 TLBVarDesc
*pVarDesc
;
3890 const TLBString
*prevName
= NULL
;
3891 SLTG_Variable
*pItem
;
3895 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
3897 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3898 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3900 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3902 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3903 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3904 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3908 if (pItem
->name
== 0xfffe)
3909 pVarDesc
->Name
= prevName
;
3911 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
3913 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
3914 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3915 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3917 if(pItem
->flags
& 0x02)
3918 pType
= &pItem
->type
;
3920 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3922 if (pItem
->flags
& ~0xda)
3923 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3925 SLTG_DoElem(pType
, pBlk
,
3926 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3928 if (TRACE_ON(typelib
)) {
3930 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3931 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3934 if (pItem
->flags
& 0x40) {
3935 TRACE_(typelib
)("VAR_DISPATCH\n");
3936 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3938 else if (pItem
->flags
& 0x10) {
3939 TRACE_(typelib
)("VAR_CONST\n");
3940 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3941 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3942 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3943 if (pItem
->flags
& 0x08)
3944 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3946 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3952 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3954 TRACE_(typelib
)("len = %u\n", len
);
3955 if (len
== 0xffff) {
3958 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3959 str
= SysAllocStringLen(NULL
, alloc_len
);
3960 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3962 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3963 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3972 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3973 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3976 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3981 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3982 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3983 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3986 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3987 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3989 if (pItem
->flags
& 0x80)
3990 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3992 prevName
= pVarDesc
->Name
;
3997 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3998 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4000 SLTG_Function
*pFunc
;
4002 TLBFuncDesc
*pFuncDesc
;
4004 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4006 pFuncDesc
= pTI
->funcdescs
;
4007 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4008 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4013 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4014 case SLTG_FUNCTION_MAGIC
:
4015 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4017 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4018 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4020 case SLTG_STATIC_FUNCTION_MAGIC
:
4021 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4024 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4027 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4029 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4030 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4031 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4032 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4033 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4034 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4036 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4037 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4039 if(pFunc
->retnextopt
& 0x80)
4040 pType
= &pFunc
->rettype
;
4042 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4044 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4046 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4047 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4048 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4050 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4052 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4053 char *paramName
= pNameTable
+ *pArg
;
4055 /* If arg type follows then paramName points to the 2nd
4056 letter of the name, else the next WORD is an offset to
4057 the arg type and paramName points to the first letter.
4058 So let's take one char off paramName and see if we're
4059 pointing at an alpha-numeric char. However if *pArg is
4060 0xffff or 0xfffe then the param has no name, the former
4061 meaning that the next WORD is the type, the latter
4062 meaning that the next WORD is an offset to the type. */
4067 else if(*pArg
== 0xfffe) {
4071 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4076 if(HaveOffs
) { /* the next word is an offset to type */
4077 pType
= (WORD
*)(pBlk
+ *pArg
);
4078 SLTG_DoElem(pType
, pBlk
,
4079 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4084 pArg
= SLTG_DoElem(pArg
, pBlk
,
4085 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4088 /* Are we an optional param ? */
4089 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4090 pFuncDesc
->funcdesc
.cParamsOpt
)
4091 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4094 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4095 paramName
- pNameTable
, pTI
->pTypeLib
);
4097 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4101 pTI
->cFuncs
= cFuncs
;
4104 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4105 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4106 SLTG_TypeInfoTail
*pTITail
)
4109 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4111 if(pTIHeader
->href_table
!= 0xffffffff) {
4112 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4118 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4119 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4121 heap_free(ref_lookup
);
4125 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4126 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4127 const SLTG_TypeInfoTail
*pTITail
)
4130 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4132 if(pTIHeader
->href_table
!= 0xffffffff) {
4133 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4139 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4140 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4143 if (pTITail
->funcs_off
!= 0xffff)
4144 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4146 heap_free(ref_lookup
);
4148 if (TRACE_ON(typelib
))
4149 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4152 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4153 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4154 const SLTG_TypeInfoTail
*pTITail
)
4156 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4159 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4160 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4161 const SLTG_TypeInfoTail
*pTITail
)
4164 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4166 if (pTITail
->simple_alias
) {
4167 /* if simple alias, no more processing required */
4168 pTI
->tdescAlias
.vt
= pTITail
->tdescalias_vt
;
4172 if(pTIHeader
->href_table
!= 0xffffffff) {
4173 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4177 /* otherwise it is an offset to a type */
4178 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4180 SLTG_DoType(pType
, pBlk
, &pTI
->tdescAlias
, ref_lookup
);
4182 heap_free(ref_lookup
);
4185 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4186 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4187 const SLTG_TypeInfoTail
*pTITail
)
4189 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4190 if (pTIHeader
->href_table
!= 0xffffffff)
4191 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4194 if (pTITail
->vars_off
!= 0xffff)
4195 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4197 if (pTITail
->funcs_off
!= 0xffff)
4198 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4200 if (pTITail
->impls_off
!= 0xffff)
4201 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4203 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4204 * of dispinterface functions including the IDispatch ones, so
4205 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4206 pTI
->cbSizeVft
= pTI
->cFuncs
* sizeof(void *);
4208 heap_free(ref_lookup
);
4209 if (TRACE_ON(typelib
))
4210 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4213 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4214 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4215 const SLTG_TypeInfoTail
*pTITail
)
4217 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4220 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4221 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4222 const SLTG_TypeInfoTail
*pTITail
)
4224 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4225 if (pTIHeader
->href_table
!= 0xffffffff)
4226 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4229 if (pTITail
->vars_off
!= 0xffff)
4230 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4232 if (pTITail
->funcs_off
!= 0xffff)
4233 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4234 heap_free(ref_lookup
);
4235 if (TRACE_ON(typelib
))
4239 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4240 manageable copy of it into this */
4253 } SLTG_InternalOtherTypeInfo
;
4255 /****************************************************************************
4256 * ITypeLib2_Constructor_SLTG
4258 * loading a SLTG typelib from an in-memory image
4260 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4262 ITypeLibImpl
*pTypeLibImpl
;
4263 SLTG_Header
*pHeader
;
4264 SLTG_BlkEntry
*pBlkEntry
;
4268 LPVOID pBlk
, pFirstBlk
;
4269 SLTG_LibBlk
*pLibBlk
;
4270 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4271 char *pAfterOTIBlks
= NULL
;
4272 char *pNameTable
, *ptr
;
4275 ITypeInfoImpl
**ppTypeInfoImpl
;
4277 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4280 pTypeLibImpl
= TypeLibImpl_Constructor();
4281 if (!pTypeLibImpl
) return NULL
;
4285 TRACE_(typelib
)("header:\n");
4286 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4287 pHeader
->nrOfFileBlks
);
4288 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4289 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4290 pHeader
->SLTG_magic
);
4294 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4295 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4297 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4298 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4300 /* Next we have a magic block */
4301 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4303 /* Let's see if we're still in sync */
4304 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4305 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4306 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4309 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4310 sizeof(SLTG_DIR_MAGIC
))) {
4311 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4315 pIndex
= (SLTG_Index
*)(pMagic
+1);
4317 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4319 pFirstBlk
= pPad9
+ 1;
4321 /* We'll set up a ptr to the main library block, which is the last one. */
4323 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4324 pBlkEntry
[order
].next
!= 0;
4325 order
= pBlkEntry
[order
].next
- 1, i
++) {
4326 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4330 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4332 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4337 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4339 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4342 ptr
= (char*)pLibBlk
+ len
;
4344 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4348 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4350 w
= *(WORD
*)(ptr
+ 2);
4353 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4354 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4355 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4357 w
= *(WORD
*)(ptr
+ 4 + len
);
4359 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4361 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4362 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4363 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4365 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4366 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4367 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4369 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4370 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4373 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4374 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4375 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4376 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4377 len
+= sizeof(SLTG_OtherTypeInfo
);
4381 pAfterOTIBlks
= ptr
;
4383 /* Skip this WORD and get the next DWORD */
4384 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4386 /* Now add this to pLibBLk look at what we're pointing at and
4387 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4388 dust and we should be pointing at the beginning of the name
4391 pNameTable
= (char*)pLibBlk
+ len
;
4393 switch(*(WORD
*)pNameTable
) {
4400 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4404 pNameTable
+= 0x216;
4408 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4410 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4413 /* Hopefully we now have enough ptrs set up to actually read in
4414 some TypeInfos. It's not clear which order to do them in, so
4415 I'll just follow the links along the BlkEntry chain and read
4416 them in the order in which they are in the file */
4418 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4419 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4421 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4422 pBlkEntry
[order
].next
!= 0;
4423 order
= pBlkEntry
[order
].next
- 1, i
++) {
4425 SLTG_TypeInfoHeader
*pTIHeader
;
4426 SLTG_TypeInfoTail
*pTITail
;
4427 SLTG_MemberHeader
*pMemHeader
;
4429 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4430 FIXME_(typelib
)("Index strings don't match\n");
4431 heap_free(pOtherTypeInfoBlks
);
4436 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4437 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4438 heap_free(pOtherTypeInfoBlks
);
4441 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4442 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4443 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4445 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4446 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4447 (*ppTypeInfoImpl
)->index
= i
;
4448 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4449 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4450 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
);
4451 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4452 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4453 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4454 (*ppTypeInfoImpl
)->wTypeFlags
=
4455 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4457 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4458 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4460 if((pTIHeader
->typeflags1
& 7) != 2)
4461 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4462 if(pTIHeader
->typeflags3
!= 2)
4463 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4465 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4466 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4467 typekind_desc
[pTIHeader
->typekind
],
4468 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4469 (*ppTypeInfoImpl
)->wTypeFlags
);
4471 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4473 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4475 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4476 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4477 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4479 switch(pTIHeader
->typekind
) {
4481 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4482 pTIHeader
, pTITail
);
4486 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4487 pTIHeader
, pTITail
);
4490 case TKIND_INTERFACE
:
4491 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4492 pTIHeader
, pTITail
);
4496 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4497 pTIHeader
, pTITail
);
4501 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4502 pTIHeader
, pTITail
);
4505 case TKIND_DISPATCH
:
4506 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4507 pTIHeader
, pTITail
);
4511 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4512 pTIHeader
, pTITail
);
4516 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4521 /* could get cFuncs, cVars and cImplTypes from here
4522 but we've already set those */
4523 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4539 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4542 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4543 FIXME("Somehow processed %d TypeInfos\n", i
);
4544 heap_free(pOtherTypeInfoBlks
);
4548 heap_free(pOtherTypeInfoBlks
);
4549 return &pTypeLibImpl
->ITypeLib2_iface
;
4552 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4554 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4556 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4558 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4559 IsEqualIID(riid
,&IID_ITypeLib
)||
4560 IsEqualIID(riid
,&IID_ITypeLib2
))
4562 *ppv
= &This
->ITypeLib2_iface
;
4564 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4565 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4567 *ppv
= &This
->ICreateTypeLib2_iface
;
4572 TRACE("-- Interface: E_NOINTERFACE\n");
4573 return E_NOINTERFACE
;
4576 IUnknown_AddRef((IUnknown
*)*ppv
);
4580 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4582 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4583 ULONG ref
= InterlockedIncrement(&This
->ref
);
4585 TRACE("(%p) ref=%u\n", This
, ref
);
4590 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4592 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4593 ULONG ref
= InterlockedDecrement(&This
->ref
);
4595 TRACE("(%p) ref=%u\n",This
, ref
);
4599 TLBImpLib
*pImpLib
, *pImpLibNext
;
4600 TLBRefType
*ref_type
;
4601 TLBString
*tlbstr
, *tlbstr_next
;
4605 /* remove cache entry */
4608 TRACE("removing from cache list\n");
4609 EnterCriticalSection(&cache_section
);
4610 if(This
->entry
.next
)
4611 list_remove(&This
->entry
);
4612 LeaveCriticalSection(&cache_section
);
4613 heap_free(This
->path
);
4615 TRACE(" destroying ITypeLib(%p)\n",This
);
4617 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4618 list_remove(&tlbstr
->entry
);
4622 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4623 list_remove(&tlbstr
->entry
);
4627 TLB_FreeCustData(&This
->custdata_list
);
4629 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4630 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4631 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4633 heap_free(This
->pTypeDesc
);
4635 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4637 if (pImpLib
->pImpTypeLib
)
4638 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4639 SysFreeString(pImpLib
->name
);
4641 list_remove(&pImpLib
->entry
);
4645 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4647 list_remove(&ref_type
->entry
);
4648 heap_free(ref_type
);
4651 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4652 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4653 heap_free(This
->typeinfos
);
4661 /* ITypeLib::GetTypeInfoCount
4663 * Returns the number of type descriptions in the type library
4665 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4667 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4668 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4669 return This
->TypeInfoCount
;
4672 /* ITypeLib::GetTypeInfo
4674 * retrieves the specified type description in the library.
4676 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4679 ITypeInfo
**ppTInfo
)
4681 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4683 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4686 return E_INVALIDARG
;
4688 if(index
>= This
->TypeInfoCount
)
4689 return TYPE_E_ELEMENTNOTFOUND
;
4691 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[index
];
4692 ITypeInfo_AddRef(*ppTInfo
);
4698 /* ITypeLibs::GetTypeInfoType
4700 * Retrieves the type of a type description.
4702 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4707 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4709 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4712 return E_INVALIDARG
;
4714 if(index
>= This
->TypeInfoCount
)
4715 return TYPE_E_ELEMENTNOTFOUND
;
4717 *pTKind
= This
->typeinfos
[index
]->typekind
;
4722 /* ITypeLib::GetTypeInfoOfGuid
4724 * Retrieves the type description that corresponds to the specified GUID.
4727 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4730 ITypeInfo
**ppTInfo
)
4732 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4735 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4737 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4738 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4739 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[i
];
4740 ITypeInfo_AddRef(*ppTInfo
);
4745 return TYPE_E_ELEMENTNOTFOUND
;
4748 /* ITypeLib::GetLibAttr
4750 * Retrieves the structure that contains the library's attributes.
4753 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4757 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4759 TRACE("(%p, %p)\n", This
, attr
);
4761 if (!attr
) return E_INVALIDARG
;
4763 *attr
= heap_alloc(sizeof(**attr
));
4764 if (!*attr
) return E_OUTOFMEMORY
;
4766 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4767 (*attr
)->lcid
= This
->set_lcid
;
4768 (*attr
)->syskind
= This
->syskind
;
4769 (*attr
)->wMajorVerNum
= This
->ver_major
;
4770 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4771 (*attr
)->wLibFlags
= This
->libflags
;
4776 /* ITypeLib::GetTypeComp
4778 * Enables a client compiler to bind to a library's types, variables,
4779 * constants, and global functions.
4782 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4784 ITypeComp
**ppTComp
)
4786 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4788 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4789 *ppTComp
= &This
->ITypeComp_iface
;
4790 ITypeComp_AddRef(*ppTComp
);
4795 /* ITypeLib::GetDocumentation
4797 * Retrieves the library's documentation string, the complete Help file name
4798 * and path, and the context identifier for the library Help topic in the Help
4801 * On a successful return all non-null BSTR pointers will have been set,
4804 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4808 BSTR
*pBstrDocString
,
4809 DWORD
*pdwHelpContext
,
4810 BSTR
*pBstrHelpFile
)
4812 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4813 HRESULT result
= E_INVALIDARG
;
4816 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4818 pBstrName
, pBstrDocString
,
4819 pdwHelpContext
, pBstrHelpFile
);
4823 /* documentation for the typelib */
4828 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4836 if (This
->DocString
)
4838 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4841 else if (This
->Name
)
4843 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->Name
))))
4847 *pBstrDocString
= NULL
;
4851 *pdwHelpContext
= This
->dwHelpContext
;
4857 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4861 *pBstrHelpFile
= NULL
;
4868 /* for a typeinfo */
4869 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4871 if(SUCCEEDED(result
))
4873 result
= ITypeInfo_GetDocumentation(pTInfo
,
4877 pdwHelpContext
, pBstrHelpFile
);
4879 ITypeInfo_Release(pTInfo
);
4884 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4886 if (pBstrName
) SysFreeString (*pBstrName
);
4888 return STG_E_INSUFFICIENTMEMORY
;
4893 * Indicates whether a passed-in string contains the name of a type or member
4894 * described in the library.
4897 static HRESULT WINAPI
ITypeLib2_fnIsName(
4903 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4905 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
4907 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4911 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4912 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4913 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4914 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
4915 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4917 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4918 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
4919 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4920 goto ITypeLib2_fnIsName_exit
;
4923 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
4924 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4925 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4931 ITypeLib2_fnIsName_exit
:
4932 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4933 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4938 /* ITypeLib::FindName
4940 * Finds occurrences of a type description in a type library. This may be used
4941 * to quickly verify that a name exists in a type library.
4944 static HRESULT WINAPI
ITypeLib2_fnFindName(
4948 ITypeInfo
**ppTInfo
,
4952 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4957 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
4959 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
4960 return E_INVALIDARG
;
4962 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
4963 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
4964 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4968 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4969 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
4970 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
4973 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4974 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
4975 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
4976 goto ITypeLib2_fnFindName_exit
;
4980 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
4982 goto ITypeLib2_fnFindName_exit
;
4985 ITypeLib2_fnFindName_exit
:
4986 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4987 ppTInfo
[count
]=(LPTYPEINFO
)pTInfo
;
4990 TRACE("found %d typeinfos\n", count
);
4997 /* ITypeLib::ReleaseTLibAttr
4999 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5002 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5004 TLIBATTR
*pTLibAttr
)
5006 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5007 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5008 heap_free(pTLibAttr
);
5011 /* ITypeLib2::GetCustData
5013 * gets the custom data
5015 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5020 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5021 TLBCustData
*pCData
;
5023 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5025 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5027 return TYPE_E_ELEMENTNOTFOUND
;
5029 VariantInit(pVarVal
);
5030 VariantCopy(pVarVal
, &pCData
->data
);
5035 /* ITypeLib2::GetLibStatistics
5037 * Returns statistics about a type library that are required for efficient
5038 * sizing of hash tables.
5041 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5043 ULONG
*pcUniqueNames
,
5044 ULONG
*pcchUniqueNames
)
5046 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5048 FIXME("(%p): stub!\n", This
);
5050 if(pcUniqueNames
) *pcUniqueNames
=1;
5051 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5055 /* ITypeLib2::GetDocumentation2
5057 * Retrieves the library's documentation string, the complete Help file name
5058 * and path, the localization context to use, and the context ID for the
5059 * library Help topic in the Help file.
5062 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5066 BSTR
*pbstrHelpString
,
5067 DWORD
*pdwHelpStringContext
,
5068 BSTR
*pbstrHelpStringDll
)
5070 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5074 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5076 /* the help string should be obtained from the helpstringdll,
5077 * using the _DLLGetDocumentation function, based on the supplied
5078 * lcid. Nice to do sometime...
5082 /* documentation for the typelib */
5084 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5085 if(pdwHelpStringContext
)
5086 *pdwHelpStringContext
=This
->dwHelpContext
;
5087 if(pbstrHelpStringDll
)
5088 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5094 /* for a typeinfo */
5095 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5097 if(SUCCEEDED(result
))
5099 ITypeInfo2
* pTInfo2
;
5100 result
= ITypeInfo_QueryInterface(pTInfo
,
5102 (LPVOID
*) &pTInfo2
);
5104 if(SUCCEEDED(result
))
5106 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5110 pdwHelpStringContext
,
5111 pbstrHelpStringDll
);
5113 ITypeInfo2_Release(pTInfo2
);
5116 ITypeInfo_Release(pTInfo
);
5122 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5124 TLBCustData
*pCData
;
5128 ct
= list_count(custdata_list
);
5130 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5131 if(!pCustData
->prgCustData
)
5132 return E_OUTOFMEMORY
;
5134 pCustData
->cCustData
= ct
;
5136 cdi
= pCustData
->prgCustData
;
5137 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5138 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5139 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5147 /* ITypeLib2::GetAllCustData
5149 * Gets all custom data items for the library.
5152 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5154 CUSTDATA
*pCustData
)
5156 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5157 TRACE("(%p)->(%p)\n", This
, pCustData
);
5158 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5161 static const ITypeLib2Vtbl tlbvt
= {
5162 ITypeLib2_fnQueryInterface
,
5164 ITypeLib2_fnRelease
,
5165 ITypeLib2_fnGetTypeInfoCount
,
5166 ITypeLib2_fnGetTypeInfo
,
5167 ITypeLib2_fnGetTypeInfoType
,
5168 ITypeLib2_fnGetTypeInfoOfGuid
,
5169 ITypeLib2_fnGetLibAttr
,
5170 ITypeLib2_fnGetTypeComp
,
5171 ITypeLib2_fnGetDocumentation
,
5173 ITypeLib2_fnFindName
,
5174 ITypeLib2_fnReleaseTLibAttr
,
5176 ITypeLib2_fnGetCustData
,
5177 ITypeLib2_fnGetLibStatistics
,
5178 ITypeLib2_fnGetDocumentation2
,
5179 ITypeLib2_fnGetAllCustData
5183 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5185 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5187 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5190 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5192 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5194 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5197 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5199 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5201 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5204 static HRESULT WINAPI
ITypeLibComp_fnBind(
5209 ITypeInfo
** ppTInfo
,
5210 DESCKIND
* pDescKind
,
5213 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5214 int typemismatch
=0, i
;
5216 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5218 *pDescKind
= DESCKIND_NONE
;
5219 pBindPtr
->lptcomp
= NULL
;
5222 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5223 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5224 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5226 /* FIXME: check wFlags here? */
5227 /* FIXME: we should use a hash table to look this info up using lHash
5228 * instead of an O(n) search */
5229 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5230 (pTypeInfo
->typekind
== TKIND_MODULE
))
5232 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5234 *pDescKind
= DESCKIND_TYPECOMP
;
5235 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5236 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5237 TRACE("module or enum: %s\n", debugstr_w(szName
));
5242 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5243 (pTypeInfo
->typekind
== TKIND_ENUM
))
5245 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5248 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5249 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5251 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5254 else if (hr
== TYPE_E_TYPEMISMATCH
)
5258 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5259 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5261 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5263 ITypeInfo
*subtypeinfo
;
5265 DESCKIND subdesckind
;
5267 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5268 &subtypeinfo
, &subdesckind
, &subbindptr
);
5269 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5271 TYPEDESC tdesc_appobject
;
5272 const VARDESC vardesc_appobject
=
5275 NULL
, /* lpstrSchema */
5290 VAR_STATIC
/* varkind */
5293 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5294 tdesc_appobject
.vt
= VT_USERDEFINED
;
5296 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5298 /* cleanup things filled in by Bind call so we can put our
5299 * application object data in there instead */
5300 switch (subdesckind
)
5302 case DESCKIND_FUNCDESC
:
5303 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5305 case DESCKIND_VARDESC
:
5306 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5311 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5313 if (pTypeInfo
->hreftype
== -1)
5314 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5316 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5320 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5321 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
5322 ITypeInfo_AddRef(*ppTInfo
);
5325 else if (hr
== TYPE_E_TYPEMISMATCH
)
5332 TRACE("type mismatch %s\n", debugstr_w(szName
));
5333 return TYPE_E_TYPEMISMATCH
;
5337 TRACE("name not found %s\n", debugstr_w(szName
));
5342 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5346 ITypeInfo
** ppTInfo
,
5347 ITypeComp
** ppTComp
)
5349 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5350 ITypeInfoImpl
*info
;
5352 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5354 if(!szName
|| !ppTInfo
|| !ppTComp
)
5355 return E_INVALIDARG
;
5357 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5364 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5365 ITypeInfo_AddRef(*ppTInfo
);
5366 *ppTComp
= &info
->ITypeComp_iface
;
5367 ITypeComp_AddRef(*ppTComp
);
5372 static const ITypeCompVtbl tlbtcvt
=
5375 ITypeLibComp_fnQueryInterface
,
5376 ITypeLibComp_fnAddRef
,
5377 ITypeLibComp_fnRelease
,
5379 ITypeLibComp_fnBind
,
5380 ITypeLibComp_fnBindType
5383 /*================== ITypeInfo(2) Methods ===================================*/
5384 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5386 ITypeInfoImpl
*pTypeInfoImpl
;
5388 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5391 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5392 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5393 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5394 pTypeInfoImpl
->ref
= 0;
5395 pTypeInfoImpl
->hreftype
= -1;
5396 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5397 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5398 list_init(&pTypeInfoImpl
->custdata_list
);
5400 TRACE("(%p)\n", pTypeInfoImpl
);
5401 return pTypeInfoImpl
;
5404 /* ITypeInfo::QueryInterface
5406 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5411 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5413 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5416 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5417 IsEqualIID(riid
,&IID_ITypeInfo
)||
5418 IsEqualIID(riid
,&IID_ITypeInfo2
))
5420 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5421 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5422 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5425 ITypeInfo2_AddRef(iface
);
5426 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5429 TRACE("-- Interface: E_NOINTERFACE\n");
5430 return E_NOINTERFACE
;
5433 /* ITypeInfo::AddRef
5435 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5437 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5438 ULONG ref
= InterlockedIncrement(&This
->ref
);
5440 TRACE("(%p)->ref is %u\n",This
, ref
);
5442 if (ref
== 1 /* incremented from 0 */)
5443 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5448 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5452 TRACE("destroying ITypeInfo(%p)\n",This
);
5454 for (i
= 0; i
< This
->cFuncs
; ++i
)
5457 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5458 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5460 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5461 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5463 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5464 heap_free(elemdesc
->u
.paramdesc
.pparamdescex
);
5466 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5468 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5469 heap_free(pFInfo
->pParamDesc
);
5470 TLB_FreeCustData(&pFInfo
->custdata_list
);
5472 heap_free(This
->funcdescs
);
5474 for(i
= 0; i
< This
->cVars
; ++i
)
5476 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5477 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5479 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5480 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5482 TLB_FreeCustData(&pVInfo
->custdata_list
);
5484 heap_free(This
->vardescs
);
5486 if(This
->impltypes
){
5487 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5488 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5489 TLB_FreeCustData(&pImpl
->custdata_list
);
5491 heap_free(This
->impltypes
);
5494 TLB_FreeCustData(&This
->custdata_list
);
5499 /* ITypeInfo::Release
5501 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5503 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5504 ULONG ref
= InterlockedDecrement(&This
->ref
);
5506 TRACE("(%p)->(%u)\n",This
, ref
);
5510 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5511 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5512 if (not_attached_to_typelib
)
5514 /* otherwise This will be freed when typelib is freed */
5520 /* ITypeInfo::GetTypeAttr
5522 * Retrieves a TYPEATTR structure that contains the attributes of the type
5526 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5527 LPTYPEATTR
*ppTypeAttr
)
5529 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5532 TRACE("(%p)\n",This
);
5534 size
= sizeof(**ppTypeAttr
);
5535 if (This
->typekind
== TKIND_ALIAS
)
5536 size
+= TLB_SizeTypeDesc(&This
->tdescAlias
, FALSE
);
5538 *ppTypeAttr
= heap_alloc(size
);
5540 return E_OUTOFMEMORY
;
5542 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5543 (*ppTypeAttr
)->lcid
= This
->lcid
;
5544 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5545 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5546 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5547 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5548 (*ppTypeAttr
)->typekind
= This
->typekind
;
5549 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5550 (*ppTypeAttr
)->cVars
= This
->cVars
;
5551 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5552 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5553 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5554 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5555 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5556 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5557 (*ppTypeAttr
)->tdescAlias
= This
->tdescAlias
;
5558 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5560 if (This
->typekind
== TKIND_ALIAS
)
5561 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5562 &This
->tdescAlias
, *ppTypeAttr
+ 1);
5564 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5565 /* This should include all the inherited funcs */
5566 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5567 /* This is always the size of IDispatch's vtbl */
5568 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5569 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5574 /* ITypeInfo::GetTypeComp
5576 * Retrieves the ITypeComp interface for the type description, which enables a
5577 * client compiler to bind to the type description's members.
5580 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5581 ITypeComp
* *ppTComp
)
5583 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5585 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5587 *ppTComp
= &This
->ITypeComp_iface
;
5588 ITypeComp_AddRef(*ppTComp
);
5592 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5594 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5595 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5596 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5600 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5603 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5604 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5606 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5607 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5608 *buffer
+= sizeof(PARAMDESCEX
);
5609 *pparamdescex_dest
= *pparamdescex_src
;
5610 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5611 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5612 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5613 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5616 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5620 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5622 UINT len
= SysStringLen(str
), i
;
5623 for (i
= 0; i
< len
; ++i
)
5629 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5631 if (V_VT(var
) == VT_INT
)
5632 return VariantChangeType(var
, var
, 0, VT_I4
);
5633 else if (V_VT(var
) == VT_UINT
)
5634 return VariantChangeType(var
, var
, 0, VT_UI4
);
5635 else if (V_VT(var
) == VT_BSTR
)
5636 return TLB_SanitizeBSTR(V_BSTR(var
));
5641 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5643 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5644 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5647 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5651 SIZE_T size
= sizeof(*src
);
5655 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5656 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5657 for (i
= 0; i
< src
->cParams
; i
++)
5659 size
+= sizeof(ELEMDESC
);
5660 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5663 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5664 if (!dest
) return E_OUTOFMEMORY
;
5667 if (dispinterface
) /* overwrite funckind */
5668 dest
->funckind
= FUNC_DISPATCH
;
5669 buffer
= (char *)(dest
+ 1);
5671 dest
->oVft
= dest
->oVft
& 0xFFFC;
5673 if (dest
->cScodes
) {
5674 dest
->lprgscode
= (SCODE
*)buffer
;
5675 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5676 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5678 dest
->lprgscode
= NULL
;
5680 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5683 SysFreeString((BSTR
)dest
);
5687 if (dest
->cParams
) {
5688 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5689 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5690 for (i
= 0; i
< src
->cParams
; i
++)
5692 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5698 /* undo the above actions */
5699 for (i
= i
- 1; i
>= 0; i
--)
5700 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5701 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5702 SysFreeString((BSTR
)dest
);
5706 dest
->lprgelemdescParam
= NULL
;
5708 /* special treatment for dispinterfaces: this makes functions appear
5709 * to return their [retval] value when it is really returning an
5711 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5713 if (dest
->cParams
&&
5714 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5716 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5717 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5719 ERR("elemdesc should have started with VT_PTR instead of:\n");
5721 dump_ELEMDESC(elemdesc
);
5722 return E_UNEXPECTED
;
5725 /* copy last parameter to the return value. we are using a flat
5726 * buffer so there is no danger of leaking memory in
5728 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5730 /* remove the last parameter */
5734 /* otherwise this function is made to appear to have no return
5736 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5744 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5746 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5748 if (index
>= This
->cFuncs
)
5749 return TYPE_E_ELEMENTNOTFOUND
;
5751 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5755 /* internal function to make the inherited interfaces' methods appear
5756 * part of the interface */
5757 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5758 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5760 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5762 UINT implemented_funcs
= 0;
5767 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5771 ITypeInfo
*pSubTypeInfo
;
5774 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5778 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5781 &sub_funcs
, hrefoffset
);
5782 implemented_funcs
+= sub_funcs
;
5783 ITypeInfo_Release(pSubTypeInfo
);
5786 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5790 *funcs
= implemented_funcs
+ This
->cFuncs
;
5794 if (index
< implemented_funcs
)
5795 return E_INVALIDARG
;
5796 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5800 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5802 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5805 switch (pTypeDesc
->vt
)
5807 case VT_USERDEFINED
:
5808 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5812 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5815 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5823 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5826 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5827 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5828 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5831 /* ITypeInfo::GetFuncDesc
5833 * Retrieves the FUNCDESC structure that contains information about a
5834 * specified function.
5837 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5838 LPFUNCDESC
*ppFuncDesc
)
5840 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5841 const FUNCDESC
*internal_funcdesc
;
5843 UINT hrefoffset
= 0;
5845 TRACE("(%p) index %d\n", This
, index
);
5848 return E_INVALIDARG
;
5850 if (This
->needs_layout
)
5851 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5853 if (This
->typekind
== TKIND_DISPATCH
)
5854 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5855 &internal_funcdesc
, NULL
,
5858 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5859 &internal_funcdesc
);
5862 WARN("description for function %d not found\n", index
);
5866 hr
= TLB_AllocAndInitFuncDesc(
5869 This
->typekind
== TKIND_DISPATCH
);
5871 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
5872 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5874 TRACE("-- 0x%08x\n", hr
);
5878 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5882 SIZE_T size
= sizeof(*src
);
5885 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5886 if (src
->varkind
== VAR_CONST
)
5887 size
+= sizeof(VARIANT
);
5888 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5890 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5891 if (!dest
) return E_OUTOFMEMORY
;
5894 buffer
= (char *)(dest
+ 1);
5895 if (src
->lpstrSchema
)
5898 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5899 len
= strlenW(src
->lpstrSchema
);
5900 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5901 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5904 if (src
->varkind
== VAR_CONST
)
5908 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5909 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5910 buffer
+= sizeof(VARIANT
);
5911 VariantInit(dest
->u
.lpvarValue
);
5912 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5915 SysFreeString((BSTR
)dest
);
5919 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5922 if (src
->varkind
== VAR_CONST
)
5923 VariantClear(dest
->u
.lpvarValue
);
5924 SysFreeString((BSTR
)dest
);
5931 /* ITypeInfo::GetVarDesc
5933 * Retrieves a VARDESC structure that describes the specified variable.
5936 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5937 LPVARDESC
*ppVarDesc
)
5939 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5940 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5942 TRACE("(%p) index %d\n", This
, index
);
5944 if(index
>= This
->cVars
)
5945 return TYPE_E_ELEMENTNOTFOUND
;
5947 if (This
->needs_layout
)
5948 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5950 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5953 /* ITypeInfo_GetNames
5955 * Retrieves the variable with the specified member ID (or the name of the
5956 * property or method and its parameters) that correspond to the specified
5959 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5960 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5962 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5963 const TLBFuncDesc
*pFDesc
;
5964 const TLBVarDesc
*pVDesc
;
5966 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5967 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
5970 /* function found, now return function and parameter names */
5971 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5974 *rgBstrNames
=SysAllocString(TLB_get_bstr(pFDesc
->Name
));
5976 rgBstrNames
[i
]=SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
-1].Name
));
5982 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
5985 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
5990 if(This
->impltypes
&&
5991 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
5992 /* recursive search */
5995 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5996 if(SUCCEEDED(result
))
5998 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5999 ITypeInfo_Release(pTInfo
);
6002 WARN("Could not search inherited interface!\n");
6006 WARN("no names found\n");
6009 return TYPE_E_ELEMENTNOTFOUND
;
6016 /* ITypeInfo::GetRefTypeOfImplType
6018 * If a type description describes a COM class, it retrieves the type
6019 * description of the implemented interface types. For an interface,
6020 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6024 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6029 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6032 TRACE("(%p) index %d\n", This
, index
);
6033 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6037 /* only valid on dual interfaces;
6038 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6041 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6047 hr
= TYPE_E_ELEMENTNOTFOUND
;
6050 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6052 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6053 *pRefType
= This
->pTypeLib
->dispatch_href
;
6057 if(index
>= This
->cImplTypes
)
6058 hr
= TYPE_E_ELEMENTNOTFOUND
;
6060 *pRefType
= This
->impltypes
[index
].hRef
;
6066 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6068 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6074 /* ITypeInfo::GetImplTypeFlags
6076 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6077 * or base interface in a type description.
6079 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6080 UINT index
, INT
*pImplTypeFlags
)
6082 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6084 TRACE("(%p) index %d\n", This
, index
);
6087 return E_INVALIDARG
;
6089 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6090 *pImplTypeFlags
= 0;
6094 if(index
>= This
->cImplTypes
)
6095 return TYPE_E_ELEMENTNOTFOUND
;
6097 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6103 * Maps between member names and member IDs, and parameter names and
6106 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6107 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6109 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6110 const TLBVarDesc
*pVDesc
;
6114 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6117 /* init out parameters in case of failure */
6118 for (i
= 0; i
< cNames
; i
++)
6119 pMemId
[i
] = MEMBERID_NIL
;
6121 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6123 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6124 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6125 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6126 for(i
=1; i
< cNames
; i
++){
6127 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6128 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6130 if( j
<pFDesc
->funcdesc
.cParams
)
6133 ret
=DISP_E_UNKNOWNNAME
;
6135 TRACE("-- 0x%08x\n", ret
);
6139 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6142 *pMemId
= pVDesc
->vardesc
.memid
;
6145 /* not found, see if it can be found in an inherited interface */
6146 if(This
->impltypes
) {
6147 /* recursive search */
6149 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6151 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6152 ITypeInfo_Release(pTInfo
);
6155 WARN("Could not search inherited interface!\n");
6157 WARN("no names found\n");
6158 return DISP_E_UNKNOWNNAME
;
6164 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6165 __ASM_GLOBAL_FUNC( call_method
,
6167 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6168 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6169 "movl %esp,%ebp\n\t"
6170 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6172 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6174 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6175 "movl 12(%ebp),%edx\n\t"
6176 "movl %esp,%edi\n\t"
6179 "subl %edx,%edi\n\t"
6180 "andl $~15,%edi\n\t"
6181 "movl %edi,%esp\n\t"
6182 "movl 12(%ebp),%ecx\n\t"
6183 "movl 16(%ebp),%esi\n\t"
6186 "1:\tcall *8(%ebp)\n\t"
6187 "subl %esp,%edi\n\t"
6188 "movl 20(%ebp),%ecx\n\t"
6189 "movl %edi,(%ecx)\n\t"
6190 "leal -8(%ebp),%esp\n\t"
6192 __ASM_CFI(".cfi_same_value %edi\n\t")
6194 __ASM_CFI(".cfi_same_value %esi\n\t")
6196 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6197 __ASM_CFI(".cfi_same_value %ebp\n\t")
6200 /* same function but returning floating point */
6201 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6203 /* ITypeInfo::Invoke
6205 * Invokes a method, or accesses a property of an object, that implements the
6206 * interface described by the type description.
6209 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6213 if (TRACE_ON(ole
)) {
6215 TRACE("Calling %p(",func
);
6216 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6217 if (nrargs
> 30) TRACE("...");
6224 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6227 FIXME("unsupported calling convention %d\n",callconv
);
6231 TRACE("returns %08x\n",res
);
6235 #elif defined(__x86_64__)
6237 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6238 __ASM_GLOBAL_FUNC( call_method
,
6240 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6241 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6242 "movq %rsp,%rbp\n\t"
6243 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6245 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6247 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6248 "movq %rcx,%rax\n\t"
6251 "cmovgq %rdx,%rcx\n\t"
6252 "leaq 0(,%rcx,8),%rdx\n\t"
6253 "subq %rdx,%rsp\n\t"
6254 "andq $~15,%rsp\n\t"
6255 "movq %rsp,%rdi\n\t"
6258 "movq 0(%rsp),%rcx\n\t"
6259 "movq 8(%rsp),%rdx\n\t"
6260 "movq 16(%rsp),%r8\n\t"
6261 "movq 24(%rsp),%r9\n\t"
6262 "movq %rcx,%xmm0\n\t"
6263 "movq %rdx,%xmm1\n\t"
6264 "movq %r8,%xmm2\n\t"
6265 "movq %r9,%xmm3\n\t"
6267 "leaq -16(%rbp),%rsp\n\t"
6269 __ASM_CFI(".cfi_same_value %rdi\n\t")
6271 __ASM_CFI(".cfi_same_value %rsi\n\t")
6272 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6274 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6275 __ASM_CFI(".cfi_same_value %rbp\n\t")
6278 /* same function but returning floating point */
6279 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6281 #endif /* __x86_64__ */
6283 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6286 ITypeInfo
*tinfo2
= NULL
;
6287 TYPEATTR
*tattr
= NULL
;
6289 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6292 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6294 tdesc
->u
.hreftype
, hr
);
6297 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6300 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6301 ITypeInfo_Release(tinfo2
);
6305 switch (tattr
->typekind
)
6312 tdesc
= &tattr
->tdescAlias
;
6313 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6316 case TKIND_INTERFACE
:
6317 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6323 case TKIND_DISPATCH
:
6332 FIXME("TKIND_RECORD unhandled.\n");
6337 FIXME("TKIND_UNION unhandled.\n");
6342 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6346 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6347 ITypeInfo_Release(tinfo2
);
6351 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6355 /* enforce only one level of pointer indirection */
6356 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6358 tdesc
= tdesc
->u
.lptdesc
;
6360 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6361 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6362 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6363 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6364 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6366 VARTYPE vt_userdefined
= 0;
6367 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6368 if (tdesc
->vt
== VT_PTR
)
6370 vt_userdefined
= VT_BYREF
;
6371 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6373 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6375 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6376 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6378 *vt
|= vt_userdefined
;
6390 case VT_USERDEFINED
:
6391 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6398 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6399 hr
= DISP_E_BADVARTYPE
;
6403 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6418 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6424 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6428 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6430 ITypeInfo_Release(tinfo2
);
6434 switch(tattr
->typekind
) {
6436 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6439 case TKIND_INTERFACE
:
6440 case TKIND_DISPATCH
:
6441 *guid
= tattr
->guid
;
6445 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6446 hres
= E_UNEXPECTED
;
6449 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6450 ITypeInfo_Release(tinfo2
);
6454 /***********************************************************************
6455 * DispCallFunc (OLEAUT32.@)
6457 * Invokes a function of the specified calling convention, passing the
6458 * specified arguments and returns the result.
6461 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6462 * oVft [I] The offset in the vtable. See notes.
6463 * cc [I] Calling convention of the function to call.
6464 * vtReturn [I] The return type of the function.
6465 * cActuals [I] Number of parameters.
6466 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6467 * prgpvarg [I] The arguments to pass.
6468 * pvargResult [O] The return value of the function. Can be NULL.
6472 * Failure: HRESULT code.
6475 * The HRESULT return value of this function is not affected by the return
6476 * value of the user supplied function, which is returned in pvargResult.
6478 * If pvInstance is NULL then a non-object function is to be called and oVft
6479 * is the address of the function to call.
6481 * The cc parameter can be one of the following values:
6494 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6495 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6498 int argspos
, stack_offset
;
6503 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6504 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6505 pvargResult
, V_VT(pvargResult
));
6507 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6509 FIXME("unsupported calling convention %d\n",cc
);
6510 return E_INVALIDARG
;
6513 /* maximum size for an argument is sizeof(VARIANT) */
6514 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6516 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6520 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6521 func
= vtable
[oVft
/sizeof(void *)];
6522 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6524 else func
= (void *)oVft
;
6526 for (i
= 0; i
< cActuals
; i
++)
6528 VARIANT
*arg
= prgpvarg
[i
];
6539 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6540 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6544 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6545 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6547 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6548 args
[argspos
++] = V_BOOL(arg
);
6551 args
[argspos
++] = V_UI4(arg
);
6554 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6561 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6564 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6568 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6572 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6573 call_method( func
, argspos
, args
, &stack_offset
);
6578 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6581 WARN("invalid return type %u\n", vtReturn
);
6583 return E_INVALIDARG
;
6585 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6589 if (stack_offset
&& cc
== CC_STDCALL
)
6591 WARN( "stack pointer off by %d\n", stack_offset
);
6592 return DISP_E_BADCALLEE
;
6594 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6595 TRACE("retval: "); dump_Variant(pvargResult
);
6598 #elif defined(__x86_64__)
6604 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6605 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6606 pvargResult
, V_VT(pvargResult
));
6608 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6610 FIXME("unsupported calling convention %d\n",cc
);
6611 return E_INVALIDARG
;
6614 /* maximum size for an argument is sizeof(DWORD_PTR) */
6615 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6617 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6621 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6622 func
= vtable
[oVft
/sizeof(void *)];
6623 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6625 else func
= (void *)oVft
;
6627 for (i
= 0; i
< cActuals
; i
++)
6629 VARIANT
*arg
= prgpvarg
[i
];
6635 args
[argspos
++] = (ULONG_PTR
)arg
;
6637 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6638 args
[argspos
++] = V_BOOL(arg
);
6641 args
[argspos
++] = V_UI8(arg
);
6644 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6651 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6655 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6659 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6660 call_method( func
, argspos
, args
);
6663 WARN("invalid return type %u\n", vtReturn
);
6665 return E_INVALIDARG
;
6667 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6671 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6672 TRACE("retval: "); dump_Variant(pvargResult
);
6676 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6677 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6682 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6684 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6687 #define INVBUF_ELEMENT_SIZE \
6688 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6689 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6690 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6691 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6692 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6693 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6694 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6695 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6697 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6702 DISPPARAMS
*pDispParams
,
6703 VARIANT
*pVarResult
,
6704 EXCEPINFO
*pExcepInfo
,
6707 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6709 unsigned int var_index
;
6712 const TLBFuncDesc
*pFuncInfo
;
6715 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6716 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6719 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6720 return DISP_E_MEMBERNOTFOUND
;
6724 ERR("NULL pDispParams not allowed\n");
6725 return E_INVALIDARG
;
6728 dump_DispParms(pDispParams
);
6730 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6732 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6733 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6734 return E_INVALIDARG
;
6737 /* we do this instead of using GetFuncDesc since it will return a fake
6738 * FUNCDESC for dispinterfaces and we want the real function description */
6739 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6740 pFuncInfo
= &This
->funcdescs
[fdc
];
6741 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6742 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6743 !func_restricted( &pFuncInfo
->funcdesc
))
6747 if (fdc
< This
->cFuncs
) {
6748 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6752 TRACE("invoking:\n");
6753 dump_TLBFuncDescOne(pFuncInfo
);
6756 switch (func_desc
->funckind
) {
6757 case FUNC_PUREVIRTUAL
:
6758 case FUNC_VIRTUAL
: {
6759 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6761 VARIANT retval
; /* pointer for storing byref retvals in */
6762 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6763 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6764 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6765 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6766 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6767 UINT vargs_converted
=0;
6771 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6773 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6775 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6776 hres
= DISP_E_PARAMNOTFOUND
;
6781 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6783 ERR("functions with the vararg attribute do not support named arguments\n");
6784 hres
= DISP_E_NONAMEDARGS
;
6788 for (i
= 0; i
< func_desc
->cParams
; i
++)
6790 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6791 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6796 TRACE("changing args\n");
6797 for (i
= 0; i
< func_desc
->cParams
; i
++)
6799 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6800 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6801 VARIANTARG
*src_arg
;
6803 if (wParamFlags
& PARAMFLAG_FLCID
)
6806 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6808 V_I4(arg
) = This
->pTypeLib
->lcid
;
6817 for (j
= 0; j
< cNamedArgs
; j
++)
6818 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6820 src_arg
= &pDispParams
->rgvarg
[j
];
6825 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6827 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6831 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6833 /* under most conditions the caller is not allowed to
6834 * pass in a dispparam arg in the index of what would be
6835 * the retval parameter. however, there is an exception
6836 * where the extra parameter is used in an extra
6837 * IDispatch::Invoke below */
6838 if ((i
< pDispParams
->cArgs
) &&
6839 ((func_desc
->cParams
!= 1) || !pVarResult
||
6840 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6842 hres
= DISP_E_BADPARAMCOUNT
;
6846 /* note: this check is placed so that if the caller passes
6847 * in a VARIANTARG for the retval we just ignore it, like
6849 if (i
== func_desc
->cParams
- 1)
6852 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6853 memset(arg
, 0, sizeof(*arg
));
6854 V_VT(arg
) = rgvt
[i
];
6855 memset(&retval
, 0, sizeof(retval
));
6856 V_BYREF(arg
) = &retval
;
6860 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6861 hres
= E_UNEXPECTED
;
6867 dump_Variant(src_arg
);
6869 if(rgvt
[i
]!=V_VT(src_arg
))
6871 if (rgvt
[i
] == VT_VARIANT
)
6872 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6873 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6875 if (rgvt
[i
] == V_VT(src_arg
))
6876 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6879 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6880 if (wParamFlags
& PARAMFLAG_FIN
)
6881 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6882 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6884 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6886 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6889 SAFEARRAYBOUND bound
;
6893 bound
.cElements
= pDispParams
->cArgs
-i
;
6894 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6896 ERR("SafeArrayCreate failed\n");
6899 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6902 ERR("SafeArrayAccessData failed with %x\n", hres
);
6903 SafeArrayDestroy(a
);
6906 for (j
= 0; j
< bound
.cElements
; j
++)
6907 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6908 hres
= SafeArrayUnaccessData(a
);
6911 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6912 SafeArrayDestroy(a
);
6915 V_ARRAY(&rgvarg
[i
]) = a
;
6916 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6918 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6920 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6921 if (wParamFlags
& PARAMFLAG_FIN
)
6922 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6924 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6925 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6926 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6928 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6930 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6931 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6935 /* FIXME: this doesn't work for VT_BYREF arguments if
6936 * they are not the same type as in the paramdesc */
6937 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6938 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6939 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6944 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6945 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6946 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6949 prgpvarg
[i
] = &rgvarg
[i
];
6953 prgpvarg
[i
] = src_arg
;
6956 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
6957 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
6958 && V_UNKNOWN(prgpvarg
[i
])) {
6959 IUnknown
*userdefined_iface
;
6962 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
6966 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
6968 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
6972 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
6973 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
6976 else if (wParamFlags
& PARAMFLAG_FOPT
)
6979 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6980 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6982 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6988 VARIANTARG
*missing_arg
;
6989 /* if the function wants a pointer to a variant then
6990 * set that up, otherwise just pass the VT_ERROR in
6991 * the argument by value */
6992 if (rgvt
[i
] & VT_BYREF
)
6994 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6995 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6996 V_VARIANTREF(arg
) = missing_arg
;
7000 V_VT(missing_arg
) = VT_ERROR
;
7001 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7006 hres
= DISP_E_BADPARAMCOUNT
;
7010 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7012 /* VT_VOID is a special case for return types, so it is not
7013 * handled in the general function */
7014 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7015 V_VT(&varresult
) = VT_EMPTY
;
7018 V_VT(&varresult
) = 0;
7019 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7020 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7023 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7024 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7025 prgpvarg
, &varresult
);
7027 vargs_converted
= 0;
7029 for (i
= 0; i
< func_desc
->cParams
; i
++)
7031 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7032 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7034 if (wParamFlags
& PARAMFLAG_FLCID
)
7036 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7040 TRACE("[retval] value: ");
7041 dump_Variant(prgpvarg
[i
]);
7046 VariantInit(pVarResult
);
7047 /* deref return value */
7048 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7051 VARIANT_ClearInd(prgpvarg
[i
]);
7053 else if (vargs_converted
< pDispParams
->cArgs
)
7055 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7056 if (wParamFlags
& PARAMFLAG_FOUT
)
7058 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7060 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7064 ERR("failed to convert param %d to vt %d\n", i
,
7065 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7070 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7071 func_desc
->cParamsOpt
< 0 &&
7072 i
== func_desc
->cParams
-1)
7074 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7077 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7080 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7083 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7086 ERR("SafeArrayAccessData failed with %x\n", hres
);
7089 for (j
= 0; j
<= ubound
; j
++)
7090 VariantClear(&v
[j
]);
7091 hres
= SafeArrayUnaccessData(a
);
7094 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7098 VariantClear(&rgvarg
[i
]);
7101 else if (wParamFlags
& PARAMFLAG_FOPT
)
7103 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7104 VariantClear(&rgvarg
[i
]);
7107 VariantClear(&missing_arg
[i
]);
7110 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7112 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7113 hres
= DISP_E_EXCEPTION
;
7116 IErrorInfo
*pErrorInfo
;
7117 pExcepInfo
->scode
= V_ERROR(&varresult
);
7118 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7120 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7121 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7122 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7123 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7125 IErrorInfo_Release(pErrorInfo
);
7129 if (V_VT(&varresult
) != VT_ERROR
)
7131 TRACE("varresult value: ");
7132 dump_Variant(&varresult
);
7136 VariantClear(pVarResult
);
7137 *pVarResult
= varresult
;
7140 VariantClear(&varresult
);
7143 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7144 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7145 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7146 (pDispParams
->cArgs
!= 0))
7148 if (V_VT(pVarResult
) == VT_DISPATCH
)
7150 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7151 /* Note: not VariantClear; we still need the dispatch
7152 * pointer to be valid */
7153 VariantInit(pVarResult
);
7154 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7155 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7156 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7157 IDispatch_Release(pDispatch
);
7161 VariantClear(pVarResult
);
7162 hres
= DISP_E_NOTACOLLECTION
;
7170 case FUNC_DISPATCH
: {
7173 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7174 if (SUCCEEDED(hres
)) {
7175 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7176 hres
= IDispatch_Invoke(
7177 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7178 pVarResult
,pExcepInfo
,pArgErr
7181 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7182 IDispatch_Release(disp
);
7184 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7188 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7193 TRACE("-- 0x%08x\n", hres
);
7196 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7199 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7200 if(FAILED(hres
)) return hres
;
7202 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7203 dump_VARDESC(var_desc
);
7204 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7208 /* not found, look for it in inherited interfaces */
7209 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7210 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7211 if(This
->impltypes
) {
7212 /* recursive search */
7214 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7215 if(SUCCEEDED(hres
)){
7216 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7217 ITypeInfo_Release(pTInfo
);
7220 WARN("Could not search inherited interface!\n");
7223 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7224 return DISP_E_MEMBERNOTFOUND
;
7227 /* ITypeInfo::GetDocumentation
7229 * Retrieves the documentation string, the complete Help file name and path,
7230 * and the context ID for the Help topic for a specified type description.
7232 * (Can be tested by the Visual Basic Editor in Word for instance.)
7234 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7235 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7236 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7238 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7239 const TLBFuncDesc
*pFDesc
;
7240 const TLBVarDesc
*pVDesc
;
7241 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7242 " HelpContext(%p) HelpFile(%p)\n",
7243 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7244 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7246 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7248 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7250 *pdwHelpContext
=This
->dwHelpContext
;
7252 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7254 }else {/* for a member */
7255 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7258 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7260 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7262 *pdwHelpContext
=pFDesc
->helpcontext
;
7264 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7267 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7270 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7272 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7274 *pdwHelpContext
=pVDesc
->HelpContext
;
7276 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7281 if(This
->impltypes
&&
7282 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7283 /* recursive search */
7286 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7287 if(SUCCEEDED(result
)) {
7288 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7289 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7290 ITypeInfo_Release(pTInfo
);
7293 WARN("Could not search inherited interface!\n");
7296 WARN("member %d not found\n", memid
);
7297 return TYPE_E_ELEMENTNOTFOUND
;
7300 /* ITypeInfo::GetDllEntry
7302 * Retrieves a description or specification of an entry point for a function
7305 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7306 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7309 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7310 const TLBFuncDesc
*pFDesc
;
7312 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7314 if (pBstrDllName
) *pBstrDllName
= NULL
;
7315 if (pBstrName
) *pBstrName
= NULL
;
7316 if (pwOrdinal
) *pwOrdinal
= 0;
7318 if (This
->typekind
!= TKIND_MODULE
)
7319 return TYPE_E_BADMODULEKIND
;
7321 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7323 dump_TypeInfo(This
);
7325 dump_TLBFuncDescOne(pFDesc
);
7328 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7330 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7332 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7340 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7343 return TYPE_E_ELEMENTNOTFOUND
;
7346 /* internal function to make the inherited interfaces' methods appear
7347 * part of the interface */
7348 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7349 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7351 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7354 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7356 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7358 ITypeInfo
*pSubTypeInfo
;
7360 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7364 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7366 ITypeInfo_Release(pSubTypeInfo
);
7370 *hRefType
-= DISPATCH_HREF_OFFSET
;
7372 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7373 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7378 /* ITypeInfo::GetRefTypeInfo
7380 * If a type description references other type descriptions, it retrieves
7381 * the referenced type descriptions.
7383 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7386 ITypeInfo
**ppTInfo
)
7388 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7389 HRESULT result
= E_FAIL
;
7392 return E_INVALIDARG
;
7394 if ((INT
)hRefType
< 0) {
7395 ITypeInfoImpl
*pTypeInfoImpl
;
7397 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7398 !(This
->typekind
== TKIND_INTERFACE
||
7399 This
->typekind
== TKIND_DISPATCH
))
7400 return TYPE_E_ELEMENTNOTFOUND
;
7402 /* when we meet a DUAL typeinfo, we must create the alternate
7405 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7407 *pTypeInfoImpl
= *This
;
7408 pTypeInfoImpl
->ref
= 0;
7410 if (This
->typekind
== TKIND_INTERFACE
)
7411 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7413 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7415 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7416 /* the AddRef implicitly adds a reference to the parent typelib, which
7417 * stops the copied data from being destroyed until the new typeinfo's
7418 * refcount goes to zero, but we need to signal to the new instance to
7419 * not free its data structures when it is destroyed */
7420 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7422 ITypeInfo_AddRef(*ppTInfo
);
7425 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7426 (This
->typekind
== TKIND_DISPATCH
))
7428 HREFTYPE href_dispatch
= hRefType
;
7429 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7431 TLBRefType
*ref_type
;
7432 ITypeLib
*pTLib
= NULL
;
7435 if(!(hRefType
& 0x1)){
7436 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7438 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7441 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7442 ITypeInfo_AddRef(*ppTInfo
);
7446 result
= TYPE_E_ELEMENTNOTFOUND
;
7450 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7452 if(ref_type
->reference
== (hRefType
& (~0x3)))
7455 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7457 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7461 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7463 TRACE("internal reference\n");
7464 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7466 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7467 TRACE("typeinfo in imported typelib that is already loaded\n");
7468 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7469 ITypeLib_AddRef(pTLib
);
7472 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7473 result
= LoadRegTypeLib( TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7474 ref_type
->pImpTLInfo
->wVersionMajor
,
7475 ref_type
->pImpTLInfo
->wVersionMinor
,
7476 ref_type
->pImpTLInfo
->lcid
,
7479 if(FAILED(result
)) {
7480 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
7481 result
=LoadTypeLib(libnam
, &pTLib
);
7482 SysFreeString(libnam
);
7484 if(SUCCEEDED(result
)) {
7485 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7486 ITypeLib_AddRef(pTLib
);
7490 if(SUCCEEDED(result
)) {
7491 if(ref_type
->index
== TLB_REF_USE_GUID
)
7492 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7494 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7497 ITypeLib_Release(pTLib
);
7501 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7502 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7506 /* ITypeInfo::AddressOfMember
7508 * Retrieves the addresses of static functions or variables, such as those
7511 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7512 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7514 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7520 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7522 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7526 module
= LoadLibraryW(dll
);
7529 ERR("couldn't load %s\n", debugstr_w(dll
));
7531 SysFreeString(entry
);
7532 return STG_E_FILENOTFOUND
;
7534 /* FIXME: store library somewhere where we can free it */
7539 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7540 entryA
= heap_alloc(len
);
7541 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7543 *ppv
= GetProcAddress(module
, entryA
);
7545 ERR("function not found %s\n", debugstr_a(entryA
));
7551 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7553 ERR("function not found %d\n", ordinal
);
7557 SysFreeString(entry
);
7560 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7565 /* ITypeInfo::CreateInstance
7567 * Creates a new instance of a type that describes a component object class
7570 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7571 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7573 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7577 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7583 WARN("Not able to aggregate\n");
7584 return CLASS_E_NOAGGREGATION
;
7587 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7588 if(FAILED(hr
)) return hr
;
7590 if(pTA
->typekind
!= TKIND_COCLASS
)
7592 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7598 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7601 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7602 TRACE("GetActiveObject rets %08x\n", hr
);
7605 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7606 IUnknown_Release(pUnk
);
7611 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7612 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7616 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7620 /* ITypeInfo::GetMops
7622 * Retrieves marshalling information.
7624 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7627 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7628 FIXME("(%p %d) stub!\n", This
, memid
);
7633 /* ITypeInfo::GetContainingTypeLib
7635 * Retrieves the containing type library and the index of the type description
7636 * within that type library.
7638 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7639 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7641 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7643 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7645 *pIndex
=This
->index
;
7646 TRACE("returning pIndex=%d\n", *pIndex
);
7650 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7651 ITypeLib_AddRef(*ppTLib
);
7652 TRACE("returning ppTLib=%p\n", *ppTLib
);
7658 /* ITypeInfo::ReleaseTypeAttr
7660 * Releases a TYPEATTR previously returned by Get
7663 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7664 TYPEATTR
* pTypeAttr
)
7666 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7667 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7668 heap_free(pTypeAttr
);
7671 /* ITypeInfo::ReleaseFuncDesc
7673 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7675 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7677 FUNCDESC
*pFuncDesc
)
7679 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7682 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7684 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7685 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7686 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7688 SysFreeString((BSTR
)pFuncDesc
);
7691 /* ITypeInfo::ReleaseVarDesc
7693 * Releases a VARDESC previously returned by GetVarDesc.
7695 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7698 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7699 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7701 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
7702 if (pVarDesc
->varkind
== VAR_CONST
)
7703 VariantClear(pVarDesc
->u
.lpvarValue
);
7704 SysFreeString((BSTR
)pVarDesc
);
7707 /* ITypeInfo2::GetTypeKind
7709 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7712 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7713 TYPEKIND
*pTypeKind
)
7715 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7716 *pTypeKind
=This
->typekind
;
7717 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7721 /* ITypeInfo2::GetTypeFlags
7723 * Returns the type flags without any allocations. This returns a DWORD type
7724 * flag, which expands the type flags without growing the TYPEATTR (type
7728 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7730 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7731 *pTypeFlags
=This
->wTypeFlags
;
7732 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7736 /* ITypeInfo2::GetFuncIndexOfMemId
7737 * Binds to a specific member based on a known DISPID, where the member name
7738 * is not known (for example, when binding to a default member).
7741 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7742 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7744 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7748 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7749 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7750 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7753 if(fdc
< This
->cFuncs
) {
7757 result
= TYPE_E_ELEMENTNOTFOUND
;
7759 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7760 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7764 /* TypeInfo2::GetVarIndexOfMemId
7766 * Binds to a specific member based on a known DISPID, where the member name
7767 * is not known (for example, when binding to a default member).
7770 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7771 MEMBERID memid
, UINT
*pVarIndex
)
7773 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7774 TLBVarDesc
*pVarInfo
;
7776 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7778 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7780 return TYPE_E_ELEMENTNOTFOUND
;
7782 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7787 /* ITypeInfo2::GetCustData
7789 * Gets the custom data
7791 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7796 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7797 TLBCustData
*pCData
;
7799 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7801 if(!guid
|| !pVarVal
)
7802 return E_INVALIDARG
;
7804 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
7806 VariantInit( pVarVal
);
7808 VariantCopy( pVarVal
, &pCData
->data
);
7810 VariantClear( pVarVal
);
7814 /* ITypeInfo2::GetFuncCustData
7816 * Gets the custom data
7818 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7824 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7825 TLBCustData
*pCData
;
7826 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7828 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7830 if(index
>= This
->cFuncs
)
7831 return TYPE_E_ELEMENTNOTFOUND
;
7833 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7835 return TYPE_E_ELEMENTNOTFOUND
;
7837 VariantInit(pVarVal
);
7838 VariantCopy(pVarVal
, &pCData
->data
);
7843 /* ITypeInfo2::GetParamCustData
7845 * Gets the custom data
7847 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7854 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7855 TLBCustData
*pCData
;
7856 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7858 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7859 debugstr_guid(guid
), pVarVal
);
7861 if(indexFunc
>= This
->cFuncs
)
7862 return TYPE_E_ELEMENTNOTFOUND
;
7864 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7865 return TYPE_E_ELEMENTNOTFOUND
;
7867 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7869 return TYPE_E_ELEMENTNOTFOUND
;
7871 VariantInit(pVarVal
);
7872 VariantCopy(pVarVal
, &pCData
->data
);
7877 /* ITypeInfo2::GetVarCustData
7879 * Gets the custom data
7881 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7887 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7888 TLBCustData
*pCData
;
7889 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7891 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7893 if(index
>= This
->cVars
)
7894 return TYPE_E_ELEMENTNOTFOUND
;
7896 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7898 return TYPE_E_ELEMENTNOTFOUND
;
7900 VariantInit(pVarVal
);
7901 VariantCopy(pVarVal
, &pCData
->data
);
7906 /* ITypeInfo2::GetImplCustData
7908 * Gets the custom data
7910 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7916 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7917 TLBCustData
*pCData
;
7918 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7920 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7922 if(index
>= This
->cImplTypes
)
7923 return TYPE_E_ELEMENTNOTFOUND
;
7925 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7927 return TYPE_E_ELEMENTNOTFOUND
;
7929 VariantInit(pVarVal
);
7930 VariantCopy(pVarVal
, &pCData
->data
);
7935 /* ITypeInfo2::GetDocumentation2
7937 * Retrieves the documentation string, the complete Help file name and path,
7938 * the localization context to use, and the context ID for the library Help
7939 * topic in the Help file.
7942 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7946 BSTR
*pbstrHelpString
,
7947 DWORD
*pdwHelpStringContext
,
7948 BSTR
*pbstrHelpStringDll
)
7950 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7951 const TLBFuncDesc
*pFDesc
;
7952 const TLBVarDesc
*pVDesc
;
7953 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7954 "HelpStringContext(%p) HelpStringDll(%p)\n",
7955 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7956 pbstrHelpStringDll
);
7957 /* the help string should be obtained from the helpstringdll,
7958 * using the _DLLGetDocumentation function, based on the supplied
7959 * lcid. Nice to do sometime...
7961 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7963 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
7964 if(pdwHelpStringContext
)
7965 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7966 if(pbstrHelpStringDll
)
7967 *pbstrHelpStringDll
=
7968 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7970 }else {/* for a member */
7971 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7974 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7975 if(pdwHelpStringContext
)
7976 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7977 if(pbstrHelpStringDll
)
7978 *pbstrHelpStringDll
=
7979 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7982 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7985 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7986 if(pdwHelpStringContext
)
7987 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7988 if(pbstrHelpStringDll
)
7989 *pbstrHelpStringDll
=
7990 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7994 return TYPE_E_ELEMENTNOTFOUND
;
7997 /* ITypeInfo2::GetAllCustData
7999 * Gets all custom data items for the Type info.
8002 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8004 CUSTDATA
*pCustData
)
8006 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8008 TRACE("%p %p\n", This
, pCustData
);
8010 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
8013 /* ITypeInfo2::GetAllFuncCustData
8015 * Gets all custom data items for the specified Function
8018 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8021 CUSTDATA
*pCustData
)
8023 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8024 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8026 TRACE("%p %u %p\n", This
, index
, pCustData
);
8028 if(index
>= This
->cFuncs
)
8029 return TYPE_E_ELEMENTNOTFOUND
;
8031 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8034 /* ITypeInfo2::GetAllParamCustData
8036 * Gets all custom data items for the Functions
8039 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8040 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8042 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8043 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8045 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8047 if(indexFunc
>= This
->cFuncs
)
8048 return TYPE_E_ELEMENTNOTFOUND
;
8050 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8051 return TYPE_E_ELEMENTNOTFOUND
;
8053 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8056 /* ITypeInfo2::GetAllVarCustData
8058 * Gets all custom data items for the specified Variable
8061 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8062 UINT index
, CUSTDATA
*pCustData
)
8064 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8065 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8067 TRACE("%p %u %p\n", This
, index
, pCustData
);
8069 if(index
>= This
->cVars
)
8070 return TYPE_E_ELEMENTNOTFOUND
;
8072 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8075 /* ITypeInfo2::GetAllImplCustData
8077 * Gets all custom data items for the specified implementation type
8080 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8083 CUSTDATA
*pCustData
)
8085 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8086 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8088 TRACE("%p %u %p\n", This
, index
, pCustData
);
8090 if(index
>= This
->cImplTypes
)
8091 return TYPE_E_ELEMENTNOTFOUND
;
8093 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8096 static const ITypeInfo2Vtbl tinfvt
=
8099 ITypeInfo_fnQueryInterface
,
8101 ITypeInfo_fnRelease
,
8103 ITypeInfo_fnGetTypeAttr
,
8104 ITypeInfo_fnGetTypeComp
,
8105 ITypeInfo_fnGetFuncDesc
,
8106 ITypeInfo_fnGetVarDesc
,
8107 ITypeInfo_fnGetNames
,
8108 ITypeInfo_fnGetRefTypeOfImplType
,
8109 ITypeInfo_fnGetImplTypeFlags
,
8110 ITypeInfo_fnGetIDsOfNames
,
8112 ITypeInfo_fnGetDocumentation
,
8113 ITypeInfo_fnGetDllEntry
,
8114 ITypeInfo_fnGetRefTypeInfo
,
8115 ITypeInfo_fnAddressOfMember
,
8116 ITypeInfo_fnCreateInstance
,
8117 ITypeInfo_fnGetMops
,
8118 ITypeInfo_fnGetContainingTypeLib
,
8119 ITypeInfo_fnReleaseTypeAttr
,
8120 ITypeInfo_fnReleaseFuncDesc
,
8121 ITypeInfo_fnReleaseVarDesc
,
8123 ITypeInfo2_fnGetTypeKind
,
8124 ITypeInfo2_fnGetTypeFlags
,
8125 ITypeInfo2_fnGetFuncIndexOfMemId
,
8126 ITypeInfo2_fnGetVarIndexOfMemId
,
8127 ITypeInfo2_fnGetCustData
,
8128 ITypeInfo2_fnGetFuncCustData
,
8129 ITypeInfo2_fnGetParamCustData
,
8130 ITypeInfo2_fnGetVarCustData
,
8131 ITypeInfo2_fnGetImplTypeCustData
,
8132 ITypeInfo2_fnGetDocumentation2
,
8133 ITypeInfo2_fnGetAllCustData
,
8134 ITypeInfo2_fnGetAllFuncCustData
,
8135 ITypeInfo2_fnGetAllParamCustData
,
8136 ITypeInfo2_fnGetAllVarCustData
,
8137 ITypeInfo2_fnGetAllImplTypeCustData
,
8140 /******************************************************************************
8141 * CreateDispTypeInfo [OLEAUT32.31]
8143 * Build type information for an object so it can be called through an
8144 * IDispatch interface.
8147 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8148 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8151 * This call allows an objects methods to be accessed through IDispatch, by
8152 * building an ITypeInfo object that IDispatch can use to call through.
8154 HRESULT WINAPI
CreateDispTypeInfo(
8155 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8156 LCID lcid
, /* [I] Locale Id */
8157 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8159 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8160 ITypeLibImpl
*pTypeLibImpl
;
8161 unsigned int param
, func
;
8162 TLBFuncDesc
*pFuncDesc
;
8166 pTypeLibImpl
= TypeLibImpl_Constructor();
8167 if (!pTypeLibImpl
) return E_FAIL
;
8169 pTypeLibImpl
->TypeInfoCount
= 2;
8170 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8172 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8173 pTIIface
->pTypeLib
= pTypeLibImpl
;
8174 pTIIface
->index
= 0;
8175 pTIIface
->Name
= NULL
;
8176 pTIIface
->dwHelpContext
= -1;
8177 pTIIface
->guid
= NULL
;
8178 pTIIface
->lcid
= lcid
;
8179 pTIIface
->typekind
= TKIND_INTERFACE
;
8180 pTIIface
->wMajorVerNum
= 0;
8181 pTIIface
->wMinorVerNum
= 0;
8182 pTIIface
->cbAlignment
= 2;
8183 pTIIface
->cbSizeInstance
= -1;
8184 pTIIface
->cbSizeVft
= -1;
8185 pTIIface
->cFuncs
= 0;
8186 pTIIface
->cImplTypes
= 0;
8187 pTIIface
->cVars
= 0;
8188 pTIIface
->wTypeFlags
= 0;
8189 pTIIface
->hreftype
= 0;
8191 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8192 pFuncDesc
= pTIIface
->funcdescs
;
8193 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8194 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8195 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8196 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8197 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8198 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8199 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8200 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8201 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8202 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8203 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8204 pFuncDesc
->funcdesc
.cScodes
= 0;
8205 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8206 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8207 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8208 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8209 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8210 md
->cArgs
* sizeof(ELEMDESC
));
8211 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8212 for(param
= 0; param
< md
->cArgs
; param
++) {
8213 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8214 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8216 pFuncDesc
->helpcontext
= 0;
8217 pFuncDesc
->HelpStringContext
= 0;
8218 pFuncDesc
->HelpString
= NULL
;
8219 pFuncDesc
->Entry
= NULL
;
8220 list_init(&pFuncDesc
->custdata_list
);
8225 dump_TypeInfo(pTIIface
);
8227 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8228 pTIClass
->pTypeLib
= pTypeLibImpl
;
8229 pTIClass
->index
= 1;
8230 pTIClass
->Name
= NULL
;
8231 pTIClass
->dwHelpContext
= -1;
8232 pTIClass
->guid
= NULL
;
8233 pTIClass
->lcid
= lcid
;
8234 pTIClass
->typekind
= TKIND_COCLASS
;
8235 pTIClass
->wMajorVerNum
= 0;
8236 pTIClass
->wMinorVerNum
= 0;
8237 pTIClass
->cbAlignment
= 2;
8238 pTIClass
->cbSizeInstance
= -1;
8239 pTIClass
->cbSizeVft
= -1;
8240 pTIClass
->cFuncs
= 0;
8241 pTIClass
->cImplTypes
= 1;
8242 pTIClass
->cVars
= 0;
8243 pTIClass
->wTypeFlags
= 0;
8244 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8246 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8248 ref
= heap_alloc_zero(sizeof(*ref
));
8249 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8250 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8252 dump_TypeInfo(pTIClass
);
8254 *pptinfo
= (ITypeInfo
*)pTIClass
;
8256 ITypeInfo_AddRef(*pptinfo
);
8257 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8263 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8265 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8267 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
8270 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8272 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8274 return ITypeInfo_AddRef((ITypeInfo
*)This
);
8277 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8279 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8281 return ITypeInfo_Release((ITypeInfo
*)This
);
8284 static HRESULT WINAPI
ITypeComp_fnBind(
8289 ITypeInfo
** ppTInfo
,
8290 DESCKIND
* pDescKind
,
8293 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8294 const TLBFuncDesc
*pFDesc
;
8295 const TLBVarDesc
*pVDesc
;
8296 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8299 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8301 *pDescKind
= DESCKIND_NONE
;
8302 pBindPtr
->lpfuncdesc
= NULL
;
8305 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8306 pFDesc
= &This
->funcdescs
[fdc
];
8307 if (!strcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8308 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8311 /* name found, but wrong flags */
8312 hr
= TYPE_E_TYPEMISMATCH
;
8316 if (fdc
< This
->cFuncs
)
8318 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8320 &pBindPtr
->lpfuncdesc
,
8321 This
->typekind
== TKIND_DISPATCH
);
8324 *pDescKind
= DESCKIND_FUNCDESC
;
8325 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8326 ITypeInfo_AddRef(*ppTInfo
);
8329 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8331 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8334 *pDescKind
= DESCKIND_VARDESC
;
8335 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8336 ITypeInfo_AddRef(*ppTInfo
);
8340 /* FIXME: search each inherited interface, not just the first */
8341 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8342 /* recursive search */
8346 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8349 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8350 ITypeInfo_Release(pTInfo
);
8354 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8355 ITypeComp_Release(pTComp
);
8358 WARN("Could not search inherited interface!\n");
8360 if (hr
== DISP_E_MEMBERNOTFOUND
)
8362 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8366 static HRESULT WINAPI
ITypeComp_fnBindType(
8370 ITypeInfo
** ppTInfo
,
8371 ITypeComp
** ppTComp
)
8373 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8375 /* strange behaviour (does nothing) but like the
8378 if (!ppTInfo
|| !ppTComp
)
8387 static const ITypeCompVtbl tcompvt
=
8390 ITypeComp_fnQueryInterface
,
8392 ITypeComp_fnRelease
,
8395 ITypeComp_fnBindType
8398 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8399 REFIID riid
, void **object
)
8401 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8403 return ITypeLib2_QueryInterface((ITypeLib2
*)This
, riid
, object
);
8406 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8408 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8410 return ITypeLib2_AddRef((ITypeLib2
*)This
);
8413 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8415 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8417 return ITypeLib2_Release((ITypeLib2
*)This
);
8420 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8421 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8423 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8424 ITypeInfoImpl
*info
;
8427 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8429 if (!ctinfo
|| !name
)
8430 return E_INVALIDARG
;
8432 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8434 return TYPE_E_NAMECONFLICT
;
8436 if (This
->typeinfos
)
8437 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8438 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8440 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8442 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8444 info
->pTypeLib
= This
;
8445 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8446 info
->index
= This
->TypeInfoCount
;
8447 info
->typekind
= kind
;
8448 info
->cbAlignment
= 4;
8450 switch(info
->typekind
) {
8452 case TKIND_INTERFACE
:
8453 case TKIND_DISPATCH
:
8455 info
->cbSizeInstance
= 4;
8459 info
->cbSizeInstance
= 0;
8462 info
->cbSizeInstance
= 2;
8465 info
->cbSizeInstance
= -0x75;
8468 FIXME("unrecognized typekind %d\n", info
->typekind
);
8469 info
->cbSizeInstance
= 0xdeadbeef;
8473 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8474 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8476 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8480 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8482 ++This
->TypeInfoCount
;
8487 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8490 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8492 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8495 return E_INVALIDARG
;
8497 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8502 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8503 WORD majorVerNum
, WORD minorVerNum
)
8505 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8507 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8509 This
->ver_major
= majorVerNum
;
8510 This
->ver_minor
= minorVerNum
;
8515 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8518 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8520 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8522 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
);
8527 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8530 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8532 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8535 return E_INVALIDARG
;
8537 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8542 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8543 LPOLESTR helpFileName
)
8545 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8547 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8550 return E_INVALIDARG
;
8552 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8557 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8560 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8562 TRACE("%p %d\n", This
, helpContext
);
8564 This
->dwHelpContext
= helpContext
;
8569 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8572 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8574 TRACE("%p %x\n", This
, lcid
);
8576 This
->set_lcid
= lcid
;
8581 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8584 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8586 TRACE("%p %x\n", This
, libFlags
);
8588 This
->libflags
= libFlags
;
8593 typedef struct tagWMSFT_SegContents
{
8596 } WMSFT_SegContents
;
8598 typedef struct tagWMSFT_TLBFile
{
8600 WMSFT_SegContents typeinfo_seg
;
8601 WMSFT_SegContents impfile_seg
;
8602 WMSFT_SegContents impinfo_seg
;
8603 WMSFT_SegContents ref_seg
;
8604 WMSFT_SegContents lib_seg
;
8605 WMSFT_SegContents guid_seg
;
8606 WMSFT_SegContents res07_seg
;
8607 WMSFT_SegContents name_seg
;
8608 WMSFT_SegContents string_seg
;
8609 WMSFT_SegContents typdesc_seg
;
8610 WMSFT_SegContents arraydesc_seg
;
8611 WMSFT_SegContents custdata_seg
;
8612 WMSFT_SegContents cdguids_seg
;
8614 WMSFT_SegContents aux_seg
;
8617 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8618 WMSFT_TLBFile
*file
)
8624 file
->string_seg
.len
= 0;
8625 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8628 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8630 return E_UNEXPECTED
;
8632 size
+= sizeof(INT16
);
8634 size
= (size
+ 4) & ~0x3;
8638 file
->string_seg
.len
+= size
;
8640 /* temporarily use str->offset to store the length of the aligned,
8641 * converted string */
8645 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8648 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8651 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8652 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8654 heap_free(file
->string_seg
.data
);
8655 return E_UNEXPECTED
;
8658 *((INT16
*)data
) = size
;
8660 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8664 str
->offset
= last_offs
;
8671 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8672 WMSFT_TLBFile
*file
)
8677 MSFT_NameIntro
*last_intro
= NULL
;
8679 file
->header
.nametablecount
= 0;
8680 file
->header
.nametablechars
= 0;
8682 file
->name_seg
.len
= 0;
8683 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8686 size
= strlenW(str
->str
);
8687 file
->header
.nametablechars
+= size
;
8688 file
->header
.nametablecount
++;
8690 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8692 return E_UNEXPECTED
;
8694 size
+= sizeof(MSFT_NameIntro
);
8696 size
= (size
+ 4) & ~0x3;
8700 file
->name_seg
.len
+= size
;
8702 /* temporarily use str->offset to store the length of the aligned,
8703 * converted string */
8707 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
);
8710 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8712 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8714 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8715 data
+ sizeof(MSFT_NameIntro
),
8716 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8718 heap_free(file
->name_seg
.data
);
8719 return E_UNEXPECTED
;
8721 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8723 intro
->hreftype
= -1; /* TODO? */
8724 intro
->next_hash
= -1;
8725 intro
->namelen
= size
& 0xFF;
8726 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8727 intro
->namelen
|= LHashValOfNameSysA(This
->syskind
,
8728 This
->lcid
, data
+ sizeof(MSFT_NameIntro
)) << 16;
8730 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8731 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8733 /* update str->offset to actual value to use in other
8734 * compilation functions that require positions within
8735 * the string table */
8739 str
->offset
= last_offs
;
8744 last_intro
->hreftype
= 0; /* last one is 0? */
8749 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8752 MSFT_GuidEntry
*entry
;
8755 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8756 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8758 entry
= file
->guid_seg
.data
;
8760 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
8761 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
8762 entry
->hreftype
= 0xFFFFFFFF; /* TODO */
8763 entry
->next_hash
= 0xFFFFFFFF; /* TODO? */
8765 guid
->offset
= offs
;
8767 offs
+= sizeof(MSFT_GuidEntry
);
8772 entry
->next_hash
= 0; /* last one has 0? */
8777 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
8780 VARTYPE arg_type
= V_VT(value
);
8783 DWORD ret
= file
->custdata_seg
.len
;
8785 if(arg_type
== VT_INT
)
8787 if(arg_type
== VT_UINT
)
8791 if(V_VT(value
) != arg_type
) {
8792 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
8794 ERR("VariantChangeType failed: %08x\n", hres
);
8799 /* Check if default value can be stored in-place */
8804 if(V_UI4(&v
) > 0x3ffffff)
8817 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
8820 /* have to allocate space in custdata_seg */
8829 /* Construct the data to be allocated */
8832 if(file
->custdata_seg
.data
){
8833 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
8834 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
8835 file
->custdata_seg
.len
+= sizeof(int) * 2;
8837 file
->custdata_seg
.len
= sizeof(int) * 2;
8838 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
8841 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
8842 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
8844 /* TODO: Check if the encoded data is already present in custdata_seg */
8850 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
8853 if(file
->custdata_seg
.data
){
8854 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
8855 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
8856 file
->custdata_seg
.len
+= len
;
8858 file
->custdata_seg
.len
= len
;
8859 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
8862 *((unsigned short *)data
) = V_VT(value
);
8863 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
8864 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
8865 if(V_BSTR(&v
)[i
] <= 0x7f)
8866 data
[i
+6] = V_BSTR(&v
)[i
];
8870 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
8871 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
8874 /* TODO: Check if the encoded data is already present in custdata_seg */
8879 FIXME("Argument type not yet handled\n");
8884 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
8886 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
8888 DWORD offs
= file
->arraydesc_seg
.len
;
8892 /* TODO: we should check for duplicates, but that's harder because each
8893 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8894 * at the library-level) */
8896 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
8897 if(!file
->arraydesc_seg
.data
)
8898 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
8900 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
8901 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
8903 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
8904 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
8905 for(i
= 0; i
< desc
->cDims
; ++i
){
8906 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
8907 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
8913 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
8919 VARTYPE vt
= desc
->vt
& VT_TYPEMASK
, subtype
;
8960 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
8963 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
8965 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
8966 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
8968 *out_size
+= 2 * sizeof(DWORD
);
8969 }else if(vt
== VT_CARRAY
){
8970 encoded
[0] = desc
->vt
| (0x7FFE << 16);
8971 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
8973 }else if(vt
== VT_USERDEFINED
){
8974 encoded
[0] = desc
->vt
| (0x7FFF << 16);
8975 encoded
[1] = desc
->u
.hreftype
;
8976 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
8978 FIXME("Don't know what to do! VT: 0x%x\n", desc
->vt
);
8979 *out_mix
= desc
->vt
;
8980 return 0x80000000 | (desc
->vt
<< 16) | desc
->vt
;
8983 data
= file
->typdesc_seg
.data
;
8984 while(offs
< file
->typdesc_seg
.len
){
8985 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
8987 offs
+= sizeof(encoded
);
8990 file
->typdesc_seg
.len
+= sizeof(encoded
);
8991 if(!file
->typdesc_seg
.data
)
8992 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
8994 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
8996 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9001 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9003 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9004 DWORD ret
= cdguids_seg
->len
, offs
;
9005 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9008 if(list_empty(custdata_list
))
9011 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9012 if(!cdguids_seg
->data
){
9013 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9015 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9017 offs
= ret
+ sizeof(MSFT_CDGuid
);
9018 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9019 cdguid
->GuidOffset
= cd
->guid
->offset
;
9020 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9021 cdguid
->next
= offs
;
9022 offs
+= sizeof(MSFT_CDGuid
);
9032 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9033 WMSFT_TLBFile
*file
)
9035 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9036 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9037 MSFT_VarRecord
*varrecord
;
9038 MSFT_FuncRecord
*funcrecord
;
9040 DWORD
*name
, *offsets
, offs
;
9042 for(i
= 0; i
< info
->cFuncs
; ++i
){
9043 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9045 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9047 /* optional fields */
9048 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9049 if(!list_empty(&desc
->custdata_list
))
9050 recorded_size
+= 7 * sizeof(INT
);
9051 else if(desc
->HelpStringContext
!= 0)
9052 recorded_size
+= 6 * sizeof(INT
);
9054 else if(desc
->Entry
)
9055 recorded_size
+= 3 * sizeof(INT
);
9056 else if(desc
->HelpString
)
9057 recorded_size
+= 2 * sizeof(INT
);
9058 else if(desc
->helpcontext
)
9059 recorded_size
+= sizeof(INT
);
9061 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9063 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9064 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9065 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9070 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9073 for(i
= 0; i
< info
->cVars
; ++i
){
9074 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9076 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9078 /* optional fields */
9079 if(desc
->HelpStringContext
!= 0)
9080 recorded_size
+= 5 * sizeof(INT
);
9081 else if(!list_empty(&desc
->custdata_list
))
9082 recorded_size
+= 4 * sizeof(INT
);
9084 else if(desc
->HelpString
)
9085 recorded_size
+= 2 * sizeof(INT
);
9086 else if(desc
->HelpContext
!= 0)
9087 recorded_size
+= sizeof(INT
);
9089 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9092 if(!recorded_size
&& !extra_size
)
9095 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9097 aux_seg
->len
+= recorded_size
+ extra_size
;
9099 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9102 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9104 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9106 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9108 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9111 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9112 for(i
= 0; i
< info
->cFuncs
; ++i
){
9113 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9114 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9116 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9117 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9118 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9119 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9122 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9127 * ^has_param_defaults
9128 * ^oEntry_is_intresource
9130 funcrecord
->FKCCIC
=
9131 desc
->funcdesc
.funckind
|
9132 (desc
->funcdesc
.invkind
<< 3) |
9133 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9134 (desc
->funcdesc
.callconv
<< 8);
9136 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9137 funcrecord
->FKCCIC
|= 0x2000;
9139 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9140 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9141 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9142 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9145 if(paramdefault_size
> 0)
9146 funcrecord
->FKCCIC
|= 0x1000;
9148 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9149 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9151 /* optional fields */
9153 if(!list_empty(&desc
->custdata_list
)){
9154 size
+= 7 * sizeof(INT
);
9155 funcrecord
->HelpContext
= desc
->helpcontext
;
9156 if(desc
->HelpString
)
9157 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9159 funcrecord
->oHelpString
= -1;
9161 funcrecord
->oEntry
= -1;
9162 else if(IS_INTRESOURCE(desc
->Entry
))
9163 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9165 funcrecord
->oEntry
= desc
->Entry
->offset
;
9166 funcrecord
->res9
= -1;
9167 funcrecord
->resA
= -1;
9168 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9169 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9170 }else if(desc
->HelpStringContext
!= 0){
9171 size
+= 6 * sizeof(INT
);
9172 funcrecord
->HelpContext
= desc
->helpcontext
;
9173 if(desc
->HelpString
)
9174 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9176 funcrecord
->oHelpString
= -1;
9178 funcrecord
->oEntry
= -1;
9179 else if(IS_INTRESOURCE(desc
->Entry
))
9180 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9182 funcrecord
->oEntry
= desc
->Entry
->offset
;
9183 funcrecord
->res9
= -1;
9184 funcrecord
->resA
= -1;
9185 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9186 }else if(desc
->Entry
){
9187 size
+= 3 * sizeof(INT
);
9188 funcrecord
->HelpContext
= desc
->helpcontext
;
9189 if(desc
->HelpString
)
9190 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9192 funcrecord
->oHelpString
= -1;
9194 funcrecord
->oEntry
= -1;
9195 else if(IS_INTRESOURCE(desc
->Entry
))
9196 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9198 funcrecord
->oEntry
= desc
->Entry
->offset
;
9199 }else if(desc
->HelpString
){
9200 size
+= 2 * sizeof(INT
);
9201 funcrecord
->HelpContext
= desc
->helpcontext
;
9202 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9203 }else if(desc
->helpcontext
){
9204 size
+= sizeof(INT
);
9205 funcrecord
->HelpContext
= desc
->helpcontext
;
9208 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9209 size
+= paramdefault_size
;
9211 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9212 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9214 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9215 if(desc
->pParamDesc
[j
].Name
)
9216 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9219 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9221 if(paramdefault_size
){
9222 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9223 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9224 else if(paramdefault_size
)
9229 size
+= sizeof(MSFT_ParameterInfo
);
9232 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9238 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9241 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9242 for(i
= 0; i
< info
->cVars
; ++i
){
9243 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9244 DWORD size
= 5 * sizeof(INT
);
9246 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9247 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9248 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9249 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9251 if(desc
->vardesc
.varkind
== VAR_CONST
){
9252 varrecord
->vardescsize
+= sizeof(VARIANT
);
9253 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9255 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9258 if(desc
->HelpStringContext
!= 0){
9259 size
+= 5 * sizeof(INT
);
9260 varrecord
->HelpContext
= desc
->HelpContext
;
9261 if(desc
->HelpString
)
9262 varrecord
->HelpString
= desc
->HelpString
->offset
;
9264 varrecord
->HelpString
= -1;
9265 varrecord
->res9
= -1;
9266 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9267 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9268 }else if(!list_empty(&desc
->custdata_list
)){
9269 size
+= 4 * sizeof(INT
);
9270 varrecord
->HelpContext
= desc
->HelpContext
;
9271 if(desc
->HelpString
)
9272 varrecord
->HelpString
= desc
->HelpString
->offset
;
9274 varrecord
->HelpString
= -1;
9275 varrecord
->res9
= -1;
9276 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9277 }else if(desc
->HelpString
){
9278 size
+= 2 * sizeof(INT
);
9279 varrecord
->HelpContext
= desc
->HelpContext
;
9280 if(desc
->HelpString
)
9281 varrecord
->HelpString
= desc
->HelpString
->offset
;
9283 varrecord
->HelpString
= -1;
9284 }else if(desc
->HelpContext
!= 0){
9285 size
+= sizeof(INT
);
9286 varrecord
->HelpContext
= desc
->HelpContext
;
9289 varrecord
->Info
= size
| (i
<< 16);
9295 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9298 memid
= (MEMBERID
*)varrecord
;
9299 for(i
= 0; i
< info
->cFuncs
; ++i
){
9300 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9301 *memid
= desc
->funcdesc
.memid
;
9304 for(i
= 0; i
< info
->cVars
; ++i
){
9305 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9306 *memid
= desc
->vardesc
.memid
;
9310 name
= (UINT
*)memid
;
9311 for(i
= 0; i
< info
->cFuncs
; ++i
){
9312 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9314 *name
= desc
->Name
->offset
;
9319 for(i
= 0; i
< info
->cVars
; ++i
){
9320 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9322 *name
= desc
->Name
->offset
;
9331 typedef struct tagWMSFT_RefChunk
{
9338 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9340 DWORD offs
= file
->ref_seg
.len
, i
;
9341 WMSFT_RefChunk
*chunk
;
9343 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9344 if(!file
->ref_seg
.data
)
9345 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9347 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9349 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9351 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9352 chunk
->href
= info
->impltypes
[i
].hRef
;
9353 chunk
->res04
= info
->impltypes
[i
].implflags
;
9355 if(i
< info
->cImplTypes
- 1)
9356 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9365 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9369 size
= sizeof(MSFT_TypeInfoBase
);
9372 MSFT_TypeInfoBase
*base
= (void*)data
;
9373 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9374 base
->typekind
= TKIND_DISPATCH
;
9376 base
->typekind
= info
->typekind
;
9377 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9378 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9379 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9384 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9390 base
->posguid
= info
->guid
->offset
;
9393 base
->flags
= info
->wTypeFlags
;
9395 base
->NameOffset
= info
->Name
->offset
;
9397 base
->NameOffset
= -1;
9398 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9400 base
->docstringoffs
= info
->DocString
->offset
;
9402 base
->docstringoffs
= -1;
9403 base
->helpstringcontext
= info
->dwHelpStringContext
;
9404 base
->helpcontext
= info
->dwHelpContext
;
9405 base
->oCustData
= WMSFT_compile_custdata(&info
->custdata_list
, file
);
9406 base
->cImplTypes
= info
->cImplTypes
;
9407 base
->cbSizeVft
= info
->cbSizeVft
;
9408 base
->size
= info
->cbSizeInstance
;
9409 if(info
->typekind
== TKIND_COCLASS
){
9410 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9411 }else if(info
->typekind
== TKIND_ALIAS
){
9412 base
->datatype1
= WMSFT_append_typedesc(&info
->tdescAlias
, file
, NULL
, NULL
);
9413 }else if(info
->typekind
== TKIND_MODULE
){
9415 base
->datatype1
= info
->DllName
->offset
;
9417 base
->datatype1
= -1;
9419 if(info
->cImplTypes
> 0)
9420 base
->datatype1
= info
->impltypes
[0].hRef
;
9422 base
->datatype1
= -1;
9424 base
->datatype2
= index
; /* FIXME: i think there's more here */
9432 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9436 file
->typeinfo_seg
.len
= 0;
9437 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9438 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9439 *junk
= file
->typeinfo_seg
.len
;
9441 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9444 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9445 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9447 file
->aux_seg
.len
= 0;
9448 file
->aux_seg
.data
= NULL
;
9450 file
->typeinfo_seg
.len
= 0;
9451 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9452 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9453 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9454 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9458 typedef struct tagWMSFT_ImpFile
{
9464 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9467 WMSFT_ImpFile
*impfile
;
9469 DWORD last_offs
= 0;
9471 file
->impfile_seg
.len
= 0;
9472 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9476 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9480 path
= implib
->name
;
9481 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9483 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9486 size
+= sizeof(INT16
);
9488 size
= (size
+ 4) & ~0x3;
9492 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9495 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9497 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9498 int strlen
= 0, size
;
9500 impfile
= (WMSFT_ImpFile
*)data
;
9501 impfile
->guid_offs
= implib
->guid
->offset
;
9502 impfile
->lcid
= implib
->lcid
;
9503 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9505 data
+= sizeof(WMSFT_ImpFile
);
9508 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9512 path
= implib
->name
;
9513 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9514 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9516 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9519 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9521 size
= strlen
+ sizeof(INT16
);
9523 size
= (size
+ 4) & ~0x3;
9526 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9529 implib
->offset
= last_offs
;
9530 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9534 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9537 TLBRefType
*ref_type
;
9540 WMSFT_compile_impfile(This
, file
);
9542 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9543 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9545 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9546 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9547 if(ref_type
->index
== TLB_REF_USE_GUID
){
9548 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9549 info
->oGuid
= ref_type
->guid
->offset
;
9551 info
->oGuid
= ref_type
->index
;
9552 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9558 static void WMSFT_compile_lib(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9560 /* TODO: What actually goes here? */
9561 file
->lib_seg
.len
= 0x80;
9562 file
->lib_seg
.data
= heap_alloc(file
->lib_seg
.len
);
9563 memset(file
->lib_seg
.data
, 0xFF, file
->lib_seg
.len
);
9566 /* sometimes, first element is offset to last guid, for some reason */
9568 *(DWORD
*)file
->lib_seg
.data
=
9569 (list_count(&This
->guid_list
) - 1) * sizeof(MSFT_GuidEntry
);
9573 static void WMSFT_compile_res07(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9575 /* TODO: What actually goes here?
9577 * It's something to do with the Name table (and string table?). When you
9578 * add a new name, the offset to that name from within the Name table gets
9579 * stuck somewhere in res07, apparently starting at the end of the segment
9580 * then moving backwards at a rate of 3 bytes per char in the Name. */
9581 file
->res07_seg
.len
= 0x200;
9582 file
->res07_seg
.data
= heap_alloc(file
->res07_seg
.len
);
9583 memset(file
->res07_seg
.data
, 0xFF, file
->res07_seg
.len
);
9586 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9588 if(contents
&& contents
->len
){
9589 segdir
->offset
= *running_offset
;
9590 segdir
->length
= contents
->len
;
9591 *running_offset
+= segdir
->length
;
9593 segdir
->offset
= -1;
9597 /* TODO: do these ever change? */
9599 segdir
->res0c
= 0xf;
9602 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9606 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9609 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9613 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9615 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9616 base
->memoffset
+= file_len
;
9623 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9625 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9626 HeapFree(GetProcessHeap(), 0, file
->lib_seg
.data
);
9627 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9628 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9629 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9630 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9631 HeapFree(GetProcessHeap(), 0, file
->res07_seg
.data
);
9632 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9633 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9634 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9635 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9636 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9637 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9638 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9641 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9643 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9645 DWORD written
, junk_size
, junk_offs
, running_offset
;
9651 TRACE("%p\n", This
);
9653 memset(&file
, 0, sizeof(file
));
9655 file
.header
.magic1
= 0x5446534D;
9656 file
.header
.magic2
= 0x00010002;
9657 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9658 file
.header
.lcid2
= This
->set_lcid
;
9659 file
.header
.varflags
= 0x41; /* TODO?? */
9661 file
.header
.varflags
|= 0x10;
9662 if (This
->HelpStringDll
)
9663 file
.header
.varflags
|= HELPDLLFLAG
;
9664 file
.header
.version
= (This
->ver_major
<< 16) | This
->ver_minor
;
9665 file
.header
.flags
= This
->libflags
;
9666 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9667 file
.header
.helpcontext
= This
->dwHelpContext
;
9668 file
.header
.res44
= 0x20;
9669 file
.header
.res48
= 0x80;
9670 file
.header
.dispatchpos
= This
->dispatch_href
;
9672 /* do name and string compilation to get offsets for other compilations */
9673 hres
= WMSFT_compile_names(This
, &file
);
9675 WMSFT_free_file(&file
);
9679 hres
= WMSFT_compile_strings(This
, &file
);
9681 WMSFT_free_file(&file
);
9685 hres
= WMSFT_compile_guids(This
, &file
);
9687 WMSFT_free_file(&file
);
9692 file
.header
.helpfile
= This
->HelpFile
->offset
;
9694 file
.header
.helpfile
= -1;
9697 file
.header
.helpstring
= This
->DocString
->offset
;
9699 file
.header
.helpstring
= -1;
9701 /* do some more segment compilation */
9702 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9703 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9706 file
.header
.NameOffset
= This
->Name
->offset
;
9708 file
.header
.NameOffset
= -1;
9710 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9713 file
.header
.posguid
= This
->guid
->offset
;
9715 file
.header
.posguid
= -1;
9717 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9718 if(file
.header
.varflags
& HELPDLLFLAG
)
9719 junk_size
+= sizeof(DWORD
);
9721 junk
= heap_alloc_zero(junk_size
);
9722 if(file
.header
.varflags
& HELPDLLFLAG
){
9723 *junk
= This
->HelpStringDll
->offset
;
9732 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9733 WMSFT_compile_impinfo(This
, &file
);
9734 WMSFT_compile_lib(This
, &file
);
9735 WMSFT_compile_res07(This
, &file
);
9739 TRACE("header at: 0x%x\n", running_offset
);
9740 running_offset
+= sizeof(file
.header
);
9742 TRACE("junk at: 0x%x\n", running_offset
);
9743 running_offset
+= junk_size
;
9745 TRACE("segdir at: 0x%x\n", running_offset
);
9746 running_offset
+= sizeof(file
.segdir
);
9748 TRACE("typeinfo at: 0x%x\n", running_offset
);
9749 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9751 TRACE("libtab at: 0x%x\n", running_offset
);
9752 tmp_fill_segdir_seg(&file
.segdir
.pLibtab
, &file
.lib_seg
, &running_offset
);
9754 TRACE("guidtab at: 0x%x\n", running_offset
);
9755 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9757 TRACE("reftab at: 0x%x\n", running_offset
);
9758 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9760 TRACE("impinfo at: 0x%x\n", running_offset
);
9761 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9763 TRACE("impfiles at: 0x%x\n", running_offset
);
9764 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9766 TRACE("res07 at: 0x%x\n", running_offset
);
9767 tmp_fill_segdir_seg(&file
.segdir
.res07
, &file
.res07_seg
, &running_offset
);
9769 TRACE("nametab at: 0x%x\n", running_offset
);
9770 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9772 TRACE("stringtab at: 0x%x\n", running_offset
);
9773 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9775 TRACE("typdesc at: 0x%x\n", running_offset
);
9776 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
9778 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
9779 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
9781 TRACE("custdata at: 0x%x\n", running_offset
);
9782 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
9784 TRACE("cdguids at: 0x%x\n", running_offset
);
9785 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
9787 TRACE("res0e at: 0x%x\n", running_offset
);
9788 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
9790 TRACE("res0f at: 0x%x\n", running_offset
);
9791 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
9793 TRACE("aux_seg at: 0x%x\n", running_offset
);
9795 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
9797 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
9798 FILE_ATTRIBUTE_NORMAL
, 0);
9799 if (outfile
== INVALID_HANDLE_VALUE
){
9800 WMSFT_free_file(&file
);
9801 return TYPE_E_IOERROR
;
9804 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
9806 WMSFT_free_file(&file
);
9807 CloseHandle(outfile
);
9808 return TYPE_E_IOERROR
;
9811 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
9813 WMSFT_free_file(&file
);
9814 CloseHandle(outfile
);
9815 return TYPE_E_IOERROR
;
9818 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
9820 WMSFT_free_file(&file
);
9821 CloseHandle(outfile
);
9822 return TYPE_E_IOERROR
;
9825 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
9826 WMSFT_write_segment(outfile
, &file
.lib_seg
);
9827 WMSFT_write_segment(outfile
, &file
.guid_seg
);
9828 WMSFT_write_segment(outfile
, &file
.ref_seg
);
9829 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
9830 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
9831 WMSFT_write_segment(outfile
, &file
.res07_seg
);
9832 WMSFT_write_segment(outfile
, &file
.name_seg
);
9833 WMSFT_write_segment(outfile
, &file
.string_seg
);
9834 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
9835 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
9836 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
9837 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
9838 WMSFT_write_segment(outfile
, &file
.aux_seg
);
9840 WMSFT_free_file(&file
);
9842 CloseHandle(outfile
);
9847 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
9850 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9851 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
9855 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
9856 REFGUID guid
, VARIANT
*varVal
)
9858 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9859 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
9863 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
9864 ULONG helpStringContext
)
9866 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9867 FIXME("%p %u - stub\n", This
, helpStringContext
);
9871 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
9874 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9875 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
9878 return E_INVALIDARG
;
9880 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
9885 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
9886 ICreateTypeLib2_fnQueryInterface
,
9887 ICreateTypeLib2_fnAddRef
,
9888 ICreateTypeLib2_fnRelease
,
9889 ICreateTypeLib2_fnCreateTypeInfo
,
9890 ICreateTypeLib2_fnSetName
,
9891 ICreateTypeLib2_fnSetVersion
,
9892 ICreateTypeLib2_fnSetGuid
,
9893 ICreateTypeLib2_fnSetDocString
,
9894 ICreateTypeLib2_fnSetHelpFileName
,
9895 ICreateTypeLib2_fnSetHelpContext
,
9896 ICreateTypeLib2_fnSetLcid
,
9897 ICreateTypeLib2_fnSetLibFlags
,
9898 ICreateTypeLib2_fnSaveAllChanges
,
9899 ICreateTypeLib2_fnDeleteTypeInfo
,
9900 ICreateTypeLib2_fnSetCustData
,
9901 ICreateTypeLib2_fnSetHelpStringContext
,
9902 ICreateTypeLib2_fnSetHelpStringDll
9905 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
9906 REFIID riid
, void **object
)
9908 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9910 return ITypeInfo2_QueryInterface((ITypeInfo2
*)This
, riid
, object
);
9913 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
9915 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9917 return ITypeInfo2_AddRef((ITypeInfo2
*)This
);
9920 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
9922 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9924 return ITypeInfo2_Release((ITypeInfo2
*)This
);
9927 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
9930 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9932 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9934 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
);
9939 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
9942 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9946 TRACE("%p %x\n", This
, typeFlags
);
9948 if (typeFlags
& TYPEFLAG_FDUAL
) {
9949 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9951 ITypeInfo
*dispatch
;
9955 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
9959 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
9960 ITypeLib_Release(stdole
);
9964 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
9965 ITypeInfo_Release(dispatch
);
9970 old_flags
= This
->wTypeFlags
;
9971 This
->wTypeFlags
= typeFlags
;
9973 hres
= ICreateTypeInfo2_LayOut(iface
);
9975 This
->wTypeFlags
= old_flags
;
9982 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
9985 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9987 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9990 return E_INVALIDARG
;
9992 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
9997 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10000 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10002 TRACE("%p %d\n", This
, helpContext
);
10004 This
->dwHelpContext
= helpContext
;
10009 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10010 WORD majorVerNum
, WORD minorVerNum
)
10012 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10014 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10016 This
->wMajorVerNum
= majorVerNum
;
10017 This
->wMinorVerNum
= minorVerNum
;
10022 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10023 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10025 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10027 ITypeLib
*container
;
10028 TLBRefType
*ref_type
;
10030 TYPEATTR
*typeattr
;
10034 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10036 if (!typeInfo
|| !refType
)
10037 return E_INVALIDARG
;
10039 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10043 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10044 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10046 ITypeLib_Release(container
);
10048 *refType
= target
->hreftype
;
10053 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10054 if (FAILED(hres
)) {
10055 ITypeLib_Release(container
);
10059 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10060 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10061 implib
->lcid
== libattr
->lcid
&&
10062 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10063 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10067 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10068 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10070 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10071 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10072 implib
->name
= SysAllocString(our_container
->path
);
10074 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10075 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10077 implib
->name
= NULL
;
10078 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10082 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
);
10083 implib
->lcid
= libattr
->lcid
;
10084 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10085 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10087 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10090 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10091 ITypeLib_Release(container
);
10093 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10098 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10099 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10100 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10101 ref_type
->tkind
== typeattr
->typekind
)
10106 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10107 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10109 ref_type
->tkind
= typeattr
->typekind
;
10110 ref_type
->pImpTLInfo
= implib
;
10111 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10113 ref_type
->index
= TLB_REF_USE_GUID
;
10115 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
);
10117 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10120 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10122 *refType
= ref_type
->reference
| 0x1;
10124 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10125 This
->pTypeLib
->dispatch_href
= *refType
;
10130 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10131 UINT index
, FUNCDESC
*funcDesc
)
10133 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10134 TLBFuncDesc tmp_func_desc
, *func_desc
;
10139 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10141 if (!funcDesc
|| funcDesc
->oVft
& 3)
10142 return E_INVALIDARG
;
10144 switch (This
->typekind
) {
10146 if (funcDesc
->funckind
!= FUNC_STATIC
)
10147 return TYPE_E_BADMODULEKIND
;
10149 case TKIND_DISPATCH
:
10150 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10151 return TYPE_E_BADMODULEKIND
;
10154 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10155 return TYPE_E_BADMODULEKIND
;
10158 if (index
> This
->cFuncs
)
10159 return TYPE_E_ELEMENTNOTFOUND
;
10161 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10162 !funcDesc
->cParams
)
10163 return TYPE_E_INCONSISTENTPROPFUNCS
;
10165 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10166 TLBFuncDesc_Constructor(&tmp_func_desc
);
10168 tmp_func_desc
.funcdesc
= *funcDesc
;
10170 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10171 tmp_func_desc
.funcdesc
.oVft
|= 1;
10173 if (funcDesc
->cScodes
) {
10174 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10175 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10177 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10179 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10180 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10181 buf_size
+= sizeof(ELEMDESC
);
10182 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10184 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10185 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10187 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10188 if (FAILED(hres
)) {
10189 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10190 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10194 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10195 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10196 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10197 if (FAILED(hres
)) {
10198 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10199 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10202 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10203 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10204 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10205 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10206 if (FAILED(hres
)) {
10207 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10208 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10214 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10216 if (This
->funcdescs
) {
10217 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10218 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10220 if (index
< This
->cFuncs
) {
10221 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10222 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10223 func_desc
= This
->funcdescs
+ index
;
10225 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10227 /* move custdata lists to the new memory location */
10228 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10230 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10231 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10232 list_init(&fd
->custdata_list
);
10234 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10235 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10240 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10242 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10243 list_init(&func_desc
->custdata_list
);
10247 This
->needs_layout
= TRUE
;
10252 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10253 UINT index
, HREFTYPE refType
)
10255 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10256 TLBImplType
*impl_type
;
10259 TRACE("%p %u %d\n", This
, index
, refType
);
10261 switch(This
->typekind
){
10262 case TKIND_COCLASS
: {
10264 FIXME("Unhandled index: -1\n");
10268 if(index
!= This
->cImplTypes
)
10269 return TYPE_E_ELEMENTNOTFOUND
;
10273 case TKIND_INTERFACE
:
10274 case TKIND_DISPATCH
:
10275 if (index
!= 0 || This
->cImplTypes
)
10276 return TYPE_E_ELEMENTNOTFOUND
;
10279 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10283 if (This
->impltypes
){
10286 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10287 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10289 if (index
< This
->cImplTypes
) {
10290 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10291 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10292 impl_type
= This
->impltypes
+ index
;
10294 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10296 /* move custdata lists to the new memory location */
10297 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10299 TLBImplType
*it
= &This
->impltypes
[i
];
10300 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10301 list_init(&it
->custdata_list
);
10303 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10304 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10309 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10311 memset(impl_type
, 0, sizeof(TLBImplType
));
10312 TLBImplType_Constructor(impl_type
);
10313 impl_type
->hRef
= refType
;
10315 ++This
->cImplTypes
;
10317 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10318 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10320 hres
= ICreateTypeInfo2_LayOut(iface
);
10327 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10328 UINT index
, INT implTypeFlags
)
10330 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10331 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10333 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10335 if (This
->typekind
!= TKIND_COCLASS
)
10336 return TYPE_E_BADMODULEKIND
;
10338 if (index
>= This
->cImplTypes
)
10339 return TYPE_E_ELEMENTNOTFOUND
;
10341 impl_type
->implflags
= implTypeFlags
;
10346 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10349 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10351 TRACE("%p %d\n", This
, alignment
);
10353 This
->cbAlignment
= alignment
;
10358 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10361 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10363 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10366 return E_INVALIDARG
;
10368 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10370 This
->lpstrSchema
= This
->Schema
->str
;
10375 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10376 UINT index
, VARDESC
*varDesc
)
10378 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10379 TLBVarDesc
*var_desc
;
10381 TRACE("%p %u %p\n", This
, index
, varDesc
);
10383 if (This
->vardescs
){
10386 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10387 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10389 if (index
< This
->cVars
) {
10390 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10391 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10392 var_desc
= This
->vardescs
+ index
;
10394 var_desc
= This
->vardescs
+ This
->cVars
;
10396 /* move custdata lists to the new memory location */
10397 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10399 TLBVarDesc
*var
= &This
->vardescs
[i
];
10400 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10401 list_init(&var
->custdata_list
);
10403 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10404 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10409 var_desc
= This
->vardescs
= heap_alloc(sizeof(TLBVarDesc
));
10411 memset(var_desc
, 0, sizeof(TLBVarDesc
));
10412 TLBVarDesc_Constructor(var_desc
);
10413 var_desc
->vardesc
= *varDesc
;
10417 This
->needs_layout
= TRUE
;
10422 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10423 UINT index
, LPOLESTR
*names
, UINT numNames
)
10425 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10426 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10429 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10432 return E_INVALIDARG
;
10434 if (index
>= This
->cFuncs
|| numNames
== 0)
10435 return TYPE_E_ELEMENTNOTFOUND
;
10437 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10438 if(numNames
> func_desc
->funcdesc
.cParams
)
10439 return TYPE_E_ELEMENTNOTFOUND
;
10441 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10442 return TYPE_E_ELEMENTNOTFOUND
;
10444 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10445 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10446 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10447 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10448 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10449 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10451 return TYPE_E_AMBIGUOUSNAME
;
10455 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10457 for (i
= 1; i
< numNames
; ++i
) {
10458 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10459 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10465 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10466 UINT index
, LPOLESTR name
)
10468 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10469 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(name
));
10473 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10474 TYPEDESC
*tdescAlias
)
10476 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10477 FIXME("%p %p - stub\n", This
, tdescAlias
);
10481 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10482 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10484 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10485 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10489 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10490 UINT index
, LPOLESTR docString
)
10492 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10493 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
10497 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10498 UINT index
, LPOLESTR docString
)
10500 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10501 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10503 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10506 return E_INVALIDARG
;
10508 if(index
>= This
->cVars
)
10509 return TYPE_E_ELEMENTNOTFOUND
;
10511 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10516 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10517 UINT index
, DWORD helpContext
)
10519 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10520 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10522 TRACE("%p %u %d\n", This
, index
, helpContext
);
10524 if(index
>= This
->cFuncs
)
10525 return TYPE_E_ELEMENTNOTFOUND
;
10527 func_desc
->helpcontext
= helpContext
;
10532 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10533 UINT index
, DWORD helpContext
)
10535 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10536 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10538 TRACE("%p %u %d\n", This
, index
, helpContext
);
10540 if(index
>= This
->cVars
)
10541 return TYPE_E_ELEMENTNOTFOUND
;
10543 var_desc
->HelpContext
= helpContext
;
10548 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10549 UINT index
, BSTR bstrMops
)
10551 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10552 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10556 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10559 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10561 TRACE("%p %p\n", This
, idlDesc
);
10564 return E_INVALIDARG
;
10566 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10567 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10572 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10574 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10576 TLBFuncDesc
*func_desc
;
10577 UINT user_vft
= 0, i
, depth
= 0;
10578 HRESULT hres
= S_OK
;
10580 TRACE("%p\n", This
);
10582 This
->needs_layout
= FALSE
;
10584 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10588 if (This
->typekind
== TKIND_INTERFACE
) {
10593 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10595 if (SUCCEEDED(hres
)) {
10596 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10598 if (SUCCEEDED(hres
)) {
10599 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10600 if (FAILED(hres
)) {
10601 ITypeInfo_Release(inh
);
10602 ITypeInfo_Release(tinfo
);
10605 This
->cbSizeVft
= attr
->cbSizeVft
* 4 / sizeof(void*);
10606 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10610 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10611 if(SUCCEEDED(hres
)){
10613 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10614 if(SUCCEEDED(hres
)){
10615 ITypeInfo_Release(inh
);
10619 }while(SUCCEEDED(hres
));
10622 ITypeInfo_Release(inh
);
10623 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10624 This
->cbSizeVft
= 0;
10627 ITypeInfo_Release(tinfo
);
10630 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10631 This
->cbSizeVft
= 0;
10634 ITypeInfo_Release(tinfo
);
10637 } else if (This
->typekind
== TKIND_DISPATCH
)
10638 This
->cbSizeVft
= 7 * sizeof(void*);
10640 This
->cbSizeVft
= 0;
10642 func_desc
= This
->funcdescs
;
10644 while (i
< This
->cFuncs
) {
10645 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10646 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10648 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10649 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10651 This
->cbSizeVft
+= sizeof(void*);
10653 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10656 BOOL reset
= FALSE
;
10658 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10660 iter
= This
->funcdescs
;
10661 while (j
< This
->cFuncs
) {
10662 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10664 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10667 ++func_desc
->funcdesc
.memid
;
10668 iter
= This
->funcdescs
;
10681 if (user_vft
> This
->cbSizeVft
)
10682 This
->cbSizeVft
= user_vft
+ sizeof(void*);
10684 ITypeInfo_Release(tinfo
);
10688 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10691 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10692 FIXME("%p %u - stub\n", This
, index
);
10696 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
10697 MEMBERID memid
, INVOKEKIND invKind
)
10699 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10700 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
10704 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
10707 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10708 FIXME("%p %u - stub\n", This
, index
);
10712 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
10715 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10716 FIXME("%p %x - stub\n", This
, memid
);
10720 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
10723 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10724 FIXME("%p %u - stub\n", This
, index
);
10728 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
10729 REFGUID guid
, VARIANT
*varVal
)
10733 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10735 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10737 if (!guid
|| !varVal
)
10738 return E_INVALIDARG
;
10740 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
);
10742 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10745 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
10746 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10748 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10749 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10753 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
10754 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
10756 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10757 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
10761 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
10762 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10764 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10765 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10769 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
10770 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10772 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10773 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10777 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
10778 ULONG helpStringContext
)
10780 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10782 TRACE("%p %u\n", This
, helpStringContext
);
10784 This
->dwHelpStringContext
= helpStringContext
;
10789 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
10790 UINT index
, ULONG helpStringContext
)
10792 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10793 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
10797 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
10798 UINT index
, ULONG helpStringContext
)
10800 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10801 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
10805 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
10807 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10808 FIXME("%p - stub\n", This
);
10812 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
10815 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10817 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
10820 return E_INVALIDARG
;
10822 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10827 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
10828 ICreateTypeInfo2_fnQueryInterface
,
10829 ICreateTypeInfo2_fnAddRef
,
10830 ICreateTypeInfo2_fnRelease
,
10831 ICreateTypeInfo2_fnSetGuid
,
10832 ICreateTypeInfo2_fnSetTypeFlags
,
10833 ICreateTypeInfo2_fnSetDocString
,
10834 ICreateTypeInfo2_fnSetHelpContext
,
10835 ICreateTypeInfo2_fnSetVersion
,
10836 ICreateTypeInfo2_fnAddRefTypeInfo
,
10837 ICreateTypeInfo2_fnAddFuncDesc
,
10838 ICreateTypeInfo2_fnAddImplType
,
10839 ICreateTypeInfo2_fnSetImplTypeFlags
,
10840 ICreateTypeInfo2_fnSetAlignment
,
10841 ICreateTypeInfo2_fnSetSchema
,
10842 ICreateTypeInfo2_fnAddVarDesc
,
10843 ICreateTypeInfo2_fnSetFuncAndParamNames
,
10844 ICreateTypeInfo2_fnSetVarName
,
10845 ICreateTypeInfo2_fnSetTypeDescAlias
,
10846 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
10847 ICreateTypeInfo2_fnSetFuncDocString
,
10848 ICreateTypeInfo2_fnSetVarDocString
,
10849 ICreateTypeInfo2_fnSetFuncHelpContext
,
10850 ICreateTypeInfo2_fnSetVarHelpContext
,
10851 ICreateTypeInfo2_fnSetMops
,
10852 ICreateTypeInfo2_fnSetTypeIdldesc
,
10853 ICreateTypeInfo2_fnLayOut
,
10854 ICreateTypeInfo2_fnDeleteFuncDesc
,
10855 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
10856 ICreateTypeInfo2_fnDeleteVarDesc
,
10857 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
10858 ICreateTypeInfo2_fnDeleteImplType
,
10859 ICreateTypeInfo2_fnSetCustData
,
10860 ICreateTypeInfo2_fnSetFuncCustData
,
10861 ICreateTypeInfo2_fnSetParamCustData
,
10862 ICreateTypeInfo2_fnSetVarCustData
,
10863 ICreateTypeInfo2_fnSetImplTypeCustData
,
10864 ICreateTypeInfo2_fnSetHelpStringContext
,
10865 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
10866 ICreateTypeInfo2_fnSetVarHelpStringContext
,
10867 ICreateTypeInfo2_fnInvalidate
,
10868 ICreateTypeInfo2_fnSetName