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 ptfd
->pParamDesc
[j
].Name
=
2397 MSFT_ReadName( pcx
, paraminfo
.oName
);
2398 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2400 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
2403 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2404 (pFuncRec
->FKCCIC
& 0x1000) )
2406 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2408 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2410 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2412 pParamDesc
->pparamdescex
= heap_alloc_zero(sizeof(PARAMDESCEX
));
2413 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2415 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2419 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2422 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2423 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2424 pFuncRec
->FKCCIC
& 0x80 )
2427 pFuncRec
->oArgCustData
[j
],
2428 &ptfd
->pParamDesc
[j
].custdata_list
);
2431 /* SEEK value = jump to offset,
2432 * from there jump to the end of record,
2433 * go back by (j-1) arguments
2435 MSFT_ReadLEDWords( ¶minfo
,
2436 sizeof(MSFT_ParameterInfo
), pcx
,
2437 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2438 * sizeof(MSFT_ParameterInfo
)));
2442 /* scode is not used: archaic win16 stuff FIXME: right? */
2443 ptfd
->funcdesc
.cScodes
= 0 ;
2444 ptfd
->funcdesc
.lprgscode
= NULL
;
2448 recoffset
+= reclength
;
2453 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2454 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2456 int infolen
, nameoffset
, reclength
;
2458 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2463 TRACE_(typelib
)("\n");
2465 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2466 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2467 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2468 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2469 recoffset
+= offset
+sizeof(INT
);
2470 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2471 /* name, eventually add to a hash table */
2472 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2473 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2474 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2475 /* read the variable information record */
2476 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2478 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2481 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2482 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2484 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2485 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2487 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2488 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2490 /* fill the VarDesc Structure */
2491 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2492 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2493 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2494 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2495 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2496 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2497 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2498 if(pVarRec
->VarKind
== VAR_CONST
){
2499 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2500 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2501 pVarRec
->OffsValue
, pcx
);
2503 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2504 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptvd
->vardesc
.elemdescVar
.tdesc
);
2505 recoffset
+= reclength
;
2509 /* fill in data for a hreftype (offset). When the referenced type is contained
2510 * in the typelib, it's just an (file) offset in the type info base dir.
2511 * If comes from import, it's an offset+1 in the ImpInfo table
2513 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2518 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2520 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2522 if(ref
->reference
== offset
) return;
2525 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2526 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2528 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2529 /* external typelib */
2530 MSFT_ImpInfo impinfo
;
2533 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2535 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2536 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2538 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2539 if(pImpLib
->offset
==impinfo
.oImpFile
)
2542 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2543 ref
->reference
= offset
& (~0x3);
2544 ref
->pImpTLInfo
= pImpLib
;
2545 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2546 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2547 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2548 ref
->index
= TLB_REF_USE_GUID
;
2550 ref
->index
= impinfo
.oGuid
;
2552 ERR("Cannot find a reference\n");
2553 ref
->reference
= -1;
2554 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2557 /* in this typelib */
2558 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2559 ref
->reference
= offset
;
2560 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2564 /* process Implemented Interfaces of a com class */
2565 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2569 MSFT_RefRecord refrec
;
2572 TRACE_(typelib
)("\n");
2574 pTI
->impltypes
= TLBImplType_Alloc(count
);
2575 pImpl
= pTI
->impltypes
;
2576 for(i
=0;i
<count
;i
++){
2577 if(offset
<0) break; /* paranoia */
2578 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2579 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2580 pImpl
->hRef
= refrec
.reftype
;
2581 pImpl
->implflags
=refrec
.flags
;
2582 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2583 offset
=refrec
.onext
;
2588 * process a typeinfo record
2590 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2593 ITypeLibImpl
* pLibInfo
)
2595 MSFT_TypeInfoBase tiBase
;
2596 ITypeInfoImpl
*ptiRet
;
2598 TRACE_(typelib
)("count=%u\n", count
);
2600 ptiRet
= ITypeInfoImpl_Constructor();
2601 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2602 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2604 /* this is where we are coming from */
2605 ptiRet
->pTypeLib
= pLibInfo
;
2606 ptiRet
->index
=count
;
2608 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2609 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2610 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2611 ptiRet
->cbSizeInstance
=tiBase
.size
;
2612 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2613 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2614 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2615 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2616 ptiRet
->wTypeFlags
=tiBase
.flags
;
2617 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2618 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2619 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2620 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2621 if(ptiRet
->typekind
== TKIND_ALIAS
)
2622 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2623 &ptiRet
->tdescAlias
, ptiRet
);
2626 /* IDLDESC idldescType; *//* never saw this one != zero */
2628 /* name, eventually add to a hash table */
2629 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2630 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2631 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2633 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2634 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2635 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2637 if (ptiRet
->typekind
== TKIND_MODULE
)
2638 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2640 /* note: InfoType's Help file and HelpStringDll come from the containing
2641 * library. Further HelpString and Docstring appear to be the same thing :(
2644 if(ptiRet
->cFuncs
>0 )
2645 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2647 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2649 if(ptiRet
->cVars
>0 )
2650 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2652 tiBase
.memoffset
, &ptiRet
->vardescs
);
2653 if(ptiRet
->cImplTypes
>0 ) {
2654 switch(ptiRet
->typekind
)
2657 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2660 case TKIND_DISPATCH
:
2661 /* This is not -1 when the interface is a non-base dual interface or
2662 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2663 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2667 if (tiBase
.datatype1
!= -1)
2669 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2670 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2671 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2675 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2676 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2677 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2681 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->custdata_list
);
2683 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2684 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2685 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2686 typekind_desc
[ptiRet
->typekind
]);
2687 if (TRACE_ON(typelib
))
2688 dump_TypeInfo(ptiRet
);
2693 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2696 INT16 len_str
, len_piece
;
2697 int offs
= 0, lengthInChars
;
2699 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2703 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2706 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2707 len_piece
= len_str
+ sizeof(INT16
);
2709 len_piece
= (len_piece
+ 4) & ~0x3;
2713 string
= heap_alloc(len_piece
+ 1);
2714 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2715 string
[len_str
] = '\0';
2717 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2718 string
, -1, NULL
, 0);
2719 if (!lengthInChars
) {
2721 return E_UNEXPECTED
;
2724 tlbstr
= heap_alloc(sizeof(TLBString
));
2726 tlbstr
->offset
= offs
;
2727 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2728 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2732 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2738 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2739 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2740 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2743 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2744 static CRITICAL_SECTION cache_section
;
2745 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2747 0, 0, &cache_section
,
2748 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2749 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2751 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2754 typedef struct TLB_PEFile
2756 IUnknown IUnknown_iface
;
2759 HRSRC typelib_resource
;
2760 HGLOBAL typelib_global
;
2761 LPVOID typelib_base
;
2764 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2766 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2769 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2771 if (IsEqualIID(riid
, &IID_IUnknown
))
2774 IUnknown_AddRef(iface
);
2778 return E_NOINTERFACE
;
2781 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2783 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2784 return InterlockedIncrement(&This
->refs
);
2787 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2789 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2790 ULONG refs
= InterlockedDecrement(&This
->refs
);
2793 if (This
->typelib_global
)
2794 FreeResource(This
->typelib_global
);
2796 FreeLibrary(This
->dll
);
2802 static const IUnknownVtbl TLB_PEFile_Vtable
=
2804 TLB_PEFile_QueryInterface
,
2809 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2812 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2814 This
= heap_alloc(sizeof(TLB_PEFile
));
2816 return E_OUTOFMEMORY
;
2818 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2821 This
->typelib_resource
= NULL
;
2822 This
->typelib_global
= NULL
;
2823 This
->typelib_base
= NULL
;
2825 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2826 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2830 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2831 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2832 if (This
->typelib_resource
)
2834 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2835 if (This
->typelib_global
)
2837 This
->typelib_base
= LockResource(This
->typelib_global
);
2839 if (This
->typelib_base
)
2841 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2842 *ppBase
= This
->typelib_base
;
2843 *ppFile
= &This
->IUnknown_iface
;
2849 TRACE("No TYPELIB resource found\n");
2853 TLB_PEFile_Release(&This
->IUnknown_iface
);
2857 typedef struct TLB_NEFile
2859 IUnknown IUnknown_iface
;
2861 LPVOID typelib_base
;
2864 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2866 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2869 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2871 if (IsEqualIID(riid
, &IID_IUnknown
))
2874 IUnknown_AddRef(iface
);
2878 return E_NOINTERFACE
;
2881 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2883 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2884 return InterlockedIncrement(&This
->refs
);
2887 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2889 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2890 ULONG refs
= InterlockedDecrement(&This
->refs
);
2893 heap_free(This
->typelib_base
);
2899 static const IUnknownVtbl TLB_NEFile_Vtable
=
2901 TLB_NEFile_QueryInterface
,
2906 /***********************************************************************
2907 * read_xx_header [internal]
2909 static int read_xx_header( HFILE lzfd
)
2911 IMAGE_DOS_HEADER mzh
;
2914 LZSeek( lzfd
, 0, SEEK_SET
);
2915 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2917 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2920 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2921 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2924 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2926 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2927 return IMAGE_OS2_SIGNATURE
;
2928 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2929 return IMAGE_NT_SIGNATURE
;
2932 WARN("Can't handle %s files.\n", magic
);
2937 /***********************************************************************
2938 * find_ne_resource [internal]
2940 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2941 DWORD
*resLen
, DWORD
*resOff
)
2943 IMAGE_OS2_HEADER nehd
;
2944 NE_TYPEINFO
*typeInfo
;
2945 NE_NAMEINFO
*nameInfo
;
2951 /* Read in NE header */
2952 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2953 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2955 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2958 TRACE("No resources in NE dll\n" );
2962 /* Read in resource table */
2963 resTab
= heap_alloc( resTabSize
);
2964 if ( !resTab
) return FALSE
;
2966 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2967 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2969 heap_free( resTab
);
2974 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2976 if (!IS_INTRESOURCE(typeid)) /* named type */
2978 BYTE len
= strlen( typeid );
2979 while (typeInfo
->type_id
)
2981 if (!(typeInfo
->type_id
& 0x8000))
2983 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2984 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2986 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2987 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2990 else /* numeric type id */
2992 WORD id
= LOWORD(typeid) | 0x8000;
2993 while (typeInfo
->type_id
)
2995 if (typeInfo
->type_id
== id
) goto found_type
;
2996 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2997 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3000 TRACE("No typeid entry found for %p\n", typeid );
3001 heap_free( resTab
);
3005 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3007 if (!IS_INTRESOURCE(resid
)) /* named resource */
3009 BYTE len
= strlen( resid
);
3010 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3012 BYTE
*p
= resTab
+ nameInfo
->id
;
3013 if (nameInfo
->id
& 0x8000) continue;
3014 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3017 else /* numeric resource id */
3019 WORD id
= LOWORD(resid
) | 0x8000;
3020 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3021 if (nameInfo
->id
== id
) goto found_name
;
3023 TRACE("No resid entry found for %p\n", typeid );
3024 heap_free( resTab
);
3028 /* Return resource data */
3029 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3030 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3032 heap_free( resTab
);
3036 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3040 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3043 This
= heap_alloc(sizeof(TLB_NEFile
));
3044 if (!This
) return E_OUTOFMEMORY
;
3046 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3048 This
->typelib_base
= NULL
;
3050 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3051 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3053 DWORD reslen
, offset
;
3054 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3056 This
->typelib_base
= heap_alloc(reslen
);
3057 if( !This
->typelib_base
)
3061 LZSeek( lzfd
, offset
, SEEK_SET
);
3062 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3064 *ppBase
= This
->typelib_base
;
3065 *pdwTLBLength
= reslen
;
3066 *ppFile
= &This
->IUnknown_iface
;
3072 if( lzfd
>= 0) LZClose( lzfd
);
3073 TLB_NEFile_Release(&This
->IUnknown_iface
);
3077 typedef struct TLB_Mapping
3079 IUnknown IUnknown_iface
;
3083 LPVOID typelib_base
;
3086 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3088 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3091 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3093 if (IsEqualIID(riid
, &IID_IUnknown
))
3096 IUnknown_AddRef(iface
);
3100 return E_NOINTERFACE
;
3103 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3105 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3106 return InterlockedIncrement(&This
->refs
);
3109 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3111 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3112 ULONG refs
= InterlockedDecrement(&This
->refs
);
3115 if (This
->typelib_base
)
3116 UnmapViewOfFile(This
->typelib_base
);
3118 CloseHandle(This
->mapping
);
3119 if (This
->file
!= INVALID_HANDLE_VALUE
)
3120 CloseHandle(This
->file
);
3126 static const IUnknownVtbl TLB_Mapping_Vtable
=
3128 TLB_Mapping_QueryInterface
,
3133 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3137 This
= heap_alloc(sizeof(TLB_Mapping
));
3139 return E_OUTOFMEMORY
;
3141 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3143 This
->file
= INVALID_HANDLE_VALUE
;
3144 This
->mapping
= NULL
;
3145 This
->typelib_base
= NULL
;
3147 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3148 if (INVALID_HANDLE_VALUE
!= This
->file
)
3150 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3153 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3154 if(This
->typelib_base
)
3156 /* retrieve file size */
3157 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3158 *ppBase
= This
->typelib_base
;
3159 *ppFile
= &This
->IUnknown_iface
;
3165 IUnknown_Release(&This
->IUnknown_iface
);
3166 return TYPE_E_CANTLOADLIBRARY
;
3169 /****************************************************************************
3172 * find the type of the typelib file and map the typelib resource into
3176 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3177 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3179 ITypeLibImpl
*entry
;
3182 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3183 LPVOID pBase
= NULL
;
3184 DWORD dwTLBLength
= 0;
3185 IUnknown
*pFile
= NULL
;
3189 index_str
= strrchrW(pszFileName
, '\\');
3190 if(index_str
&& *++index_str
!= '\0')
3193 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3194 if(*end_ptr
== '\0')
3196 int str_len
= index_str
- pszFileName
- 1;
3198 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3199 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3204 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3206 if(strchrW(file
, '\\'))
3208 lstrcpyW(pszPath
, file
);
3212 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3213 pszPath
[len
] = '\\';
3214 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3218 if(file
!= pszFileName
) heap_free(file
);
3220 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3222 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3223 EnterCriticalSection(&cache_section
);
3224 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3226 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3228 TRACE("cache hit\n");
3229 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3230 ITypeLib2_AddRef(*ppTypeLib
);
3231 LeaveCriticalSection(&cache_section
);
3235 LeaveCriticalSection(&cache_section
);
3237 /* now actually load and parse the typelib */
3239 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3240 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3241 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3242 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3243 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3246 if (dwTLBLength
>= 4)
3248 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3249 if (dwSignature
== MSFT_SIGNATURE
)
3250 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3251 else if (dwSignature
== SLTG_SIGNATURE
)
3252 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3255 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3256 ret
= TYPE_E_CANTLOADLIBRARY
;
3260 ret
= TYPE_E_CANTLOADLIBRARY
;
3261 IUnknown_Release(pFile
);
3265 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3267 TRACE("adding to cache\n");
3268 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3269 lstrcpyW(impl
->path
, pszPath
);
3270 /* We should really canonicalise the path here. */
3271 impl
->index
= index
;
3273 /* FIXME: check if it has added already in the meantime */
3274 EnterCriticalSection(&cache_section
);
3275 list_add_head(&tlb_cache
, &impl
->entry
);
3276 LeaveCriticalSection(&cache_section
);
3282 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3284 ret
= TYPE_E_CANTLOADLIBRARY
;
3291 /*================== ITypeLib(2) Methods ===================================*/
3293 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3295 ITypeLibImpl
* pTypeLibImpl
;
3297 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3298 if (!pTypeLibImpl
) return NULL
;
3300 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3301 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3302 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3303 pTypeLibImpl
->ref
= 1;
3305 list_init(&pTypeLibImpl
->implib_list
);
3306 list_init(&pTypeLibImpl
->custdata_list
);
3307 list_init(&pTypeLibImpl
->name_list
);
3308 list_init(&pTypeLibImpl
->string_list
);
3309 list_init(&pTypeLibImpl
->guid_list
);
3310 list_init(&pTypeLibImpl
->ref_list
);
3311 pTypeLibImpl
->dispatch_href
= -1;
3313 return pTypeLibImpl
;
3316 /****************************************************************************
3317 * ITypeLib2_Constructor_MSFT
3319 * loading an MSFT typelib from an in-memory image
3321 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3325 MSFT_Header tlbHeader
;
3326 MSFT_SegDir tlbSegDir
;
3327 ITypeLibImpl
* pTypeLibImpl
;
3329 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3331 pTypeLibImpl
= TypeLibImpl_Constructor();
3332 if (!pTypeLibImpl
) return NULL
;
3334 /* get pointer to beginning of typelib data */
3338 cx
.pLibInfo
= pTypeLibImpl
;
3339 cx
.length
= dwTLBLength
;
3342 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3343 TRACE_(typelib
)("header:\n");
3344 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3345 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3346 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3349 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3351 /* there is a small amount of information here until the next important
3353 * the segment directory . Try to calculate the amount of data */
3354 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3356 /* now read the segment directory */
3357 TRACE("read segment directory (at %d)\n",lPSegDir
);
3358 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3359 cx
.pTblDir
= &tlbSegDir
;
3361 /* just check two entries */
3362 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3364 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3365 heap_free(pTypeLibImpl
);
3369 MSFT_ReadAllNames(&cx
);
3370 MSFT_ReadAllStrings(&cx
);
3371 MSFT_ReadAllGuids(&cx
);
3373 /* now fill our internal data */
3374 /* TLIBATTR fields */
3375 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3377 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3378 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3379 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3380 pTypeLibImpl
->libflags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3382 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3383 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3385 /* name, eventually add to a hash table */
3386 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3389 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3390 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3392 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3395 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3396 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3399 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3402 if(tlbHeader
.CustomDataOffset
>= 0)
3404 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3407 /* fill in type descriptions */
3408 if(tlbSegDir
.pTypdescTab
.length
> 0)
3410 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3412 pTypeLibImpl
->ctTypeDesc
= cTD
;
3413 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3414 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3417 /* FIXME: add several sanity checks here */
3418 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3419 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3421 /* FIXME: check safearray */
3423 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3425 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3427 else if(td
[0] == VT_CARRAY
)
3429 /* array descr table here */
3430 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3432 else if(td
[0] == VT_USERDEFINED
)
3434 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3436 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3439 /* second time around to fill the array subscript info */
3442 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3443 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3445 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3446 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3449 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3451 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3453 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3455 for(j
= 0; j
<td
[2]; j
++)
3457 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3458 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3459 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3460 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3465 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3466 ERR("didn't find array description data\n");
3471 /* imported type libs */
3472 if(tlbSegDir
.pImpFiles
.offset
>0)
3475 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3478 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3482 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3483 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3484 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3486 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3487 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3488 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3489 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3492 name
= heap_alloc_zero(size
+1);
3493 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3494 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3497 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3498 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3500 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3504 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3505 if(pTypeLibImpl
->dispatch_href
!= -1)
3506 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3509 if(tlbHeader
.nrtypeinfos
>= 0 )
3511 ITypeInfoImpl
**ppTI
;
3514 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3516 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3518 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3521 (pTypeLibImpl
->TypeInfoCount
)++;
3525 TRACE("(%p)\n", pTypeLibImpl
);
3526 return &pTypeLibImpl
->ITypeLib2_iface
;
3530 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3536 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3537 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3541 guid
->Data4
[0] = s
>> 8;
3542 guid
->Data4
[1] = s
& 0xff;
3545 for(i
= 0; i
< 6; i
++) {
3546 memcpy(b
, str
+ 24 + 2 * i
, 2);
3547 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3552 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3559 bytelen
= *(const WORD
*)ptr
;
3560 if(bytelen
== 0xffff) return 2;
3562 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3563 tmp_str
= SysAllocStringLen(NULL
, len
);
3565 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3566 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3567 SysFreeString(tmp_str
);
3572 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3577 bytelen
= *(const WORD
*)ptr
;
3578 if(bytelen
== 0xffff) return 2;
3579 *str
= heap_alloc(bytelen
+ 1);
3580 memcpy(*str
, ptr
+ 2, bytelen
);
3581 (*str
)[bytelen
] = '\0';
3585 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3590 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3591 if (tlbstr
->offset
== offset
)
3595 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3596 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3597 SysFreeString(tmp_str
);
3602 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3604 char *ptr
= pLibBlk
;
3607 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3608 FIXME("libblk magic = %04x\n", w
);
3613 if((w
= *(WORD
*)ptr
) != 0xffff) {
3614 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3619 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3621 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3623 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3626 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3629 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3630 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3632 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3635 ptr
+= 4; /* skip res12 */
3637 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3640 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3643 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3646 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
);
3647 ptr
+= sizeof(GUID
);
3649 return ptr
- (char*)pLibBlk
;
3652 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3657 } sltg_ref_lookup_t
;
3659 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3660 HREFTYPE
*typelib_ref
)
3662 if(table
&& typeinfo_ref
< table
->num
)
3664 *typelib_ref
= table
->refs
[typeinfo_ref
];
3668 ERR_(typelib
)("Unable to find reference\n");
3673 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3678 if((*pType
& 0xe00) == 0xe00) {
3680 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3681 pTD
= pTD
->u
.lptdesc
;
3683 switch(*pType
& 0x3f) {
3686 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3687 pTD
= pTD
->u
.lptdesc
;
3690 case VT_USERDEFINED
:
3691 pTD
->vt
= VT_USERDEFINED
;
3692 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3698 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3701 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3703 pTD
->vt
= VT_CARRAY
;
3704 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3705 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3706 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3707 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3709 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3715 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3719 pTD
->vt
= VT_SAFEARRAY
;
3720 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3721 pTD
= pTD
->u
.lptdesc
;
3725 pTD
->vt
= *pType
& 0x3f;
3734 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3735 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3737 /* Handle [in/out] first */
3738 if((*pType
& 0xc000) == 0xc000)
3739 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3740 else if(*pType
& 0x8000)
3741 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3742 else if(*pType
& 0x4000)
3743 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3745 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3748 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3751 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3753 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3757 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3762 TLBRefType
*ref_type
;
3763 sltg_ref_lookup_t
*table
;
3764 HREFTYPE typelib_ref
;
3766 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3767 FIXME("Ref magic = %x\n", pRef
->magic
);
3770 name
= ( (char*)pRef
->names
+ pRef
->number
);
3772 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3773 table
->num
= pRef
->number
>> 3;
3775 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3777 /* We don't want the first href to be 0 */
3778 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3780 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3782 unsigned int lib_offs
, type_num
;
3784 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3786 name
+= SLTG_ReadStringA(name
, &refname
);
3787 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3788 FIXME_(typelib
)("Can't sscanf ref\n");
3789 if(lib_offs
!= 0xffff) {
3792 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3793 if(import
->offset
== lib_offs
)
3796 if(&import
->entry
== &pTL
->implib_list
) {
3797 char fname
[MAX_PATH
+1];
3801 import
= heap_alloc_zero(sizeof(*import
));
3802 import
->offset
= lib_offs
;
3803 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3804 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
);
3805 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3806 &import
->wVersionMajor
,
3807 &import
->wVersionMinor
,
3808 &import
->lcid
, fname
) != 4) {
3809 FIXME_(typelib
)("can't sscanf ref %s\n",
3810 pNameTable
+ lib_offs
+ 40);
3812 len
= strlen(fname
);
3813 if(fname
[len
-1] != '#')
3814 FIXME("fname = %s\n", fname
);
3815 fname
[len
-1] = '\0';
3816 import
->name
= TLB_MultiByteToBSTR(fname
);
3817 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3819 ref_type
->pImpTLInfo
= import
;
3821 /* Store a reference to IDispatch */
3822 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3823 pTL
->dispatch_href
= typelib_ref
;
3825 } else { /* internal ref */
3826 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3828 ref_type
->reference
= typelib_ref
;
3829 ref_type
->index
= type_num
;
3832 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3834 table
->refs
[ref
] = typelib_ref
;
3837 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3838 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3839 dump_TLBRefType(pTL
);
3843 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3844 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3846 SLTG_ImplInfo
*info
;
3847 TLBImplType
*pImplType
;
3848 /* I don't really get this structure, usually it's 0x16 bytes
3849 long, but iuser.tlb contains some that are 0x18 bytes long.
3850 That's ok because we can use the next ptr to jump to the next
3851 one. But how do we know the length of the last one? The WORD
3852 at offs 0x8 might be the clue. For now I'm just assuming that
3853 the last one is the regular 0x16 bytes. */
3855 info
= (SLTG_ImplInfo
*)pBlk
;
3858 if(info
->next
== 0xffff)
3860 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3863 info
= (SLTG_ImplInfo
*)pBlk
;
3864 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
3865 pImplType
= pTI
->impltypes
;
3867 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3868 pImplType
->implflags
= info
->impltypeflags
;
3871 if(info
->next
== 0xffff)
3874 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3875 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3877 info
++; /* see comment at top of function */
3881 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3882 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3884 TLBVarDesc
*pVarDesc
;
3885 const TLBString
*prevName
= NULL
;
3886 SLTG_Variable
*pItem
;
3890 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
3892 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3893 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3895 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3897 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3898 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3899 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3903 if (pItem
->name
== 0xfffe)
3904 pVarDesc
->Name
= prevName
;
3906 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
3908 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
3909 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3910 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3912 if(pItem
->flags
& 0x02)
3913 pType
= &pItem
->type
;
3915 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3917 if (pItem
->flags
& ~0xda)
3918 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3920 SLTG_DoElem(pType
, pBlk
,
3921 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3923 if (TRACE_ON(typelib
)) {
3925 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3926 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3929 if (pItem
->flags
& 0x40) {
3930 TRACE_(typelib
)("VAR_DISPATCH\n");
3931 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3933 else if (pItem
->flags
& 0x10) {
3934 TRACE_(typelib
)("VAR_CONST\n");
3935 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3936 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3937 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3938 if (pItem
->flags
& 0x08)
3939 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3941 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3947 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3949 TRACE_(typelib
)("len = %u\n", len
);
3950 if (len
== 0xffff) {
3953 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3954 str
= SysAllocStringLen(NULL
, alloc_len
);
3955 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3957 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3958 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3967 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3968 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3971 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3976 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3977 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3978 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3981 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3982 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3984 if (pItem
->flags
& 0x80)
3985 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3987 prevName
= pVarDesc
->Name
;
3992 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3993 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3995 SLTG_Function
*pFunc
;
3997 TLBFuncDesc
*pFuncDesc
;
3999 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4001 pFuncDesc
= pTI
->funcdescs
;
4002 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4003 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4008 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4009 case SLTG_FUNCTION_MAGIC
:
4010 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4012 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4013 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4015 case SLTG_STATIC_FUNCTION_MAGIC
:
4016 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4019 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4022 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4024 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4025 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4026 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4027 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4028 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4029 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4031 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4032 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4034 if(pFunc
->retnextopt
& 0x80)
4035 pType
= &pFunc
->rettype
;
4037 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4039 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4041 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4042 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4043 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4045 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4047 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4048 char *paramName
= pNameTable
+ *pArg
;
4050 /* If arg type follows then paramName points to the 2nd
4051 letter of the name, else the next WORD is an offset to
4052 the arg type and paramName points to the first letter.
4053 So let's take one char off paramName and see if we're
4054 pointing at an alpha-numeric char. However if *pArg is
4055 0xffff or 0xfffe then the param has no name, the former
4056 meaning that the next WORD is the type, the latter
4057 meaning that the next WORD is an offset to the type. */
4062 else if(*pArg
== 0xfffe) {
4066 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4071 if(HaveOffs
) { /* the next word is an offset to type */
4072 pType
= (WORD
*)(pBlk
+ *pArg
);
4073 SLTG_DoElem(pType
, pBlk
,
4074 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4079 pArg
= SLTG_DoElem(pArg
, pBlk
,
4080 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4083 /* Are we an optional param ? */
4084 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4085 pFuncDesc
->funcdesc
.cParamsOpt
)
4086 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4089 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4090 paramName
- pNameTable
, pTI
->pTypeLib
);
4092 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4096 pTI
->cFuncs
= cFuncs
;
4099 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4100 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4101 SLTG_TypeInfoTail
*pTITail
)
4104 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4106 if(pTIHeader
->href_table
!= 0xffffffff) {
4107 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4113 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4114 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4116 heap_free(ref_lookup
);
4120 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4121 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4122 const SLTG_TypeInfoTail
*pTITail
)
4125 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4127 if(pTIHeader
->href_table
!= 0xffffffff) {
4128 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4134 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4135 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4138 if (pTITail
->funcs_off
!= 0xffff)
4139 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4141 heap_free(ref_lookup
);
4143 if (TRACE_ON(typelib
))
4144 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4147 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4148 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4149 const SLTG_TypeInfoTail
*pTITail
)
4151 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4154 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4155 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4156 const SLTG_TypeInfoTail
*pTITail
)
4159 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4161 if (pTITail
->simple_alias
) {
4162 /* if simple alias, no more processing required */
4163 pTI
->tdescAlias
.vt
= pTITail
->tdescalias_vt
;
4167 if(pTIHeader
->href_table
!= 0xffffffff) {
4168 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4172 /* otherwise it is an offset to a type */
4173 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4175 SLTG_DoType(pType
, pBlk
, &pTI
->tdescAlias
, ref_lookup
);
4177 heap_free(ref_lookup
);
4180 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4181 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4182 const SLTG_TypeInfoTail
*pTITail
)
4184 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4185 if (pTIHeader
->href_table
!= 0xffffffff)
4186 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4189 if (pTITail
->vars_off
!= 0xffff)
4190 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4192 if (pTITail
->funcs_off
!= 0xffff)
4193 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4195 if (pTITail
->impls_off
!= 0xffff)
4196 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4198 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4199 * of dispinterface functions including the IDispatch ones, so
4200 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4201 pTI
->cbSizeVft
= pTI
->cFuncs
* sizeof(void *);
4203 heap_free(ref_lookup
);
4204 if (TRACE_ON(typelib
))
4205 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4208 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4209 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4210 const SLTG_TypeInfoTail
*pTITail
)
4212 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4215 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4216 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4217 const SLTG_TypeInfoTail
*pTITail
)
4219 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4220 if (pTIHeader
->href_table
!= 0xffffffff)
4221 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4224 if (pTITail
->vars_off
!= 0xffff)
4225 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4227 if (pTITail
->funcs_off
!= 0xffff)
4228 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4229 heap_free(ref_lookup
);
4230 if (TRACE_ON(typelib
))
4234 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4235 manageable copy of it into this */
4248 } SLTG_InternalOtherTypeInfo
;
4250 /****************************************************************************
4251 * ITypeLib2_Constructor_SLTG
4253 * loading a SLTG typelib from an in-memory image
4255 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4257 ITypeLibImpl
*pTypeLibImpl
;
4258 SLTG_Header
*pHeader
;
4259 SLTG_BlkEntry
*pBlkEntry
;
4263 LPVOID pBlk
, pFirstBlk
;
4264 SLTG_LibBlk
*pLibBlk
;
4265 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4266 char *pAfterOTIBlks
= NULL
;
4267 char *pNameTable
, *ptr
;
4270 ITypeInfoImpl
**ppTypeInfoImpl
;
4272 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4275 pTypeLibImpl
= TypeLibImpl_Constructor();
4276 if (!pTypeLibImpl
) return NULL
;
4280 TRACE_(typelib
)("header:\n");
4281 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4282 pHeader
->nrOfFileBlks
);
4283 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4284 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4285 pHeader
->SLTG_magic
);
4289 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4290 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4292 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4293 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4295 /* Next we have a magic block */
4296 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4298 /* Let's see if we're still in sync */
4299 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4300 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4301 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4304 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4305 sizeof(SLTG_DIR_MAGIC
))) {
4306 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4310 pIndex
= (SLTG_Index
*)(pMagic
+1);
4312 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4314 pFirstBlk
= pPad9
+ 1;
4316 /* We'll set up a ptr to the main library block, which is the last one. */
4318 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4319 pBlkEntry
[order
].next
!= 0;
4320 order
= pBlkEntry
[order
].next
- 1, i
++) {
4321 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4325 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4327 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4332 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4334 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4337 ptr
= (char*)pLibBlk
+ len
;
4339 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4343 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4345 w
= *(WORD
*)(ptr
+ 2);
4348 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4349 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4350 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4352 w
= *(WORD
*)(ptr
+ 4 + len
);
4354 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4356 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4357 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4358 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4360 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4361 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4362 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4364 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4365 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4368 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4369 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4370 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4371 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4372 len
+= sizeof(SLTG_OtherTypeInfo
);
4376 pAfterOTIBlks
= ptr
;
4378 /* Skip this WORD and get the next DWORD */
4379 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4381 /* Now add this to pLibBLk look at what we're pointing at and
4382 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4383 dust and we should be pointing at the beginning of the name
4386 pNameTable
= (char*)pLibBlk
+ len
;
4388 switch(*(WORD
*)pNameTable
) {
4395 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4399 pNameTable
+= 0x216;
4403 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4405 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4408 /* Hopefully we now have enough ptrs set up to actually read in
4409 some TypeInfos. It's not clear which order to do them in, so
4410 I'll just follow the links along the BlkEntry chain and read
4411 them in the order in which they are in the file */
4413 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4414 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4416 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4417 pBlkEntry
[order
].next
!= 0;
4418 order
= pBlkEntry
[order
].next
- 1, i
++) {
4420 SLTG_TypeInfoHeader
*pTIHeader
;
4421 SLTG_TypeInfoTail
*pTITail
;
4422 SLTG_MemberHeader
*pMemHeader
;
4424 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4425 FIXME_(typelib
)("Index strings don't match\n");
4426 heap_free(pOtherTypeInfoBlks
);
4431 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4432 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4433 heap_free(pOtherTypeInfoBlks
);
4436 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4437 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4438 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4440 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4441 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4442 (*ppTypeInfoImpl
)->index
= i
;
4443 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4444 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4445 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
);
4446 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4447 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4448 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4449 (*ppTypeInfoImpl
)->wTypeFlags
=
4450 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4452 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4453 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4455 if((pTIHeader
->typeflags1
& 7) != 2)
4456 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4457 if(pTIHeader
->typeflags3
!= 2)
4458 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4460 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4461 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4462 typekind_desc
[pTIHeader
->typekind
],
4463 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4464 (*ppTypeInfoImpl
)->wTypeFlags
);
4466 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4468 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4470 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4471 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4472 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4474 switch(pTIHeader
->typekind
) {
4476 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4477 pTIHeader
, pTITail
);
4481 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4482 pTIHeader
, pTITail
);
4485 case TKIND_INTERFACE
:
4486 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4487 pTIHeader
, pTITail
);
4491 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4492 pTIHeader
, pTITail
);
4496 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4497 pTIHeader
, pTITail
);
4500 case TKIND_DISPATCH
:
4501 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4502 pTIHeader
, pTITail
);
4506 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4507 pTIHeader
, pTITail
);
4511 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4516 /* could get cFuncs, cVars and cImplTypes from here
4517 but we've already set those */
4518 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4534 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4537 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4538 FIXME("Somehow processed %d TypeInfos\n", i
);
4539 heap_free(pOtherTypeInfoBlks
);
4543 heap_free(pOtherTypeInfoBlks
);
4544 return &pTypeLibImpl
->ITypeLib2_iface
;
4547 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4549 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4551 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4553 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4554 IsEqualIID(riid
,&IID_ITypeLib
)||
4555 IsEqualIID(riid
,&IID_ITypeLib2
))
4557 *ppv
= &This
->ITypeLib2_iface
;
4559 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4560 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4562 *ppv
= &This
->ICreateTypeLib2_iface
;
4567 TRACE("-- Interface: E_NOINTERFACE\n");
4568 return E_NOINTERFACE
;
4571 IUnknown_AddRef((IUnknown
*)*ppv
);
4575 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4577 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4578 ULONG ref
= InterlockedIncrement(&This
->ref
);
4580 TRACE("(%p) ref=%u\n", This
, ref
);
4585 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4587 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4588 ULONG ref
= InterlockedDecrement(&This
->ref
);
4590 TRACE("(%p) ref=%u\n",This
, ref
);
4594 TLBImpLib
*pImpLib
, *pImpLibNext
;
4595 TLBRefType
*ref_type
;
4596 TLBString
*tlbstr
, *tlbstr_next
;
4600 /* remove cache entry */
4603 TRACE("removing from cache list\n");
4604 EnterCriticalSection(&cache_section
);
4605 if(This
->entry
.next
)
4606 list_remove(&This
->entry
);
4607 LeaveCriticalSection(&cache_section
);
4608 heap_free(This
->path
);
4610 TRACE(" destroying ITypeLib(%p)\n",This
);
4612 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4613 list_remove(&tlbstr
->entry
);
4617 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4618 list_remove(&tlbstr
->entry
);
4622 TLB_FreeCustData(&This
->custdata_list
);
4624 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4625 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4626 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4628 heap_free(This
->pTypeDesc
);
4630 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4632 if (pImpLib
->pImpTypeLib
)
4633 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4634 SysFreeString(pImpLib
->name
);
4636 list_remove(&pImpLib
->entry
);
4640 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4642 list_remove(&ref_type
->entry
);
4643 heap_free(ref_type
);
4646 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4647 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4648 heap_free(This
->typeinfos
);
4656 /* ITypeLib::GetTypeInfoCount
4658 * Returns the number of type descriptions in the type library
4660 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4662 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4663 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4664 return This
->TypeInfoCount
;
4667 /* ITypeLib::GetTypeInfo
4669 * retrieves the specified type description in the library.
4671 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4674 ITypeInfo
**ppTInfo
)
4676 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4678 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4681 return E_INVALIDARG
;
4683 if(index
>= This
->TypeInfoCount
)
4684 return TYPE_E_ELEMENTNOTFOUND
;
4686 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[index
];
4687 ITypeInfo_AddRef(*ppTInfo
);
4693 /* ITypeLibs::GetTypeInfoType
4695 * Retrieves the type of a type description.
4697 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4702 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4704 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4707 return E_INVALIDARG
;
4709 if(index
>= This
->TypeInfoCount
)
4710 return TYPE_E_ELEMENTNOTFOUND
;
4712 *pTKind
= This
->typeinfos
[index
]->typekind
;
4717 /* ITypeLib::GetTypeInfoOfGuid
4719 * Retrieves the type description that corresponds to the specified GUID.
4722 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4725 ITypeInfo
**ppTInfo
)
4727 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4730 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4732 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4733 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4734 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[i
];
4735 ITypeInfo_AddRef(*ppTInfo
);
4740 return TYPE_E_ELEMENTNOTFOUND
;
4743 /* ITypeLib::GetLibAttr
4745 * Retrieves the structure that contains the library's attributes.
4748 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4752 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4754 TRACE("(%p, %p)\n", This
, attr
);
4756 if (!attr
) return E_INVALIDARG
;
4758 *attr
= heap_alloc(sizeof(**attr
));
4759 if (!*attr
) return E_OUTOFMEMORY
;
4761 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4762 (*attr
)->lcid
= This
->set_lcid
;
4763 (*attr
)->syskind
= This
->syskind
;
4764 (*attr
)->wMajorVerNum
= This
->ver_major
;
4765 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4766 (*attr
)->wLibFlags
= This
->libflags
;
4771 /* ITypeLib::GetTypeComp
4773 * Enables a client compiler to bind to a library's types, variables,
4774 * constants, and global functions.
4777 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4779 ITypeComp
**ppTComp
)
4781 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4783 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4784 *ppTComp
= &This
->ITypeComp_iface
;
4785 ITypeComp_AddRef(*ppTComp
);
4790 /* ITypeLib::GetDocumentation
4792 * Retrieves the library's documentation string, the complete Help file name
4793 * and path, and the context identifier for the library Help topic in the Help
4796 * On a successful return all non-null BSTR pointers will have been set,
4799 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4803 BSTR
*pBstrDocString
,
4804 DWORD
*pdwHelpContext
,
4805 BSTR
*pBstrHelpFile
)
4807 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4808 HRESULT result
= E_INVALIDARG
;
4811 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4813 pBstrName
, pBstrDocString
,
4814 pdwHelpContext
, pBstrHelpFile
);
4818 /* documentation for the typelib */
4823 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4831 if (This
->DocString
)
4833 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4837 *pBstrDocString
= NULL
;
4841 *pdwHelpContext
= This
->dwHelpContext
;
4847 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4851 *pBstrHelpFile
= NULL
;
4858 /* for a typeinfo */
4859 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4861 if(SUCCEEDED(result
))
4863 result
= ITypeInfo_GetDocumentation(pTInfo
,
4867 pdwHelpContext
, pBstrHelpFile
);
4869 ITypeInfo_Release(pTInfo
);
4874 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4876 if (pBstrName
) SysFreeString (*pBstrName
);
4878 return STG_E_INSUFFICIENTMEMORY
;
4883 * Indicates whether a passed-in string contains the name of a type or member
4884 * described in the library.
4887 static HRESULT WINAPI
ITypeLib2_fnIsName(
4893 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4895 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
4897 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4901 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4902 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4903 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4904 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
4905 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4907 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4908 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
4909 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4910 goto ITypeLib2_fnIsName_exit
;
4913 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
4914 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4915 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4921 ITypeLib2_fnIsName_exit
:
4922 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4923 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4928 /* ITypeLib::FindName
4930 * Finds occurrences of a type description in a type library. This may be used
4931 * to quickly verify that a name exists in a type library.
4934 static HRESULT WINAPI
ITypeLib2_fnFindName(
4938 ITypeInfo
**ppTInfo
,
4942 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4947 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
4949 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
4950 return E_INVALIDARG
;
4952 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
4953 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
4954 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4958 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4959 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
4960 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
4963 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4964 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
4965 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
4966 goto ITypeLib2_fnFindName_exit
;
4970 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
4972 goto ITypeLib2_fnFindName_exit
;
4975 ITypeLib2_fnFindName_exit
:
4976 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4977 ppTInfo
[count
]=(LPTYPEINFO
)pTInfo
;
4980 TRACE("found %d typeinfos\n", count
);
4987 /* ITypeLib::ReleaseTLibAttr
4989 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4992 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4994 TLIBATTR
*pTLibAttr
)
4996 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4997 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
4998 heap_free(pTLibAttr
);
5001 /* ITypeLib2::GetCustData
5003 * gets the custom data
5005 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5010 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5011 TLBCustData
*pCData
;
5013 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5015 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5017 return TYPE_E_ELEMENTNOTFOUND
;
5019 VariantInit(pVarVal
);
5020 VariantCopy(pVarVal
, &pCData
->data
);
5025 /* ITypeLib2::GetLibStatistics
5027 * Returns statistics about a type library that are required for efficient
5028 * sizing of hash tables.
5031 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5033 ULONG
*pcUniqueNames
,
5034 ULONG
*pcchUniqueNames
)
5036 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5038 FIXME("(%p): stub!\n", This
);
5040 if(pcUniqueNames
) *pcUniqueNames
=1;
5041 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5045 /* ITypeLib2::GetDocumentation2
5047 * Retrieves the library's documentation string, the complete Help file name
5048 * and path, the localization context to use, and the context ID for the
5049 * library Help topic in the Help file.
5052 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5056 BSTR
*pbstrHelpString
,
5057 DWORD
*pdwHelpStringContext
,
5058 BSTR
*pbstrHelpStringDll
)
5060 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5064 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5066 /* the help string should be obtained from the helpstringdll,
5067 * using the _DLLGetDocumentation function, based on the supplied
5068 * lcid. Nice to do sometime...
5072 /* documentation for the typelib */
5074 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5075 if(pdwHelpStringContext
)
5076 *pdwHelpStringContext
=This
->dwHelpContext
;
5077 if(pbstrHelpStringDll
)
5078 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5084 /* for a typeinfo */
5085 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5087 if(SUCCEEDED(result
))
5089 ITypeInfo2
* pTInfo2
;
5090 result
= ITypeInfo_QueryInterface(pTInfo
,
5092 (LPVOID
*) &pTInfo2
);
5094 if(SUCCEEDED(result
))
5096 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5100 pdwHelpStringContext
,
5101 pbstrHelpStringDll
);
5103 ITypeInfo2_Release(pTInfo2
);
5106 ITypeInfo_Release(pTInfo
);
5112 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5114 TLBCustData
*pCData
;
5118 ct
= list_count(custdata_list
);
5120 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5121 if(!pCustData
->prgCustData
)
5122 return E_OUTOFMEMORY
;
5124 pCustData
->cCustData
= ct
;
5126 cdi
= pCustData
->prgCustData
;
5127 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5128 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5129 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5137 /* ITypeLib2::GetAllCustData
5139 * Gets all custom data items for the library.
5142 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5144 CUSTDATA
*pCustData
)
5146 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5147 TRACE("(%p)->(%p)\n", This
, pCustData
);
5148 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5151 static const ITypeLib2Vtbl tlbvt
= {
5152 ITypeLib2_fnQueryInterface
,
5154 ITypeLib2_fnRelease
,
5155 ITypeLib2_fnGetTypeInfoCount
,
5156 ITypeLib2_fnGetTypeInfo
,
5157 ITypeLib2_fnGetTypeInfoType
,
5158 ITypeLib2_fnGetTypeInfoOfGuid
,
5159 ITypeLib2_fnGetLibAttr
,
5160 ITypeLib2_fnGetTypeComp
,
5161 ITypeLib2_fnGetDocumentation
,
5163 ITypeLib2_fnFindName
,
5164 ITypeLib2_fnReleaseTLibAttr
,
5166 ITypeLib2_fnGetCustData
,
5167 ITypeLib2_fnGetLibStatistics
,
5168 ITypeLib2_fnGetDocumentation2
,
5169 ITypeLib2_fnGetAllCustData
5173 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5175 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5177 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5180 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5182 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5184 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5187 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5189 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5191 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5194 static HRESULT WINAPI
ITypeLibComp_fnBind(
5199 ITypeInfo
** ppTInfo
,
5200 DESCKIND
* pDescKind
,
5203 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5204 int typemismatch
=0, i
;
5206 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5208 *pDescKind
= DESCKIND_NONE
;
5209 pBindPtr
->lptcomp
= NULL
;
5212 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5213 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5214 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5216 /* FIXME: check wFlags here? */
5217 /* FIXME: we should use a hash table to look this info up using lHash
5218 * instead of an O(n) search */
5219 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5220 (pTypeInfo
->typekind
== TKIND_MODULE
))
5222 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5224 *pDescKind
= DESCKIND_TYPECOMP
;
5225 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5226 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5227 TRACE("module or enum: %s\n", debugstr_w(szName
));
5232 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5233 (pTypeInfo
->typekind
== TKIND_ENUM
))
5235 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5238 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5239 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5241 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5244 else if (hr
== TYPE_E_TYPEMISMATCH
)
5248 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5249 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5251 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5253 ITypeInfo
*subtypeinfo
;
5255 DESCKIND subdesckind
;
5257 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5258 &subtypeinfo
, &subdesckind
, &subbindptr
);
5259 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5261 TYPEDESC tdesc_appobject
;
5262 const VARDESC vardesc_appobject
=
5265 NULL
, /* lpstrSchema */
5280 VAR_STATIC
/* varkind */
5283 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5284 tdesc_appobject
.vt
= VT_USERDEFINED
;
5286 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5288 /* cleanup things filled in by Bind call so we can put our
5289 * application object data in there instead */
5290 switch (subdesckind
)
5292 case DESCKIND_FUNCDESC
:
5293 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5295 case DESCKIND_VARDESC
:
5296 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5301 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5303 if (pTypeInfo
->hreftype
== -1)
5304 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5306 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5310 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5311 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
5312 ITypeInfo_AddRef(*ppTInfo
);
5315 else if (hr
== TYPE_E_TYPEMISMATCH
)
5322 TRACE("type mismatch %s\n", debugstr_w(szName
));
5323 return TYPE_E_TYPEMISMATCH
;
5327 TRACE("name not found %s\n", debugstr_w(szName
));
5332 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5336 ITypeInfo
** ppTInfo
,
5337 ITypeComp
** ppTComp
)
5339 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5340 ITypeInfoImpl
*info
;
5342 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5344 if(!szName
|| !ppTInfo
|| !ppTComp
)
5345 return E_INVALIDARG
;
5347 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5354 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5355 ITypeInfo_AddRef(*ppTInfo
);
5356 *ppTComp
= &info
->ITypeComp_iface
;
5357 ITypeComp_AddRef(*ppTComp
);
5362 static const ITypeCompVtbl tlbtcvt
=
5365 ITypeLibComp_fnQueryInterface
,
5366 ITypeLibComp_fnAddRef
,
5367 ITypeLibComp_fnRelease
,
5369 ITypeLibComp_fnBind
,
5370 ITypeLibComp_fnBindType
5373 /*================== ITypeInfo(2) Methods ===================================*/
5374 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5376 ITypeInfoImpl
*pTypeInfoImpl
;
5378 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5381 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5382 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5383 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5384 pTypeInfoImpl
->ref
= 0;
5385 pTypeInfoImpl
->hreftype
= -1;
5386 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5387 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5388 list_init(&pTypeInfoImpl
->custdata_list
);
5390 TRACE("(%p)\n", pTypeInfoImpl
);
5391 return pTypeInfoImpl
;
5394 /* ITypeInfo::QueryInterface
5396 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5401 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5403 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5406 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5407 IsEqualIID(riid
,&IID_ITypeInfo
)||
5408 IsEqualIID(riid
,&IID_ITypeInfo2
))
5410 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5411 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5412 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5415 ITypeInfo2_AddRef(iface
);
5416 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5419 TRACE("-- Interface: E_NOINTERFACE\n");
5420 return E_NOINTERFACE
;
5423 /* ITypeInfo::AddRef
5425 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5427 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5428 ULONG ref
= InterlockedIncrement(&This
->ref
);
5430 TRACE("(%p)->ref is %u\n",This
, ref
);
5432 if (ref
== 1 /* incremented from 0 */)
5433 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5438 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5442 TRACE("destroying ITypeInfo(%p)\n",This
);
5444 for (i
= 0; i
< This
->cFuncs
; ++i
)
5447 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5448 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5450 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5451 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5453 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5454 heap_free(elemdesc
->u
.paramdesc
.pparamdescex
);
5456 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5458 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5459 heap_free(pFInfo
->pParamDesc
);
5460 TLB_FreeCustData(&pFInfo
->custdata_list
);
5462 heap_free(This
->funcdescs
);
5464 for(i
= 0; i
< This
->cVars
; ++i
)
5466 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5467 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5469 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5470 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5472 TLB_FreeCustData(&pVInfo
->custdata_list
);
5474 heap_free(This
->vardescs
);
5476 if(This
->impltypes
){
5477 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5478 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5479 TLB_FreeCustData(&pImpl
->custdata_list
);
5481 heap_free(This
->impltypes
);
5484 TLB_FreeCustData(&This
->custdata_list
);
5489 /* ITypeInfo::Release
5491 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5493 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5494 ULONG ref
= InterlockedDecrement(&This
->ref
);
5496 TRACE("(%p)->(%u)\n",This
, ref
);
5500 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5501 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5502 if (not_attached_to_typelib
)
5504 /* otherwise This will be freed when typelib is freed */
5510 /* ITypeInfo::GetTypeAttr
5512 * Retrieves a TYPEATTR structure that contains the attributes of the type
5516 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5517 LPTYPEATTR
*ppTypeAttr
)
5519 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5522 TRACE("(%p)\n",This
);
5524 size
= sizeof(**ppTypeAttr
);
5525 if (This
->typekind
== TKIND_ALIAS
)
5526 size
+= TLB_SizeTypeDesc(&This
->tdescAlias
, FALSE
);
5528 *ppTypeAttr
= heap_alloc(size
);
5530 return E_OUTOFMEMORY
;
5532 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5533 (*ppTypeAttr
)->lcid
= This
->lcid
;
5534 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5535 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5536 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5537 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5538 (*ppTypeAttr
)->typekind
= This
->typekind
;
5539 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5540 (*ppTypeAttr
)->cVars
= This
->cVars
;
5541 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5542 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5543 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5544 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5545 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5546 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5547 (*ppTypeAttr
)->tdescAlias
= This
->tdescAlias
;
5548 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5550 if (This
->typekind
== TKIND_ALIAS
)
5551 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5552 &This
->tdescAlias
, *ppTypeAttr
+ 1);
5554 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5555 /* This should include all the inherited funcs */
5556 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5557 /* This is always the size of IDispatch's vtbl */
5558 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5559 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5564 /* ITypeInfo::GetTypeComp
5566 * Retrieves the ITypeComp interface for the type description, which enables a
5567 * client compiler to bind to the type description's members.
5570 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5571 ITypeComp
* *ppTComp
)
5573 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5575 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5577 *ppTComp
= &This
->ITypeComp_iface
;
5578 ITypeComp_AddRef(*ppTComp
);
5582 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5584 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5585 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5586 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5590 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5593 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5594 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5596 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5597 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5598 *buffer
+= sizeof(PARAMDESCEX
);
5599 *pparamdescex_dest
= *pparamdescex_src
;
5600 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5601 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5602 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5603 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5606 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5610 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5612 UINT len
= SysStringLen(str
), i
;
5613 for (i
= 0; i
< len
; ++i
)
5619 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5621 if (V_VT(var
) == VT_INT
)
5622 return VariantChangeType(var
, var
, 0, VT_I4
);
5623 else if (V_VT(var
) == VT_UINT
)
5624 return VariantChangeType(var
, var
, 0, VT_UI4
);
5625 else if (V_VT(var
) == VT_BSTR
)
5626 return TLB_SanitizeBSTR(V_BSTR(var
));
5631 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5633 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5634 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5637 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5641 SIZE_T size
= sizeof(*src
);
5645 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5646 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5647 for (i
= 0; i
< src
->cParams
; i
++)
5649 size
+= sizeof(ELEMDESC
);
5650 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5653 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5654 if (!dest
) return E_OUTOFMEMORY
;
5657 if (dispinterface
) /* overwrite funckind */
5658 dest
->funckind
= FUNC_DISPATCH
;
5659 buffer
= (char *)(dest
+ 1);
5661 dest
->oVft
= dest
->oVft
& 0xFFFC;
5663 if (dest
->cScodes
) {
5664 dest
->lprgscode
= (SCODE
*)buffer
;
5665 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5666 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5668 dest
->lprgscode
= NULL
;
5670 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5673 SysFreeString((BSTR
)dest
);
5677 if (dest
->cParams
) {
5678 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5679 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5680 for (i
= 0; i
< src
->cParams
; i
++)
5682 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5688 /* undo the above actions */
5689 for (i
= i
- 1; i
>= 0; i
--)
5690 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5691 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5692 SysFreeString((BSTR
)dest
);
5696 dest
->lprgelemdescParam
= NULL
;
5698 /* special treatment for dispinterfaces: this makes functions appear
5699 * to return their [retval] value when it is really returning an
5701 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5703 if (dest
->cParams
&&
5704 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5706 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5707 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5709 ERR("elemdesc should have started with VT_PTR instead of:\n");
5711 dump_ELEMDESC(elemdesc
);
5712 return E_UNEXPECTED
;
5715 /* copy last parameter to the return value. we are using a flat
5716 * buffer so there is no danger of leaking memory in
5718 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5720 /* remove the last parameter */
5724 /* otherwise this function is made to appear to have no return
5726 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5734 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5736 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5738 if (index
>= This
->cFuncs
)
5739 return TYPE_E_ELEMENTNOTFOUND
;
5741 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5745 /* internal function to make the inherited interfaces' methods appear
5746 * part of the interface */
5747 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5748 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5750 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5752 UINT implemented_funcs
= 0;
5757 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5761 ITypeInfo
*pSubTypeInfo
;
5764 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5768 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5771 &sub_funcs
, hrefoffset
);
5772 implemented_funcs
+= sub_funcs
;
5773 ITypeInfo_Release(pSubTypeInfo
);
5776 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5780 *funcs
= implemented_funcs
+ This
->cFuncs
;
5784 if (index
< implemented_funcs
)
5785 return E_INVALIDARG
;
5786 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5790 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5792 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5795 switch (pTypeDesc
->vt
)
5797 case VT_USERDEFINED
:
5798 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5802 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5805 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5813 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5816 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5817 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5818 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5821 /* ITypeInfo::GetFuncDesc
5823 * Retrieves the FUNCDESC structure that contains information about a
5824 * specified function.
5827 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5828 LPFUNCDESC
*ppFuncDesc
)
5830 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5831 const FUNCDESC
*internal_funcdesc
;
5833 UINT hrefoffset
= 0;
5835 TRACE("(%p) index %d\n", This
, index
);
5838 return E_INVALIDARG
;
5840 if (This
->needs_layout
)
5841 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5843 if (This
->typekind
== TKIND_DISPATCH
)
5844 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5845 &internal_funcdesc
, NULL
,
5848 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5849 &internal_funcdesc
);
5852 WARN("description for function %d not found\n", index
);
5856 hr
= TLB_AllocAndInitFuncDesc(
5859 This
->typekind
== TKIND_DISPATCH
);
5861 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
5862 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5864 TRACE("-- 0x%08x\n", hr
);
5868 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5872 SIZE_T size
= sizeof(*src
);
5875 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5876 if (src
->varkind
== VAR_CONST
)
5877 size
+= sizeof(VARIANT
);
5878 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5880 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5881 if (!dest
) return E_OUTOFMEMORY
;
5884 buffer
= (char *)(dest
+ 1);
5885 if (src
->lpstrSchema
)
5888 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5889 len
= strlenW(src
->lpstrSchema
);
5890 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5891 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5894 if (src
->varkind
== VAR_CONST
)
5898 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5899 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5900 buffer
+= sizeof(VARIANT
);
5901 VariantInit(dest
->u
.lpvarValue
);
5902 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5905 SysFreeString((BSTR
)dest
);
5909 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5912 if (src
->varkind
== VAR_CONST
)
5913 VariantClear(dest
->u
.lpvarValue
);
5914 SysFreeString((BSTR
)dest
);
5921 /* ITypeInfo::GetVarDesc
5923 * Retrieves a VARDESC structure that describes the specified variable.
5926 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5927 LPVARDESC
*ppVarDesc
)
5929 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5930 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5932 TRACE("(%p) index %d\n", This
, index
);
5934 if(index
>= This
->cVars
)
5935 return TYPE_E_ELEMENTNOTFOUND
;
5937 if (This
->needs_layout
)
5938 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5940 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5943 /* ITypeInfo_GetNames
5945 * Retrieves the variable with the specified member ID (or the name of the
5946 * property or method and its parameters) that correspond to the specified
5949 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5950 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5952 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5953 const TLBFuncDesc
*pFDesc
;
5954 const TLBVarDesc
*pVDesc
;
5956 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5959 return E_INVALIDARG
;
5963 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
5966 if(!cMaxNames
|| !pFDesc
->Name
)
5969 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
5972 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
5973 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
5975 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
5981 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
5984 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
5989 if(This
->impltypes
&&
5990 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
5991 /* recursive search */
5994 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5995 if(SUCCEEDED(result
))
5997 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5998 ITypeInfo_Release(pTInfo
);
6001 WARN("Could not search inherited interface!\n");
6005 WARN("no names found\n");
6008 return TYPE_E_ELEMENTNOTFOUND
;
6014 /* ITypeInfo::GetRefTypeOfImplType
6016 * If a type description describes a COM class, it retrieves the type
6017 * description of the implemented interface types. For an interface,
6018 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6022 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6027 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6030 TRACE("(%p) index %d\n", This
, index
);
6031 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6035 /* only valid on dual interfaces;
6036 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6039 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6045 hr
= TYPE_E_ELEMENTNOTFOUND
;
6048 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6050 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6051 *pRefType
= This
->pTypeLib
->dispatch_href
;
6055 if(index
>= This
->cImplTypes
)
6056 hr
= TYPE_E_ELEMENTNOTFOUND
;
6058 *pRefType
= This
->impltypes
[index
].hRef
;
6064 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6066 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6072 /* ITypeInfo::GetImplTypeFlags
6074 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6075 * or base interface in a type description.
6077 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6078 UINT index
, INT
*pImplTypeFlags
)
6080 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6082 TRACE("(%p) index %d\n", This
, index
);
6085 return E_INVALIDARG
;
6087 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6088 *pImplTypeFlags
= 0;
6092 if(index
>= This
->cImplTypes
)
6093 return TYPE_E_ELEMENTNOTFOUND
;
6095 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6101 * Maps between member names and member IDs, and parameter names and
6104 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6105 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6107 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6108 const TLBVarDesc
*pVDesc
;
6112 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6115 /* init out parameters in case of failure */
6116 for (i
= 0; i
< cNames
; i
++)
6117 pMemId
[i
] = MEMBERID_NIL
;
6119 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6121 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6122 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6123 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6124 for(i
=1; i
< cNames
; i
++){
6125 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6126 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6128 if( j
<pFDesc
->funcdesc
.cParams
)
6131 ret
=DISP_E_UNKNOWNNAME
;
6133 TRACE("-- 0x%08x\n", ret
);
6137 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6140 *pMemId
= pVDesc
->vardesc
.memid
;
6143 /* not found, see if it can be found in an inherited interface */
6144 if(This
->impltypes
) {
6145 /* recursive search */
6147 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6149 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6150 ITypeInfo_Release(pTInfo
);
6153 WARN("Could not search inherited interface!\n");
6155 WARN("no names found\n");
6156 return DISP_E_UNKNOWNNAME
;
6162 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6163 __ASM_GLOBAL_FUNC( call_method
,
6165 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6166 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6167 "movl %esp,%ebp\n\t"
6168 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6170 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6172 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6173 "movl 12(%ebp),%edx\n\t"
6174 "movl %esp,%edi\n\t"
6177 "subl %edx,%edi\n\t"
6178 "andl $~15,%edi\n\t"
6179 "movl %edi,%esp\n\t"
6180 "movl 12(%ebp),%ecx\n\t"
6181 "movl 16(%ebp),%esi\n\t"
6184 "1:\tcall *8(%ebp)\n\t"
6185 "subl %esp,%edi\n\t"
6186 "movl 20(%ebp),%ecx\n\t"
6187 "movl %edi,(%ecx)\n\t"
6188 "leal -8(%ebp),%esp\n\t"
6190 __ASM_CFI(".cfi_same_value %edi\n\t")
6192 __ASM_CFI(".cfi_same_value %esi\n\t")
6194 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6195 __ASM_CFI(".cfi_same_value %ebp\n\t")
6198 /* same function but returning floating point */
6199 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6201 /* ITypeInfo::Invoke
6203 * Invokes a method, or accesses a property of an object, that implements the
6204 * interface described by the type description.
6207 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6211 if (TRACE_ON(ole
)) {
6213 TRACE("Calling %p(",func
);
6214 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6215 if (nrargs
> 30) TRACE("...");
6222 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6225 FIXME("unsupported calling convention %d\n",callconv
);
6229 TRACE("returns %08x\n",res
);
6233 #elif defined(__x86_64__)
6235 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6236 __ASM_GLOBAL_FUNC( call_method
,
6238 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6239 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6240 "movq %rsp,%rbp\n\t"
6241 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6243 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6245 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6246 "movq %rcx,%rax\n\t"
6249 "cmovgq %rdx,%rcx\n\t"
6250 "leaq 0(,%rcx,8),%rdx\n\t"
6251 "subq %rdx,%rsp\n\t"
6252 "andq $~15,%rsp\n\t"
6253 "movq %rsp,%rdi\n\t"
6256 "movq 0(%rsp),%rcx\n\t"
6257 "movq 8(%rsp),%rdx\n\t"
6258 "movq 16(%rsp),%r8\n\t"
6259 "movq 24(%rsp),%r9\n\t"
6260 "movq %rcx,%xmm0\n\t"
6261 "movq %rdx,%xmm1\n\t"
6262 "movq %r8,%xmm2\n\t"
6263 "movq %r9,%xmm3\n\t"
6265 "leaq -16(%rbp),%rsp\n\t"
6267 __ASM_CFI(".cfi_same_value %rdi\n\t")
6269 __ASM_CFI(".cfi_same_value %rsi\n\t")
6270 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6272 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6273 __ASM_CFI(".cfi_same_value %rbp\n\t")
6276 /* same function but returning floating point */
6277 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6279 #endif /* __x86_64__ */
6281 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6284 ITypeInfo
*tinfo2
= NULL
;
6285 TYPEATTR
*tattr
= NULL
;
6287 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6290 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6292 tdesc
->u
.hreftype
, hr
);
6295 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6298 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6299 ITypeInfo_Release(tinfo2
);
6303 switch (tattr
->typekind
)
6310 tdesc
= &tattr
->tdescAlias
;
6311 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6314 case TKIND_INTERFACE
:
6315 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6321 case TKIND_DISPATCH
:
6330 FIXME("TKIND_RECORD unhandled.\n");
6335 FIXME("TKIND_UNION unhandled.\n");
6340 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6344 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6345 ITypeInfo_Release(tinfo2
);
6349 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6353 /* enforce only one level of pointer indirection */
6354 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6356 tdesc
= tdesc
->u
.lptdesc
;
6358 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6359 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6360 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6361 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6362 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6364 VARTYPE vt_userdefined
= 0;
6365 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6366 if (tdesc
->vt
== VT_PTR
)
6368 vt_userdefined
= VT_BYREF
;
6369 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6371 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6373 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6374 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6376 *vt
|= vt_userdefined
;
6388 case VT_USERDEFINED
:
6389 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6396 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6397 hr
= DISP_E_BADVARTYPE
;
6401 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6416 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6422 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6426 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6428 ITypeInfo_Release(tinfo2
);
6432 switch(tattr
->typekind
) {
6434 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6437 case TKIND_INTERFACE
:
6438 case TKIND_DISPATCH
:
6439 *guid
= tattr
->guid
;
6443 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6444 hres
= E_UNEXPECTED
;
6447 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6448 ITypeInfo_Release(tinfo2
);
6452 /***********************************************************************
6453 * DispCallFunc (OLEAUT32.@)
6455 * Invokes a function of the specified calling convention, passing the
6456 * specified arguments and returns the result.
6459 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6460 * oVft [I] The offset in the vtable. See notes.
6461 * cc [I] Calling convention of the function to call.
6462 * vtReturn [I] The return type of the function.
6463 * cActuals [I] Number of parameters.
6464 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6465 * prgpvarg [I] The arguments to pass.
6466 * pvargResult [O] The return value of the function. Can be NULL.
6470 * Failure: HRESULT code.
6473 * The HRESULT return value of this function is not affected by the return
6474 * value of the user supplied function, which is returned in pvargResult.
6476 * If pvInstance is NULL then a non-object function is to be called and oVft
6477 * is the address of the function to call.
6479 * The cc parameter can be one of the following values:
6492 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6493 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6496 int argspos
, stack_offset
;
6501 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6502 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6503 pvargResult
, V_VT(pvargResult
));
6505 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6507 FIXME("unsupported calling convention %d\n",cc
);
6508 return E_INVALIDARG
;
6511 /* maximum size for an argument is sizeof(VARIANT) */
6512 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6514 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6518 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6519 func
= vtable
[oVft
/sizeof(void *)];
6520 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6522 else func
= (void *)oVft
;
6524 for (i
= 0; i
< cActuals
; i
++)
6526 VARIANT
*arg
= prgpvarg
[i
];
6537 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6538 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6542 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6543 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6545 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6546 args
[argspos
++] = V_BOOL(arg
);
6549 args
[argspos
++] = V_UI4(arg
);
6552 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6559 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6562 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6566 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6570 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6571 call_method( func
, argspos
, args
, &stack_offset
);
6576 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6579 WARN("invalid return type %u\n", vtReturn
);
6581 return E_INVALIDARG
;
6583 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6587 if (stack_offset
&& cc
== CC_STDCALL
)
6589 WARN( "stack pointer off by %d\n", stack_offset
);
6590 return DISP_E_BADCALLEE
;
6592 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6593 TRACE("retval: "); dump_Variant(pvargResult
);
6596 #elif defined(__x86_64__)
6602 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6603 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6604 pvargResult
, V_VT(pvargResult
));
6606 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6608 FIXME("unsupported calling convention %d\n",cc
);
6609 return E_INVALIDARG
;
6612 /* maximum size for an argument is sizeof(DWORD_PTR) */
6613 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6615 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6619 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6620 func
= vtable
[oVft
/sizeof(void *)];
6621 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6623 else func
= (void *)oVft
;
6625 for (i
= 0; i
< cActuals
; i
++)
6627 VARIANT
*arg
= prgpvarg
[i
];
6633 args
[argspos
++] = (ULONG_PTR
)arg
;
6635 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6636 args
[argspos
++] = V_BOOL(arg
);
6639 args
[argspos
++] = V_UI8(arg
);
6642 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6649 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6653 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6657 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6658 call_method( func
, argspos
, args
);
6661 WARN("invalid return type %u\n", vtReturn
);
6663 return E_INVALIDARG
;
6665 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6669 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6670 TRACE("retval: "); dump_Variant(pvargResult
);
6674 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6675 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6680 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6682 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6685 #define INVBUF_ELEMENT_SIZE \
6686 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6687 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6688 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6689 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6690 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6691 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6692 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6693 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6695 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6700 DISPPARAMS
*pDispParams
,
6701 VARIANT
*pVarResult
,
6702 EXCEPINFO
*pExcepInfo
,
6705 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6707 unsigned int var_index
;
6710 const TLBFuncDesc
*pFuncInfo
;
6713 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6714 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6717 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6718 return DISP_E_MEMBERNOTFOUND
;
6722 ERR("NULL pDispParams not allowed\n");
6723 return E_INVALIDARG
;
6726 dump_DispParms(pDispParams
);
6728 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6730 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6731 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6732 return E_INVALIDARG
;
6735 /* we do this instead of using GetFuncDesc since it will return a fake
6736 * FUNCDESC for dispinterfaces and we want the real function description */
6737 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6738 pFuncInfo
= &This
->funcdescs
[fdc
];
6739 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6740 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6741 !func_restricted( &pFuncInfo
->funcdesc
))
6745 if (fdc
< This
->cFuncs
) {
6746 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6750 TRACE("invoking:\n");
6751 dump_TLBFuncDescOne(pFuncInfo
);
6754 switch (func_desc
->funckind
) {
6755 case FUNC_PUREVIRTUAL
:
6756 case FUNC_VIRTUAL
: {
6757 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6759 VARIANT retval
; /* pointer for storing byref retvals in */
6760 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6761 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6762 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6763 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6764 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6765 UINT vargs_converted
=0;
6769 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6771 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6773 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6774 hres
= DISP_E_PARAMNOTFOUND
;
6779 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6781 ERR("functions with the vararg attribute do not support named arguments\n");
6782 hres
= DISP_E_NONAMEDARGS
;
6786 for (i
= 0; i
< func_desc
->cParams
; i
++)
6788 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6789 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6794 TRACE("changing args\n");
6795 for (i
= 0; i
< func_desc
->cParams
; i
++)
6797 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6798 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6799 VARIANTARG
*src_arg
;
6801 if (wParamFlags
& PARAMFLAG_FLCID
)
6804 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6806 V_I4(arg
) = This
->pTypeLib
->lcid
;
6815 for (j
= 0; j
< cNamedArgs
; j
++)
6816 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6818 src_arg
= &pDispParams
->rgvarg
[j
];
6823 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6825 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6829 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6831 /* under most conditions the caller is not allowed to
6832 * pass in a dispparam arg in the index of what would be
6833 * the retval parameter. however, there is an exception
6834 * where the extra parameter is used in an extra
6835 * IDispatch::Invoke below */
6836 if ((i
< pDispParams
->cArgs
) &&
6837 ((func_desc
->cParams
!= 1) || !pVarResult
||
6838 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6840 hres
= DISP_E_BADPARAMCOUNT
;
6844 /* note: this check is placed so that if the caller passes
6845 * in a VARIANTARG for the retval we just ignore it, like
6847 if (i
== func_desc
->cParams
- 1)
6850 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6851 memset(arg
, 0, sizeof(*arg
));
6852 V_VT(arg
) = rgvt
[i
];
6853 memset(&retval
, 0, sizeof(retval
));
6854 V_BYREF(arg
) = &retval
;
6858 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6859 hres
= E_UNEXPECTED
;
6865 dump_Variant(src_arg
);
6867 if(rgvt
[i
]!=V_VT(src_arg
))
6869 if (rgvt
[i
] == VT_VARIANT
)
6870 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6871 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6873 if (rgvt
[i
] == V_VT(src_arg
))
6874 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6877 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6878 if (wParamFlags
& PARAMFLAG_FIN
)
6879 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6880 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6882 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6884 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6887 SAFEARRAYBOUND bound
;
6891 bound
.cElements
= pDispParams
->cArgs
-i
;
6892 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6894 ERR("SafeArrayCreate failed\n");
6897 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6900 ERR("SafeArrayAccessData failed with %x\n", hres
);
6901 SafeArrayDestroy(a
);
6904 for (j
= 0; j
< bound
.cElements
; j
++)
6905 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6906 hres
= SafeArrayUnaccessData(a
);
6909 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6910 SafeArrayDestroy(a
);
6913 V_ARRAY(&rgvarg
[i
]) = a
;
6914 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6916 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6918 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6919 if (wParamFlags
& PARAMFLAG_FIN
)
6920 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6922 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6923 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6924 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6926 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6928 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6929 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6933 /* FIXME: this doesn't work for VT_BYREF arguments if
6934 * they are not the same type as in the paramdesc */
6935 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6936 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6937 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6942 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6943 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6944 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6947 prgpvarg
[i
] = &rgvarg
[i
];
6951 prgpvarg
[i
] = src_arg
;
6954 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
6955 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
6956 && V_UNKNOWN(prgpvarg
[i
])) {
6957 IUnknown
*userdefined_iface
;
6960 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
6964 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
6966 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
6970 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
6971 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
6974 else if (wParamFlags
& PARAMFLAG_FOPT
)
6977 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6978 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6980 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6986 VARIANTARG
*missing_arg
;
6987 /* if the function wants a pointer to a variant then
6988 * set that up, otherwise just pass the VT_ERROR in
6989 * the argument by value */
6990 if (rgvt
[i
] & VT_BYREF
)
6992 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6993 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6994 V_VARIANTREF(arg
) = missing_arg
;
6998 V_VT(missing_arg
) = VT_ERROR
;
6999 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7004 hres
= DISP_E_BADPARAMCOUNT
;
7008 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7010 /* VT_VOID is a special case for return types, so it is not
7011 * handled in the general function */
7012 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7013 V_VT(&varresult
) = VT_EMPTY
;
7016 V_VT(&varresult
) = 0;
7017 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7018 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7021 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7022 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7023 prgpvarg
, &varresult
);
7025 vargs_converted
= 0;
7027 for (i
= 0; i
< func_desc
->cParams
; i
++)
7029 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7030 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7032 if (wParamFlags
& PARAMFLAG_FLCID
)
7034 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7038 TRACE("[retval] value: ");
7039 dump_Variant(prgpvarg
[i
]);
7044 VariantInit(pVarResult
);
7045 /* deref return value */
7046 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7049 VARIANT_ClearInd(prgpvarg
[i
]);
7051 else if (vargs_converted
< pDispParams
->cArgs
)
7053 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7054 if (wParamFlags
& PARAMFLAG_FOUT
)
7056 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7058 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7062 ERR("failed to convert param %d to vt %d\n", i
,
7063 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7068 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7069 func_desc
->cParamsOpt
< 0 &&
7070 i
== func_desc
->cParams
-1)
7072 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7075 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7078 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7081 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7084 ERR("SafeArrayAccessData failed with %x\n", hres
);
7087 for (j
= 0; j
<= ubound
; j
++)
7088 VariantClear(&v
[j
]);
7089 hres
= SafeArrayUnaccessData(a
);
7092 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7096 VariantClear(&rgvarg
[i
]);
7099 else if (wParamFlags
& PARAMFLAG_FOPT
)
7101 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7102 VariantClear(&rgvarg
[i
]);
7105 VariantClear(&missing_arg
[i
]);
7108 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7110 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7111 hres
= DISP_E_EXCEPTION
;
7114 IErrorInfo
*pErrorInfo
;
7115 pExcepInfo
->scode
= V_ERROR(&varresult
);
7116 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7118 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7119 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7120 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7121 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7123 IErrorInfo_Release(pErrorInfo
);
7127 if (V_VT(&varresult
) != VT_ERROR
)
7129 TRACE("varresult value: ");
7130 dump_Variant(&varresult
);
7134 VariantClear(pVarResult
);
7135 *pVarResult
= varresult
;
7138 VariantClear(&varresult
);
7141 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7142 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7143 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7144 (pDispParams
->cArgs
!= 0))
7146 if (V_VT(pVarResult
) == VT_DISPATCH
)
7148 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7149 /* Note: not VariantClear; we still need the dispatch
7150 * pointer to be valid */
7151 VariantInit(pVarResult
);
7152 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7153 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7154 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7155 IDispatch_Release(pDispatch
);
7159 VariantClear(pVarResult
);
7160 hres
= DISP_E_NOTACOLLECTION
;
7168 case FUNC_DISPATCH
: {
7171 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7172 if (SUCCEEDED(hres
)) {
7173 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7174 hres
= IDispatch_Invoke(
7175 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7176 pVarResult
,pExcepInfo
,pArgErr
7179 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7180 IDispatch_Release(disp
);
7182 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7186 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7191 TRACE("-- 0x%08x\n", hres
);
7194 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7197 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7198 if(FAILED(hres
)) return hres
;
7200 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7201 dump_VARDESC(var_desc
);
7202 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7206 /* not found, look for it in inherited interfaces */
7207 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7208 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7209 if(This
->impltypes
) {
7210 /* recursive search */
7212 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7213 if(SUCCEEDED(hres
)){
7214 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7215 ITypeInfo_Release(pTInfo
);
7218 WARN("Could not search inherited interface!\n");
7221 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7222 return DISP_E_MEMBERNOTFOUND
;
7225 /* ITypeInfo::GetDocumentation
7227 * Retrieves the documentation string, the complete Help file name and path,
7228 * and the context ID for the Help topic for a specified type description.
7230 * (Can be tested by the Visual Basic Editor in Word for instance.)
7232 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7233 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7234 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7236 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7237 const TLBFuncDesc
*pFDesc
;
7238 const TLBVarDesc
*pVDesc
;
7239 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7240 " HelpContext(%p) HelpFile(%p)\n",
7241 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7242 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7244 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7246 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7248 *pdwHelpContext
=This
->dwHelpContext
;
7250 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7252 }else {/* for a member */
7253 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7256 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7258 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7260 *pdwHelpContext
=pFDesc
->helpcontext
;
7262 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7265 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7268 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7270 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7272 *pdwHelpContext
=pVDesc
->HelpContext
;
7274 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7279 if(This
->impltypes
&&
7280 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7281 /* recursive search */
7284 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7285 if(SUCCEEDED(result
)) {
7286 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7287 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7288 ITypeInfo_Release(pTInfo
);
7291 WARN("Could not search inherited interface!\n");
7294 WARN("member %d not found\n", memid
);
7295 return TYPE_E_ELEMENTNOTFOUND
;
7298 /* ITypeInfo::GetDllEntry
7300 * Retrieves a description or specification of an entry point for a function
7303 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7304 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7307 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7308 const TLBFuncDesc
*pFDesc
;
7310 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7312 if (pBstrDllName
) *pBstrDllName
= NULL
;
7313 if (pBstrName
) *pBstrName
= NULL
;
7314 if (pwOrdinal
) *pwOrdinal
= 0;
7316 if (This
->typekind
!= TKIND_MODULE
)
7317 return TYPE_E_BADMODULEKIND
;
7319 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7321 dump_TypeInfo(This
);
7323 dump_TLBFuncDescOne(pFDesc
);
7326 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7328 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7330 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7338 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7341 return TYPE_E_ELEMENTNOTFOUND
;
7344 /* internal function to make the inherited interfaces' methods appear
7345 * part of the interface */
7346 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7347 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7349 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7352 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7354 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7356 ITypeInfo
*pSubTypeInfo
;
7358 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7362 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7364 ITypeInfo_Release(pSubTypeInfo
);
7368 *hRefType
-= DISPATCH_HREF_OFFSET
;
7370 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7371 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7376 /* ITypeInfo::GetRefTypeInfo
7378 * If a type description references other type descriptions, it retrieves
7379 * the referenced type descriptions.
7381 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7384 ITypeInfo
**ppTInfo
)
7386 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7387 HRESULT result
= E_FAIL
;
7390 return E_INVALIDARG
;
7392 if ((INT
)hRefType
< 0) {
7393 ITypeInfoImpl
*pTypeInfoImpl
;
7395 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7396 !(This
->typekind
== TKIND_INTERFACE
||
7397 This
->typekind
== TKIND_DISPATCH
))
7398 return TYPE_E_ELEMENTNOTFOUND
;
7400 /* when we meet a DUAL typeinfo, we must create the alternate
7403 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7405 *pTypeInfoImpl
= *This
;
7406 pTypeInfoImpl
->ref
= 0;
7408 if (This
->typekind
== TKIND_INTERFACE
)
7409 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7411 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7413 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7414 /* the AddRef implicitly adds a reference to the parent typelib, which
7415 * stops the copied data from being destroyed until the new typeinfo's
7416 * refcount goes to zero, but we need to signal to the new instance to
7417 * not free its data structures when it is destroyed */
7418 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7420 ITypeInfo_AddRef(*ppTInfo
);
7423 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7424 (This
->typekind
== TKIND_DISPATCH
))
7426 HREFTYPE href_dispatch
= hRefType
;
7427 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7429 TLBRefType
*ref_type
;
7430 ITypeLib
*pTLib
= NULL
;
7433 if(!(hRefType
& 0x1)){
7434 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7436 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7439 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7440 ITypeInfo_AddRef(*ppTInfo
);
7446 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7448 if(ref_type
->reference
== (hRefType
& (~0x3)))
7451 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7453 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7457 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7459 TRACE("internal reference\n");
7460 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7462 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7463 TRACE("typeinfo in imported typelib that is already loaded\n");
7464 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7465 ITypeLib_AddRef(pTLib
);
7468 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7469 result
= LoadRegTypeLib( TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7470 ref_type
->pImpTLInfo
->wVersionMajor
,
7471 ref_type
->pImpTLInfo
->wVersionMinor
,
7472 ref_type
->pImpTLInfo
->lcid
,
7475 if(FAILED(result
)) {
7476 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
7477 result
=LoadTypeLib(libnam
, &pTLib
);
7478 SysFreeString(libnam
);
7480 if(SUCCEEDED(result
)) {
7481 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7482 ITypeLib_AddRef(pTLib
);
7486 if(SUCCEEDED(result
)) {
7487 if(ref_type
->index
== TLB_REF_USE_GUID
)
7488 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7490 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7493 ITypeLib_Release(pTLib
);
7497 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7498 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7502 /* ITypeInfo::AddressOfMember
7504 * Retrieves the addresses of static functions or variables, such as those
7507 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7508 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7510 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7516 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7518 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7522 module
= LoadLibraryW(dll
);
7525 ERR("couldn't load %s\n", debugstr_w(dll
));
7527 SysFreeString(entry
);
7528 return STG_E_FILENOTFOUND
;
7530 /* FIXME: store library somewhere where we can free it */
7535 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7536 entryA
= heap_alloc(len
);
7537 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7539 *ppv
= GetProcAddress(module
, entryA
);
7541 ERR("function not found %s\n", debugstr_a(entryA
));
7547 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7549 ERR("function not found %d\n", ordinal
);
7553 SysFreeString(entry
);
7556 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7561 /* ITypeInfo::CreateInstance
7563 * Creates a new instance of a type that describes a component object class
7566 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7567 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7569 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7573 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7579 WARN("Not able to aggregate\n");
7580 return CLASS_E_NOAGGREGATION
;
7583 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7584 if(FAILED(hr
)) return hr
;
7586 if(pTA
->typekind
!= TKIND_COCLASS
)
7588 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7594 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7597 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7598 TRACE("GetActiveObject rets %08x\n", hr
);
7601 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7602 IUnknown_Release(pUnk
);
7607 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7608 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7612 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7616 /* ITypeInfo::GetMops
7618 * Retrieves marshalling information.
7620 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7623 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7624 FIXME("(%p %d) stub!\n", This
, memid
);
7629 /* ITypeInfo::GetContainingTypeLib
7631 * Retrieves the containing type library and the index of the type description
7632 * within that type library.
7634 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7635 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7637 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7639 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7641 *pIndex
=This
->index
;
7642 TRACE("returning pIndex=%d\n", *pIndex
);
7646 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7647 ITypeLib_AddRef(*ppTLib
);
7648 TRACE("returning ppTLib=%p\n", *ppTLib
);
7654 /* ITypeInfo::ReleaseTypeAttr
7656 * Releases a TYPEATTR previously returned by Get
7659 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7660 TYPEATTR
* pTypeAttr
)
7662 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7663 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7664 heap_free(pTypeAttr
);
7667 /* ITypeInfo::ReleaseFuncDesc
7669 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7671 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7673 FUNCDESC
*pFuncDesc
)
7675 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7678 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7680 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7681 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7682 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7684 SysFreeString((BSTR
)pFuncDesc
);
7687 /* ITypeInfo::ReleaseVarDesc
7689 * Releases a VARDESC previously returned by GetVarDesc.
7691 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7694 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7695 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7697 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
7698 if (pVarDesc
->varkind
== VAR_CONST
)
7699 VariantClear(pVarDesc
->u
.lpvarValue
);
7700 SysFreeString((BSTR
)pVarDesc
);
7703 /* ITypeInfo2::GetTypeKind
7705 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7708 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7709 TYPEKIND
*pTypeKind
)
7711 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7712 *pTypeKind
=This
->typekind
;
7713 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7717 /* ITypeInfo2::GetTypeFlags
7719 * Returns the type flags without any allocations. This returns a DWORD type
7720 * flag, which expands the type flags without growing the TYPEATTR (type
7724 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7726 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7727 *pTypeFlags
=This
->wTypeFlags
;
7728 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7732 /* ITypeInfo2::GetFuncIndexOfMemId
7733 * Binds to a specific member based on a known DISPID, where the member name
7734 * is not known (for example, when binding to a default member).
7737 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7738 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7740 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7744 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7745 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7746 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7749 if(fdc
< This
->cFuncs
) {
7753 result
= TYPE_E_ELEMENTNOTFOUND
;
7755 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7756 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7760 /* TypeInfo2::GetVarIndexOfMemId
7762 * Binds to a specific member based on a known DISPID, where the member name
7763 * is not known (for example, when binding to a default member).
7766 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7767 MEMBERID memid
, UINT
*pVarIndex
)
7769 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7770 TLBVarDesc
*pVarInfo
;
7772 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7774 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7776 return TYPE_E_ELEMENTNOTFOUND
;
7778 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7783 /* ITypeInfo2::GetCustData
7785 * Gets the custom data
7787 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7792 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7793 TLBCustData
*pCData
;
7795 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7797 if(!guid
|| !pVarVal
)
7798 return E_INVALIDARG
;
7800 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
7802 VariantInit( pVarVal
);
7804 VariantCopy( pVarVal
, &pCData
->data
);
7806 VariantClear( pVarVal
);
7810 /* ITypeInfo2::GetFuncCustData
7812 * Gets the custom data
7814 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7820 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7821 TLBCustData
*pCData
;
7822 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7824 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7826 if(index
>= This
->cFuncs
)
7827 return TYPE_E_ELEMENTNOTFOUND
;
7829 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7831 return TYPE_E_ELEMENTNOTFOUND
;
7833 VariantInit(pVarVal
);
7834 VariantCopy(pVarVal
, &pCData
->data
);
7839 /* ITypeInfo2::GetParamCustData
7841 * Gets the custom data
7843 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7850 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7851 TLBCustData
*pCData
;
7852 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7854 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7855 debugstr_guid(guid
), pVarVal
);
7857 if(indexFunc
>= This
->cFuncs
)
7858 return TYPE_E_ELEMENTNOTFOUND
;
7860 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7861 return TYPE_E_ELEMENTNOTFOUND
;
7863 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7865 return TYPE_E_ELEMENTNOTFOUND
;
7867 VariantInit(pVarVal
);
7868 VariantCopy(pVarVal
, &pCData
->data
);
7873 /* ITypeInfo2::GetVarCustData
7875 * Gets the custom data
7877 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7883 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7884 TLBCustData
*pCData
;
7885 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7887 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7889 if(index
>= This
->cVars
)
7890 return TYPE_E_ELEMENTNOTFOUND
;
7892 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7894 return TYPE_E_ELEMENTNOTFOUND
;
7896 VariantInit(pVarVal
);
7897 VariantCopy(pVarVal
, &pCData
->data
);
7902 /* ITypeInfo2::GetImplCustData
7904 * Gets the custom data
7906 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7912 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7913 TLBCustData
*pCData
;
7914 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7916 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7918 if(index
>= This
->cImplTypes
)
7919 return TYPE_E_ELEMENTNOTFOUND
;
7921 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7923 return TYPE_E_ELEMENTNOTFOUND
;
7925 VariantInit(pVarVal
);
7926 VariantCopy(pVarVal
, &pCData
->data
);
7931 /* ITypeInfo2::GetDocumentation2
7933 * Retrieves the documentation string, the complete Help file name and path,
7934 * the localization context to use, and the context ID for the library Help
7935 * topic in the Help file.
7938 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7942 BSTR
*pbstrHelpString
,
7943 DWORD
*pdwHelpStringContext
,
7944 BSTR
*pbstrHelpStringDll
)
7946 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7947 const TLBFuncDesc
*pFDesc
;
7948 const TLBVarDesc
*pVDesc
;
7949 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7950 "HelpStringContext(%p) HelpStringDll(%p)\n",
7951 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7952 pbstrHelpStringDll
);
7953 /* the help string should be obtained from the helpstringdll,
7954 * using the _DLLGetDocumentation function, based on the supplied
7955 * lcid. Nice to do sometime...
7957 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7959 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
7960 if(pdwHelpStringContext
)
7961 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7962 if(pbstrHelpStringDll
)
7963 *pbstrHelpStringDll
=
7964 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7966 }else {/* for a member */
7967 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7970 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7971 if(pdwHelpStringContext
)
7972 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7973 if(pbstrHelpStringDll
)
7974 *pbstrHelpStringDll
=
7975 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7978 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7981 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7982 if(pdwHelpStringContext
)
7983 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7984 if(pbstrHelpStringDll
)
7985 *pbstrHelpStringDll
=
7986 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7990 return TYPE_E_ELEMENTNOTFOUND
;
7993 /* ITypeInfo2::GetAllCustData
7995 * Gets all custom data items for the Type info.
7998 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8000 CUSTDATA
*pCustData
)
8002 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8004 TRACE("%p %p\n", This
, pCustData
);
8006 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
8009 /* ITypeInfo2::GetAllFuncCustData
8011 * Gets all custom data items for the specified Function
8014 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8017 CUSTDATA
*pCustData
)
8019 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8020 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8022 TRACE("%p %u %p\n", This
, index
, pCustData
);
8024 if(index
>= This
->cFuncs
)
8025 return TYPE_E_ELEMENTNOTFOUND
;
8027 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8030 /* ITypeInfo2::GetAllParamCustData
8032 * Gets all custom data items for the Functions
8035 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8036 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8038 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8039 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8041 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8043 if(indexFunc
>= This
->cFuncs
)
8044 return TYPE_E_ELEMENTNOTFOUND
;
8046 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8047 return TYPE_E_ELEMENTNOTFOUND
;
8049 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8052 /* ITypeInfo2::GetAllVarCustData
8054 * Gets all custom data items for the specified Variable
8057 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8058 UINT index
, CUSTDATA
*pCustData
)
8060 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8061 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8063 TRACE("%p %u %p\n", This
, index
, pCustData
);
8065 if(index
>= This
->cVars
)
8066 return TYPE_E_ELEMENTNOTFOUND
;
8068 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8071 /* ITypeInfo2::GetAllImplCustData
8073 * Gets all custom data items for the specified implementation type
8076 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8079 CUSTDATA
*pCustData
)
8081 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8082 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8084 TRACE("%p %u %p\n", This
, index
, pCustData
);
8086 if(index
>= This
->cImplTypes
)
8087 return TYPE_E_ELEMENTNOTFOUND
;
8089 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8092 static const ITypeInfo2Vtbl tinfvt
=
8095 ITypeInfo_fnQueryInterface
,
8097 ITypeInfo_fnRelease
,
8099 ITypeInfo_fnGetTypeAttr
,
8100 ITypeInfo_fnGetTypeComp
,
8101 ITypeInfo_fnGetFuncDesc
,
8102 ITypeInfo_fnGetVarDesc
,
8103 ITypeInfo_fnGetNames
,
8104 ITypeInfo_fnGetRefTypeOfImplType
,
8105 ITypeInfo_fnGetImplTypeFlags
,
8106 ITypeInfo_fnGetIDsOfNames
,
8108 ITypeInfo_fnGetDocumentation
,
8109 ITypeInfo_fnGetDllEntry
,
8110 ITypeInfo_fnGetRefTypeInfo
,
8111 ITypeInfo_fnAddressOfMember
,
8112 ITypeInfo_fnCreateInstance
,
8113 ITypeInfo_fnGetMops
,
8114 ITypeInfo_fnGetContainingTypeLib
,
8115 ITypeInfo_fnReleaseTypeAttr
,
8116 ITypeInfo_fnReleaseFuncDesc
,
8117 ITypeInfo_fnReleaseVarDesc
,
8119 ITypeInfo2_fnGetTypeKind
,
8120 ITypeInfo2_fnGetTypeFlags
,
8121 ITypeInfo2_fnGetFuncIndexOfMemId
,
8122 ITypeInfo2_fnGetVarIndexOfMemId
,
8123 ITypeInfo2_fnGetCustData
,
8124 ITypeInfo2_fnGetFuncCustData
,
8125 ITypeInfo2_fnGetParamCustData
,
8126 ITypeInfo2_fnGetVarCustData
,
8127 ITypeInfo2_fnGetImplTypeCustData
,
8128 ITypeInfo2_fnGetDocumentation2
,
8129 ITypeInfo2_fnGetAllCustData
,
8130 ITypeInfo2_fnGetAllFuncCustData
,
8131 ITypeInfo2_fnGetAllParamCustData
,
8132 ITypeInfo2_fnGetAllVarCustData
,
8133 ITypeInfo2_fnGetAllImplTypeCustData
,
8136 /******************************************************************************
8137 * CreateDispTypeInfo [OLEAUT32.31]
8139 * Build type information for an object so it can be called through an
8140 * IDispatch interface.
8143 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8144 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8147 * This call allows an objects methods to be accessed through IDispatch, by
8148 * building an ITypeInfo object that IDispatch can use to call through.
8150 HRESULT WINAPI
CreateDispTypeInfo(
8151 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8152 LCID lcid
, /* [I] Locale Id */
8153 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8155 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8156 ITypeLibImpl
*pTypeLibImpl
;
8157 unsigned int param
, func
;
8158 TLBFuncDesc
*pFuncDesc
;
8162 pTypeLibImpl
= TypeLibImpl_Constructor();
8163 if (!pTypeLibImpl
) return E_FAIL
;
8165 pTypeLibImpl
->TypeInfoCount
= 2;
8166 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8168 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8169 pTIIface
->pTypeLib
= pTypeLibImpl
;
8170 pTIIface
->index
= 0;
8171 pTIIface
->Name
= NULL
;
8172 pTIIface
->dwHelpContext
= -1;
8173 pTIIface
->guid
= NULL
;
8174 pTIIface
->lcid
= lcid
;
8175 pTIIface
->typekind
= TKIND_INTERFACE
;
8176 pTIIface
->wMajorVerNum
= 0;
8177 pTIIface
->wMinorVerNum
= 0;
8178 pTIIface
->cbAlignment
= 2;
8179 pTIIface
->cbSizeInstance
= -1;
8180 pTIIface
->cbSizeVft
= -1;
8181 pTIIface
->cFuncs
= 0;
8182 pTIIface
->cImplTypes
= 0;
8183 pTIIface
->cVars
= 0;
8184 pTIIface
->wTypeFlags
= 0;
8185 pTIIface
->hreftype
= 0;
8187 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8188 pFuncDesc
= pTIIface
->funcdescs
;
8189 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8190 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8191 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8192 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8193 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8194 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8195 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8196 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8197 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8198 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8199 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8200 pFuncDesc
->funcdesc
.cScodes
= 0;
8201 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8202 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8203 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8204 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8205 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8206 md
->cArgs
* sizeof(ELEMDESC
));
8207 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8208 for(param
= 0; param
< md
->cArgs
; param
++) {
8209 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8210 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8212 pFuncDesc
->helpcontext
= 0;
8213 pFuncDesc
->HelpStringContext
= 0;
8214 pFuncDesc
->HelpString
= NULL
;
8215 pFuncDesc
->Entry
= NULL
;
8216 list_init(&pFuncDesc
->custdata_list
);
8221 dump_TypeInfo(pTIIface
);
8223 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8224 pTIClass
->pTypeLib
= pTypeLibImpl
;
8225 pTIClass
->index
= 1;
8226 pTIClass
->Name
= NULL
;
8227 pTIClass
->dwHelpContext
= -1;
8228 pTIClass
->guid
= NULL
;
8229 pTIClass
->lcid
= lcid
;
8230 pTIClass
->typekind
= TKIND_COCLASS
;
8231 pTIClass
->wMajorVerNum
= 0;
8232 pTIClass
->wMinorVerNum
= 0;
8233 pTIClass
->cbAlignment
= 2;
8234 pTIClass
->cbSizeInstance
= -1;
8235 pTIClass
->cbSizeVft
= -1;
8236 pTIClass
->cFuncs
= 0;
8237 pTIClass
->cImplTypes
= 1;
8238 pTIClass
->cVars
= 0;
8239 pTIClass
->wTypeFlags
= 0;
8240 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8242 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8244 ref
= heap_alloc_zero(sizeof(*ref
));
8245 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8246 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8248 dump_TypeInfo(pTIClass
);
8250 *pptinfo
= (ITypeInfo
*)pTIClass
;
8252 ITypeInfo_AddRef(*pptinfo
);
8253 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8259 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8261 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8263 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
8266 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8268 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8270 return ITypeInfo_AddRef((ITypeInfo
*)This
);
8273 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8275 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8277 return ITypeInfo_Release((ITypeInfo
*)This
);
8280 static HRESULT WINAPI
ITypeComp_fnBind(
8285 ITypeInfo
** ppTInfo
,
8286 DESCKIND
* pDescKind
,
8289 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8290 const TLBFuncDesc
*pFDesc
;
8291 const TLBVarDesc
*pVDesc
;
8292 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8295 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8297 *pDescKind
= DESCKIND_NONE
;
8298 pBindPtr
->lpfuncdesc
= NULL
;
8301 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8302 pFDesc
= &This
->funcdescs
[fdc
];
8303 if (!strcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8304 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8307 /* name found, but wrong flags */
8308 hr
= TYPE_E_TYPEMISMATCH
;
8312 if (fdc
< This
->cFuncs
)
8314 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8316 &pBindPtr
->lpfuncdesc
,
8317 This
->typekind
== TKIND_DISPATCH
);
8320 *pDescKind
= DESCKIND_FUNCDESC
;
8321 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8322 ITypeInfo_AddRef(*ppTInfo
);
8325 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8327 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8330 *pDescKind
= DESCKIND_VARDESC
;
8331 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8332 ITypeInfo_AddRef(*ppTInfo
);
8336 /* FIXME: search each inherited interface, not just the first */
8337 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8338 /* recursive search */
8342 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8345 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8346 ITypeInfo_Release(pTInfo
);
8350 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8351 ITypeComp_Release(pTComp
);
8354 WARN("Could not search inherited interface!\n");
8356 if (hr
== DISP_E_MEMBERNOTFOUND
)
8358 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8362 static HRESULT WINAPI
ITypeComp_fnBindType(
8366 ITypeInfo
** ppTInfo
,
8367 ITypeComp
** ppTComp
)
8369 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8371 /* strange behaviour (does nothing) but like the
8374 if (!ppTInfo
|| !ppTComp
)
8383 static const ITypeCompVtbl tcompvt
=
8386 ITypeComp_fnQueryInterface
,
8388 ITypeComp_fnRelease
,
8391 ITypeComp_fnBindType
8394 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8395 REFIID riid
, void **object
)
8397 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8399 return ITypeLib2_QueryInterface((ITypeLib2
*)This
, riid
, object
);
8402 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8404 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8406 return ITypeLib2_AddRef((ITypeLib2
*)This
);
8409 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8411 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8413 return ITypeLib2_Release((ITypeLib2
*)This
);
8416 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8417 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8419 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8420 ITypeInfoImpl
*info
;
8423 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8425 if (!ctinfo
|| !name
)
8426 return E_INVALIDARG
;
8428 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8430 return TYPE_E_NAMECONFLICT
;
8432 if (This
->typeinfos
)
8433 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8434 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8436 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8438 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8440 info
->pTypeLib
= This
;
8441 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8442 info
->index
= This
->TypeInfoCount
;
8443 info
->typekind
= kind
;
8444 info
->cbAlignment
= 4;
8446 switch(info
->typekind
) {
8448 case TKIND_INTERFACE
:
8449 case TKIND_DISPATCH
:
8451 info
->cbSizeInstance
= 4;
8455 info
->cbSizeInstance
= 0;
8458 info
->cbSizeInstance
= 2;
8461 info
->cbSizeInstance
= -0x75;
8464 FIXME("unrecognized typekind %d\n", info
->typekind
);
8465 info
->cbSizeInstance
= 0xdeadbeef;
8469 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8470 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8472 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8476 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8478 ++This
->TypeInfoCount
;
8483 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8486 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8488 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8491 return E_INVALIDARG
;
8493 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8498 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8499 WORD majorVerNum
, WORD minorVerNum
)
8501 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8503 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8505 This
->ver_major
= majorVerNum
;
8506 This
->ver_minor
= minorVerNum
;
8511 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8514 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8516 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8518 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
);
8523 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8526 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8528 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8531 return E_INVALIDARG
;
8533 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8538 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8539 LPOLESTR helpFileName
)
8541 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8543 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8546 return E_INVALIDARG
;
8548 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8553 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8556 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8558 TRACE("%p %d\n", This
, helpContext
);
8560 This
->dwHelpContext
= helpContext
;
8565 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8568 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8570 TRACE("%p %x\n", This
, lcid
);
8572 This
->set_lcid
= lcid
;
8577 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8580 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8582 TRACE("%p %x\n", This
, libFlags
);
8584 This
->libflags
= libFlags
;
8589 typedef struct tagWMSFT_SegContents
{
8592 } WMSFT_SegContents
;
8594 typedef struct tagWMSFT_TLBFile
{
8596 WMSFT_SegContents typeinfo_seg
;
8597 WMSFT_SegContents impfile_seg
;
8598 WMSFT_SegContents impinfo_seg
;
8599 WMSFT_SegContents ref_seg
;
8600 WMSFT_SegContents lib_seg
;
8601 WMSFT_SegContents guid_seg
;
8602 WMSFT_SegContents res07_seg
;
8603 WMSFT_SegContents name_seg
;
8604 WMSFT_SegContents string_seg
;
8605 WMSFT_SegContents typdesc_seg
;
8606 WMSFT_SegContents arraydesc_seg
;
8607 WMSFT_SegContents custdata_seg
;
8608 WMSFT_SegContents cdguids_seg
;
8610 WMSFT_SegContents aux_seg
;
8613 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8614 WMSFT_TLBFile
*file
)
8620 file
->string_seg
.len
= 0;
8621 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8624 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8626 return E_UNEXPECTED
;
8628 size
+= sizeof(INT16
);
8630 size
= (size
+ 4) & ~0x3;
8634 file
->string_seg
.len
+= size
;
8636 /* temporarily use str->offset to store the length of the aligned,
8637 * converted string */
8641 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8644 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8647 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8648 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8650 heap_free(file
->string_seg
.data
);
8651 return E_UNEXPECTED
;
8654 *((INT16
*)data
) = size
;
8656 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8660 str
->offset
= last_offs
;
8667 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8668 WMSFT_TLBFile
*file
)
8673 MSFT_NameIntro
*last_intro
= NULL
;
8675 file
->header
.nametablecount
= 0;
8676 file
->header
.nametablechars
= 0;
8678 file
->name_seg
.len
= 0;
8679 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8682 size
= strlenW(str
->str
);
8683 file
->header
.nametablechars
+= size
;
8684 file
->header
.nametablecount
++;
8686 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8688 return E_UNEXPECTED
;
8690 size
+= sizeof(MSFT_NameIntro
);
8692 size
= (size
+ 4) & ~0x3;
8696 file
->name_seg
.len
+= size
;
8698 /* temporarily use str->offset to store the length of the aligned,
8699 * converted string */
8703 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
);
8706 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8708 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8710 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8711 data
+ sizeof(MSFT_NameIntro
),
8712 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8714 heap_free(file
->name_seg
.data
);
8715 return E_UNEXPECTED
;
8717 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8719 intro
->hreftype
= -1; /* TODO? */
8720 intro
->next_hash
= -1;
8721 intro
->namelen
= size
& 0xFF;
8722 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8723 intro
->namelen
|= LHashValOfNameSysA(This
->syskind
,
8724 This
->lcid
, data
+ sizeof(MSFT_NameIntro
)) << 16;
8726 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8727 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8729 /* update str->offset to actual value to use in other
8730 * compilation functions that require positions within
8731 * the string table */
8735 str
->offset
= last_offs
;
8740 last_intro
->hreftype
= 0; /* last one is 0? */
8745 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8748 MSFT_GuidEntry
*entry
;
8751 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8752 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8754 entry
= file
->guid_seg
.data
;
8756 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
8757 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
8758 entry
->hreftype
= 0xFFFFFFFF; /* TODO */
8759 entry
->next_hash
= 0xFFFFFFFF; /* TODO? */
8761 guid
->offset
= offs
;
8763 offs
+= sizeof(MSFT_GuidEntry
);
8768 entry
->next_hash
= 0; /* last one has 0? */
8773 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
8776 VARTYPE arg_type
= V_VT(value
);
8779 DWORD ret
= file
->custdata_seg
.len
;
8781 if(arg_type
== VT_INT
)
8783 if(arg_type
== VT_UINT
)
8787 if(V_VT(value
) != arg_type
) {
8788 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
8790 ERR("VariantChangeType failed: %08x\n", hres
);
8795 /* Check if default value can be stored in-place */
8800 if(V_UI4(&v
) > 0x3ffffff)
8813 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
8816 /* have to allocate space in custdata_seg */
8825 /* Construct the data to be allocated */
8828 if(file
->custdata_seg
.data
){
8829 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
8830 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
8831 file
->custdata_seg
.len
+= sizeof(int) * 2;
8833 file
->custdata_seg
.len
= sizeof(int) * 2;
8834 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
8837 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
8838 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
8840 /* TODO: Check if the encoded data is already present in custdata_seg */
8846 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
8849 if(file
->custdata_seg
.data
){
8850 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
8851 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
8852 file
->custdata_seg
.len
+= len
;
8854 file
->custdata_seg
.len
= len
;
8855 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
8858 *((unsigned short *)data
) = V_VT(value
);
8859 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
8860 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
8861 if(V_BSTR(&v
)[i
] <= 0x7f)
8862 data
[i
+6] = V_BSTR(&v
)[i
];
8866 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
8867 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
8870 /* TODO: Check if the encoded data is already present in custdata_seg */
8875 FIXME("Argument type not yet handled\n");
8880 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
8882 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
8884 DWORD offs
= file
->arraydesc_seg
.len
;
8888 /* TODO: we should check for duplicates, but that's harder because each
8889 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8890 * at the library-level) */
8892 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
8893 if(!file
->arraydesc_seg
.data
)
8894 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
8896 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
8897 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
8899 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
8900 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
8901 for(i
= 0; i
< desc
->cDims
; ++i
){
8902 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
8903 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
8909 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
8915 VARTYPE vt
= desc
->vt
& VT_TYPEMASK
, subtype
;
8956 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
8959 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
8961 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
8962 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
8964 *out_size
+= 2 * sizeof(DWORD
);
8965 }else if(vt
== VT_CARRAY
){
8966 encoded
[0] = desc
->vt
| (0x7FFE << 16);
8967 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
8969 }else if(vt
== VT_USERDEFINED
){
8970 encoded
[0] = desc
->vt
| (0x7FFF << 16);
8971 encoded
[1] = desc
->u
.hreftype
;
8972 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
8974 FIXME("Don't know what to do! VT: 0x%x\n", desc
->vt
);
8975 *out_mix
= desc
->vt
;
8976 return 0x80000000 | (desc
->vt
<< 16) | desc
->vt
;
8979 data
= file
->typdesc_seg
.data
;
8980 while(offs
< file
->typdesc_seg
.len
){
8981 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
8983 offs
+= sizeof(encoded
);
8986 file
->typdesc_seg
.len
+= sizeof(encoded
);
8987 if(!file
->typdesc_seg
.data
)
8988 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
8990 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
8992 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
8997 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
8999 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9000 DWORD ret
= cdguids_seg
->len
, offs
;
9001 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9004 if(list_empty(custdata_list
))
9007 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9008 if(!cdguids_seg
->data
){
9009 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9011 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9013 offs
= ret
+ sizeof(MSFT_CDGuid
);
9014 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9015 cdguid
->GuidOffset
= cd
->guid
->offset
;
9016 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9017 cdguid
->next
= offs
;
9018 offs
+= sizeof(MSFT_CDGuid
);
9028 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9029 WMSFT_TLBFile
*file
)
9031 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9032 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9033 MSFT_VarRecord
*varrecord
;
9034 MSFT_FuncRecord
*funcrecord
;
9036 DWORD
*name
, *offsets
, offs
;
9038 for(i
= 0; i
< info
->cFuncs
; ++i
){
9039 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9041 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9043 /* optional fields */
9044 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9045 if(!list_empty(&desc
->custdata_list
))
9046 recorded_size
+= 7 * sizeof(INT
);
9047 else if(desc
->HelpStringContext
!= 0)
9048 recorded_size
+= 6 * sizeof(INT
);
9050 else if(desc
->Entry
)
9051 recorded_size
+= 3 * sizeof(INT
);
9052 else if(desc
->HelpString
)
9053 recorded_size
+= 2 * sizeof(INT
);
9054 else if(desc
->helpcontext
)
9055 recorded_size
+= sizeof(INT
);
9057 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9059 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9060 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9061 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9066 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9069 for(i
= 0; i
< info
->cVars
; ++i
){
9070 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9072 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9074 /* optional fields */
9075 if(desc
->HelpStringContext
!= 0)
9076 recorded_size
+= 5 * sizeof(INT
);
9077 else if(!list_empty(&desc
->custdata_list
))
9078 recorded_size
+= 4 * sizeof(INT
);
9080 else if(desc
->HelpString
)
9081 recorded_size
+= 2 * sizeof(INT
);
9082 else if(desc
->HelpContext
!= 0)
9083 recorded_size
+= sizeof(INT
);
9085 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9088 if(!recorded_size
&& !extra_size
)
9091 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9093 aux_seg
->len
+= recorded_size
+ extra_size
;
9095 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9098 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9100 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9102 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9104 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9107 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9108 for(i
= 0; i
< info
->cFuncs
; ++i
){
9109 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9110 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9112 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9113 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9114 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9115 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9118 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9123 * ^has_param_defaults
9124 * ^oEntry_is_intresource
9126 funcrecord
->FKCCIC
=
9127 desc
->funcdesc
.funckind
|
9128 (desc
->funcdesc
.invkind
<< 3) |
9129 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9130 (desc
->funcdesc
.callconv
<< 8);
9132 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9133 funcrecord
->FKCCIC
|= 0x2000;
9135 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9136 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9137 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9138 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9141 if(paramdefault_size
> 0)
9142 funcrecord
->FKCCIC
|= 0x1000;
9144 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9145 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9147 /* optional fields */
9149 if(!list_empty(&desc
->custdata_list
)){
9150 size
+= 7 * sizeof(INT
);
9151 funcrecord
->HelpContext
= desc
->helpcontext
;
9152 if(desc
->HelpString
)
9153 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9155 funcrecord
->oHelpString
= -1;
9157 funcrecord
->oEntry
= -1;
9158 else if(IS_INTRESOURCE(desc
->Entry
))
9159 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9161 funcrecord
->oEntry
= desc
->Entry
->offset
;
9162 funcrecord
->res9
= -1;
9163 funcrecord
->resA
= -1;
9164 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9165 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9166 }else if(desc
->HelpStringContext
!= 0){
9167 size
+= 6 * sizeof(INT
);
9168 funcrecord
->HelpContext
= desc
->helpcontext
;
9169 if(desc
->HelpString
)
9170 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9172 funcrecord
->oHelpString
= -1;
9174 funcrecord
->oEntry
= -1;
9175 else if(IS_INTRESOURCE(desc
->Entry
))
9176 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9178 funcrecord
->oEntry
= desc
->Entry
->offset
;
9179 funcrecord
->res9
= -1;
9180 funcrecord
->resA
= -1;
9181 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9182 }else if(desc
->Entry
){
9183 size
+= 3 * sizeof(INT
);
9184 funcrecord
->HelpContext
= desc
->helpcontext
;
9185 if(desc
->HelpString
)
9186 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9188 funcrecord
->oHelpString
= -1;
9190 funcrecord
->oEntry
= -1;
9191 else if(IS_INTRESOURCE(desc
->Entry
))
9192 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9194 funcrecord
->oEntry
= desc
->Entry
->offset
;
9195 }else if(desc
->HelpString
){
9196 size
+= 2 * sizeof(INT
);
9197 funcrecord
->HelpContext
= desc
->helpcontext
;
9198 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9199 }else if(desc
->helpcontext
){
9200 size
+= sizeof(INT
);
9201 funcrecord
->HelpContext
= desc
->helpcontext
;
9204 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9205 size
+= paramdefault_size
;
9207 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9208 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9210 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9211 if(desc
->pParamDesc
[j
].Name
)
9212 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9215 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9217 if(paramdefault_size
){
9218 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9219 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9220 else if(paramdefault_size
)
9225 size
+= sizeof(MSFT_ParameterInfo
);
9228 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9234 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9237 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9238 for(i
= 0; i
< info
->cVars
; ++i
){
9239 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9240 DWORD size
= 5 * sizeof(INT
);
9242 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9243 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9244 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9245 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9247 if(desc
->vardesc
.varkind
== VAR_CONST
){
9248 varrecord
->vardescsize
+= sizeof(VARIANT
);
9249 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9251 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9254 if(desc
->HelpStringContext
!= 0){
9255 size
+= 5 * sizeof(INT
);
9256 varrecord
->HelpContext
= desc
->HelpContext
;
9257 if(desc
->HelpString
)
9258 varrecord
->HelpString
= desc
->HelpString
->offset
;
9260 varrecord
->HelpString
= -1;
9261 varrecord
->res9
= -1;
9262 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9263 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9264 }else if(!list_empty(&desc
->custdata_list
)){
9265 size
+= 4 * sizeof(INT
);
9266 varrecord
->HelpContext
= desc
->HelpContext
;
9267 if(desc
->HelpString
)
9268 varrecord
->HelpString
= desc
->HelpString
->offset
;
9270 varrecord
->HelpString
= -1;
9271 varrecord
->res9
= -1;
9272 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9273 }else if(desc
->HelpString
){
9274 size
+= 2 * sizeof(INT
);
9275 varrecord
->HelpContext
= desc
->HelpContext
;
9276 if(desc
->HelpString
)
9277 varrecord
->HelpString
= desc
->HelpString
->offset
;
9279 varrecord
->HelpString
= -1;
9280 }else if(desc
->HelpContext
!= 0){
9281 size
+= sizeof(INT
);
9282 varrecord
->HelpContext
= desc
->HelpContext
;
9285 varrecord
->Info
= size
| (i
<< 16);
9291 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9294 memid
= (MEMBERID
*)varrecord
;
9295 for(i
= 0; i
< info
->cFuncs
; ++i
){
9296 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9297 *memid
= desc
->funcdesc
.memid
;
9300 for(i
= 0; i
< info
->cVars
; ++i
){
9301 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9302 *memid
= desc
->vardesc
.memid
;
9306 name
= (UINT
*)memid
;
9307 for(i
= 0; i
< info
->cFuncs
; ++i
){
9308 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9310 *name
= desc
->Name
->offset
;
9315 for(i
= 0; i
< info
->cVars
; ++i
){
9316 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9318 *name
= desc
->Name
->offset
;
9327 typedef struct tagWMSFT_RefChunk
{
9334 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9336 DWORD offs
= file
->ref_seg
.len
, i
;
9337 WMSFT_RefChunk
*chunk
;
9339 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9340 if(!file
->ref_seg
.data
)
9341 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9343 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9345 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9347 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9348 chunk
->href
= info
->impltypes
[i
].hRef
;
9349 chunk
->res04
= info
->impltypes
[i
].implflags
;
9351 if(i
< info
->cImplTypes
- 1)
9352 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9361 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9365 size
= sizeof(MSFT_TypeInfoBase
);
9368 MSFT_TypeInfoBase
*base
= (void*)data
;
9369 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9370 base
->typekind
= TKIND_DISPATCH
;
9372 base
->typekind
= info
->typekind
;
9373 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9374 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9375 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9380 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9386 base
->posguid
= info
->guid
->offset
;
9389 base
->flags
= info
->wTypeFlags
;
9391 base
->NameOffset
= info
->Name
->offset
;
9393 base
->NameOffset
= -1;
9394 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9396 base
->docstringoffs
= info
->DocString
->offset
;
9398 base
->docstringoffs
= -1;
9399 base
->helpstringcontext
= info
->dwHelpStringContext
;
9400 base
->helpcontext
= info
->dwHelpContext
;
9401 base
->oCustData
= WMSFT_compile_custdata(&info
->custdata_list
, file
);
9402 base
->cImplTypes
= info
->cImplTypes
;
9403 base
->cbSizeVft
= info
->cbSizeVft
;
9404 base
->size
= info
->cbSizeInstance
;
9405 if(info
->typekind
== TKIND_COCLASS
){
9406 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9407 }else if(info
->typekind
== TKIND_ALIAS
){
9408 base
->datatype1
= WMSFT_append_typedesc(&info
->tdescAlias
, file
, NULL
, NULL
);
9409 }else if(info
->typekind
== TKIND_MODULE
){
9411 base
->datatype1
= info
->DllName
->offset
;
9413 base
->datatype1
= -1;
9415 if(info
->cImplTypes
> 0)
9416 base
->datatype1
= info
->impltypes
[0].hRef
;
9418 base
->datatype1
= -1;
9420 base
->datatype2
= index
; /* FIXME: i think there's more here */
9428 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9432 file
->typeinfo_seg
.len
= 0;
9433 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9434 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9435 *junk
= file
->typeinfo_seg
.len
;
9437 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9440 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9441 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9443 file
->aux_seg
.len
= 0;
9444 file
->aux_seg
.data
= NULL
;
9446 file
->typeinfo_seg
.len
= 0;
9447 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9448 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9449 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9450 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9454 typedef struct tagWMSFT_ImpFile
{
9460 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9463 WMSFT_ImpFile
*impfile
;
9465 DWORD last_offs
= 0;
9467 file
->impfile_seg
.len
= 0;
9468 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9472 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9476 path
= implib
->name
;
9477 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9479 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9482 size
+= sizeof(INT16
);
9484 size
= (size
+ 4) & ~0x3;
9488 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9491 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9493 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9494 int strlen
= 0, size
;
9496 impfile
= (WMSFT_ImpFile
*)data
;
9497 impfile
->guid_offs
= implib
->guid
->offset
;
9498 impfile
->lcid
= implib
->lcid
;
9499 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9501 data
+= sizeof(WMSFT_ImpFile
);
9504 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9508 path
= implib
->name
;
9509 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9510 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9512 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9515 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9517 size
= strlen
+ sizeof(INT16
);
9519 size
= (size
+ 4) & ~0x3;
9522 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9525 implib
->offset
= last_offs
;
9526 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9530 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9533 TLBRefType
*ref_type
;
9536 WMSFT_compile_impfile(This
, file
);
9538 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9539 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9541 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9542 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9543 if(ref_type
->index
== TLB_REF_USE_GUID
){
9544 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9545 info
->oGuid
= ref_type
->guid
->offset
;
9547 info
->oGuid
= ref_type
->index
;
9548 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9554 static void WMSFT_compile_lib(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9556 /* TODO: What actually goes here? */
9557 file
->lib_seg
.len
= 0x80;
9558 file
->lib_seg
.data
= heap_alloc(file
->lib_seg
.len
);
9559 memset(file
->lib_seg
.data
, 0xFF, file
->lib_seg
.len
);
9562 /* sometimes, first element is offset to last guid, for some reason */
9564 *(DWORD
*)file
->lib_seg
.data
=
9565 (list_count(&This
->guid_list
) - 1) * sizeof(MSFT_GuidEntry
);
9569 static void WMSFT_compile_res07(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9571 /* TODO: What actually goes here?
9573 * It's something to do with the Name table (and string table?). When you
9574 * add a new name, the offset to that name from within the Name table gets
9575 * stuck somewhere in res07, apparently starting at the end of the segment
9576 * then moving backwards at a rate of 3 bytes per char in the Name. */
9577 file
->res07_seg
.len
= 0x200;
9578 file
->res07_seg
.data
= heap_alloc(file
->res07_seg
.len
);
9579 memset(file
->res07_seg
.data
, 0xFF, file
->res07_seg
.len
);
9582 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9584 if(contents
&& contents
->len
){
9585 segdir
->offset
= *running_offset
;
9586 segdir
->length
= contents
->len
;
9587 *running_offset
+= segdir
->length
;
9589 segdir
->offset
= -1;
9593 /* TODO: do these ever change? */
9595 segdir
->res0c
= 0xf;
9598 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9602 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9605 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9609 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9611 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9612 base
->memoffset
+= file_len
;
9619 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9621 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9622 HeapFree(GetProcessHeap(), 0, file
->lib_seg
.data
);
9623 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9624 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9625 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9626 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9627 HeapFree(GetProcessHeap(), 0, file
->res07_seg
.data
);
9628 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9629 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9630 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9631 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9632 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9633 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9634 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9637 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9639 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9641 DWORD written
, junk_size
, junk_offs
, running_offset
;
9647 TRACE("%p\n", This
);
9649 memset(&file
, 0, sizeof(file
));
9651 file
.header
.magic1
= 0x5446534D;
9652 file
.header
.magic2
= 0x00010002;
9653 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9654 file
.header
.lcid2
= This
->set_lcid
;
9655 file
.header
.varflags
= 0x41; /* TODO?? */
9657 file
.header
.varflags
|= 0x10;
9658 if (This
->HelpStringDll
)
9659 file
.header
.varflags
|= HELPDLLFLAG
;
9660 file
.header
.version
= (This
->ver_major
<< 16) | This
->ver_minor
;
9661 file
.header
.flags
= This
->libflags
;
9662 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9663 file
.header
.helpcontext
= This
->dwHelpContext
;
9664 file
.header
.res44
= 0x20;
9665 file
.header
.res48
= 0x80;
9666 file
.header
.dispatchpos
= This
->dispatch_href
;
9668 /* do name and string compilation to get offsets for other compilations */
9669 hres
= WMSFT_compile_names(This
, &file
);
9671 WMSFT_free_file(&file
);
9675 hres
= WMSFT_compile_strings(This
, &file
);
9677 WMSFT_free_file(&file
);
9681 hres
= WMSFT_compile_guids(This
, &file
);
9683 WMSFT_free_file(&file
);
9688 file
.header
.helpfile
= This
->HelpFile
->offset
;
9690 file
.header
.helpfile
= -1;
9693 file
.header
.helpstring
= This
->DocString
->offset
;
9695 file
.header
.helpstring
= -1;
9697 /* do some more segment compilation */
9698 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9699 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9702 file
.header
.NameOffset
= This
->Name
->offset
;
9704 file
.header
.NameOffset
= -1;
9706 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9709 file
.header
.posguid
= This
->guid
->offset
;
9711 file
.header
.posguid
= -1;
9713 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9714 if(file
.header
.varflags
& HELPDLLFLAG
)
9715 junk_size
+= sizeof(DWORD
);
9717 junk
= heap_alloc_zero(junk_size
);
9718 if(file
.header
.varflags
& HELPDLLFLAG
){
9719 *junk
= This
->HelpStringDll
->offset
;
9728 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9729 WMSFT_compile_impinfo(This
, &file
);
9730 WMSFT_compile_lib(This
, &file
);
9731 WMSFT_compile_res07(This
, &file
);
9735 TRACE("header at: 0x%x\n", running_offset
);
9736 running_offset
+= sizeof(file
.header
);
9738 TRACE("junk at: 0x%x\n", running_offset
);
9739 running_offset
+= junk_size
;
9741 TRACE("segdir at: 0x%x\n", running_offset
);
9742 running_offset
+= sizeof(file
.segdir
);
9744 TRACE("typeinfo at: 0x%x\n", running_offset
);
9745 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9747 TRACE("libtab at: 0x%x\n", running_offset
);
9748 tmp_fill_segdir_seg(&file
.segdir
.pLibtab
, &file
.lib_seg
, &running_offset
);
9750 TRACE("guidtab at: 0x%x\n", running_offset
);
9751 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9753 TRACE("reftab at: 0x%x\n", running_offset
);
9754 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9756 TRACE("impinfo at: 0x%x\n", running_offset
);
9757 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9759 TRACE("impfiles at: 0x%x\n", running_offset
);
9760 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9762 TRACE("res07 at: 0x%x\n", running_offset
);
9763 tmp_fill_segdir_seg(&file
.segdir
.res07
, &file
.res07_seg
, &running_offset
);
9765 TRACE("nametab at: 0x%x\n", running_offset
);
9766 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9768 TRACE("stringtab at: 0x%x\n", running_offset
);
9769 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9771 TRACE("typdesc at: 0x%x\n", running_offset
);
9772 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
9774 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
9775 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
9777 TRACE("custdata at: 0x%x\n", running_offset
);
9778 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
9780 TRACE("cdguids at: 0x%x\n", running_offset
);
9781 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
9783 TRACE("res0e at: 0x%x\n", running_offset
);
9784 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
9786 TRACE("res0f at: 0x%x\n", running_offset
);
9787 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
9789 TRACE("aux_seg at: 0x%x\n", running_offset
);
9791 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
9793 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
9794 FILE_ATTRIBUTE_NORMAL
, 0);
9795 if (outfile
== INVALID_HANDLE_VALUE
){
9796 WMSFT_free_file(&file
);
9797 return TYPE_E_IOERROR
;
9800 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
9802 WMSFT_free_file(&file
);
9803 CloseHandle(outfile
);
9804 return TYPE_E_IOERROR
;
9807 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
9809 WMSFT_free_file(&file
);
9810 CloseHandle(outfile
);
9811 return TYPE_E_IOERROR
;
9814 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
9816 WMSFT_free_file(&file
);
9817 CloseHandle(outfile
);
9818 return TYPE_E_IOERROR
;
9821 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
9822 WMSFT_write_segment(outfile
, &file
.lib_seg
);
9823 WMSFT_write_segment(outfile
, &file
.guid_seg
);
9824 WMSFT_write_segment(outfile
, &file
.ref_seg
);
9825 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
9826 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
9827 WMSFT_write_segment(outfile
, &file
.res07_seg
);
9828 WMSFT_write_segment(outfile
, &file
.name_seg
);
9829 WMSFT_write_segment(outfile
, &file
.string_seg
);
9830 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
9831 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
9832 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
9833 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
9834 WMSFT_write_segment(outfile
, &file
.aux_seg
);
9836 WMSFT_free_file(&file
);
9838 CloseHandle(outfile
);
9843 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
9846 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9847 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
9851 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
9852 REFGUID guid
, VARIANT
*varVal
)
9854 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9855 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
9859 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
9860 ULONG helpStringContext
)
9862 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9863 FIXME("%p %u - stub\n", This
, helpStringContext
);
9867 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
9870 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9871 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
9874 return E_INVALIDARG
;
9876 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
9881 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
9882 ICreateTypeLib2_fnQueryInterface
,
9883 ICreateTypeLib2_fnAddRef
,
9884 ICreateTypeLib2_fnRelease
,
9885 ICreateTypeLib2_fnCreateTypeInfo
,
9886 ICreateTypeLib2_fnSetName
,
9887 ICreateTypeLib2_fnSetVersion
,
9888 ICreateTypeLib2_fnSetGuid
,
9889 ICreateTypeLib2_fnSetDocString
,
9890 ICreateTypeLib2_fnSetHelpFileName
,
9891 ICreateTypeLib2_fnSetHelpContext
,
9892 ICreateTypeLib2_fnSetLcid
,
9893 ICreateTypeLib2_fnSetLibFlags
,
9894 ICreateTypeLib2_fnSaveAllChanges
,
9895 ICreateTypeLib2_fnDeleteTypeInfo
,
9896 ICreateTypeLib2_fnSetCustData
,
9897 ICreateTypeLib2_fnSetHelpStringContext
,
9898 ICreateTypeLib2_fnSetHelpStringDll
9901 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
9902 REFIID riid
, void **object
)
9904 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9906 return ITypeInfo2_QueryInterface((ITypeInfo2
*)This
, riid
, object
);
9909 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
9911 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9913 return ITypeInfo2_AddRef((ITypeInfo2
*)This
);
9916 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
9918 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9920 return ITypeInfo2_Release((ITypeInfo2
*)This
);
9923 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
9926 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9928 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9930 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
);
9935 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
9938 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9942 TRACE("%p %x\n", This
, typeFlags
);
9944 if (typeFlags
& TYPEFLAG_FDUAL
) {
9945 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9947 ITypeInfo
*dispatch
;
9951 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
9955 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
9956 ITypeLib_Release(stdole
);
9960 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
9961 ITypeInfo_Release(dispatch
);
9966 old_flags
= This
->wTypeFlags
;
9967 This
->wTypeFlags
= typeFlags
;
9969 hres
= ICreateTypeInfo2_LayOut(iface
);
9971 This
->wTypeFlags
= old_flags
;
9978 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
9981 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9983 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9986 return E_INVALIDARG
;
9988 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
9993 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
9996 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9998 TRACE("%p %d\n", This
, helpContext
);
10000 This
->dwHelpContext
= helpContext
;
10005 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10006 WORD majorVerNum
, WORD minorVerNum
)
10008 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10010 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10012 This
->wMajorVerNum
= majorVerNum
;
10013 This
->wMinorVerNum
= minorVerNum
;
10018 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10019 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10021 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10023 ITypeLib
*container
;
10024 TLBRefType
*ref_type
;
10026 TYPEATTR
*typeattr
;
10030 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10032 if (!typeInfo
|| !refType
)
10033 return E_INVALIDARG
;
10035 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10039 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10040 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10042 ITypeLib_Release(container
);
10044 *refType
= target
->hreftype
;
10049 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10050 if (FAILED(hres
)) {
10051 ITypeLib_Release(container
);
10055 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10056 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10057 implib
->lcid
== libattr
->lcid
&&
10058 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10059 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10063 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10064 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10066 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10067 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10068 implib
->name
= SysAllocString(our_container
->path
);
10070 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10071 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10073 implib
->name
= NULL
;
10074 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10078 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
);
10079 implib
->lcid
= libattr
->lcid
;
10080 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10081 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10083 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10086 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10087 ITypeLib_Release(container
);
10089 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10094 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10095 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10096 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10097 ref_type
->tkind
== typeattr
->typekind
)
10102 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10103 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10105 ref_type
->tkind
= typeattr
->typekind
;
10106 ref_type
->pImpTLInfo
= implib
;
10107 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10109 ref_type
->index
= TLB_REF_USE_GUID
;
10111 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
);
10113 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10116 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10118 *refType
= ref_type
->reference
| 0x1;
10120 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10121 This
->pTypeLib
->dispatch_href
= *refType
;
10126 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10127 UINT index
, FUNCDESC
*funcDesc
)
10129 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10130 TLBFuncDesc tmp_func_desc
, *func_desc
;
10135 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10137 if (!funcDesc
|| funcDesc
->oVft
& 3)
10138 return E_INVALIDARG
;
10140 switch (This
->typekind
) {
10142 if (funcDesc
->funckind
!= FUNC_STATIC
)
10143 return TYPE_E_BADMODULEKIND
;
10145 case TKIND_DISPATCH
:
10146 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10147 return TYPE_E_BADMODULEKIND
;
10150 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10151 return TYPE_E_BADMODULEKIND
;
10154 if (index
> This
->cFuncs
)
10155 return TYPE_E_ELEMENTNOTFOUND
;
10157 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10158 !funcDesc
->cParams
)
10159 return TYPE_E_INCONSISTENTPROPFUNCS
;
10161 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10162 TLBFuncDesc_Constructor(&tmp_func_desc
);
10164 tmp_func_desc
.funcdesc
= *funcDesc
;
10166 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10167 tmp_func_desc
.funcdesc
.oVft
|= 1;
10169 if (funcDesc
->cScodes
) {
10170 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10171 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10173 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10175 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10176 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10177 buf_size
+= sizeof(ELEMDESC
);
10178 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10180 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10181 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10183 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10184 if (FAILED(hres
)) {
10185 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10186 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10190 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10191 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10192 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10193 if (FAILED(hres
)) {
10194 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10195 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10198 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10199 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10200 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10201 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10202 if (FAILED(hres
)) {
10203 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10204 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10210 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10212 if (This
->funcdescs
) {
10213 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10214 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10216 if (index
< This
->cFuncs
) {
10217 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10218 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10219 func_desc
= This
->funcdescs
+ index
;
10221 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10223 /* move custdata lists to the new memory location */
10224 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10226 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10227 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10228 list_init(&fd
->custdata_list
);
10230 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10231 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10236 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10238 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10239 list_init(&func_desc
->custdata_list
);
10243 This
->needs_layout
= TRUE
;
10248 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10249 UINT index
, HREFTYPE refType
)
10251 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10252 TLBImplType
*impl_type
;
10255 TRACE("%p %u %d\n", This
, index
, refType
);
10257 switch(This
->typekind
){
10258 case TKIND_COCLASS
: {
10260 FIXME("Unhandled index: -1\n");
10264 if(index
!= This
->cImplTypes
)
10265 return TYPE_E_ELEMENTNOTFOUND
;
10269 case TKIND_INTERFACE
:
10270 case TKIND_DISPATCH
:
10271 if (index
!= 0 || This
->cImplTypes
)
10272 return TYPE_E_ELEMENTNOTFOUND
;
10275 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10279 if (This
->impltypes
){
10282 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10283 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10285 if (index
< This
->cImplTypes
) {
10286 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10287 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10288 impl_type
= This
->impltypes
+ index
;
10290 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10292 /* move custdata lists to the new memory location */
10293 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10295 TLBImplType
*it
= &This
->impltypes
[i
];
10296 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10297 list_init(&it
->custdata_list
);
10299 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10300 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10305 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10307 memset(impl_type
, 0, sizeof(TLBImplType
));
10308 TLBImplType_Constructor(impl_type
);
10309 impl_type
->hRef
= refType
;
10311 ++This
->cImplTypes
;
10313 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10314 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10316 hres
= ICreateTypeInfo2_LayOut(iface
);
10323 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10324 UINT index
, INT implTypeFlags
)
10326 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10327 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10329 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10331 if (This
->typekind
!= TKIND_COCLASS
)
10332 return TYPE_E_BADMODULEKIND
;
10334 if (index
>= This
->cImplTypes
)
10335 return TYPE_E_ELEMENTNOTFOUND
;
10337 impl_type
->implflags
= implTypeFlags
;
10342 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10345 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10347 TRACE("%p %d\n", This
, alignment
);
10349 This
->cbAlignment
= alignment
;
10354 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10357 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10359 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10362 return E_INVALIDARG
;
10364 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10366 This
->lpstrSchema
= This
->Schema
->str
;
10371 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10372 UINT index
, VARDESC
*varDesc
)
10374 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10375 TLBVarDesc
*var_desc
;
10377 TRACE("%p %u %p\n", This
, index
, varDesc
);
10379 if (This
->vardescs
){
10382 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10383 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10385 if (index
< This
->cVars
) {
10386 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10387 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10388 var_desc
= This
->vardescs
+ index
;
10390 var_desc
= This
->vardescs
+ This
->cVars
;
10392 /* move custdata lists to the new memory location */
10393 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10395 TLBVarDesc
*var
= &This
->vardescs
[i
];
10396 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10397 list_init(&var
->custdata_list
);
10399 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10400 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10405 var_desc
= This
->vardescs
= heap_alloc(sizeof(TLBVarDesc
));
10407 memset(var_desc
, 0, sizeof(TLBVarDesc
));
10408 TLBVarDesc_Constructor(var_desc
);
10409 var_desc
->vardesc
= *varDesc
;
10413 This
->needs_layout
= TRUE
;
10418 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10419 UINT index
, LPOLESTR
*names
, UINT numNames
)
10421 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10422 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10425 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10428 return E_INVALIDARG
;
10430 if (index
>= This
->cFuncs
|| numNames
== 0)
10431 return TYPE_E_ELEMENTNOTFOUND
;
10433 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10434 if(numNames
> func_desc
->funcdesc
.cParams
)
10435 return TYPE_E_ELEMENTNOTFOUND
;
10437 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10438 return TYPE_E_ELEMENTNOTFOUND
;
10440 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10441 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10442 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10443 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10444 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10445 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10447 return TYPE_E_AMBIGUOUSNAME
;
10451 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10453 for (i
= 1; i
< numNames
; ++i
) {
10454 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10455 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10461 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10462 UINT index
, LPOLESTR name
)
10464 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10465 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(name
));
10469 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10470 TYPEDESC
*tdescAlias
)
10472 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10473 FIXME("%p %p - stub\n", This
, tdescAlias
);
10477 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10478 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10480 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10481 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10485 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10486 UINT index
, LPOLESTR docString
)
10488 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10489 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
10493 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10494 UINT index
, LPOLESTR docString
)
10496 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10497 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10499 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10502 return E_INVALIDARG
;
10504 if(index
>= This
->cVars
)
10505 return TYPE_E_ELEMENTNOTFOUND
;
10507 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10512 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10513 UINT index
, DWORD helpContext
)
10515 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10516 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10518 TRACE("%p %u %d\n", This
, index
, helpContext
);
10520 if(index
>= This
->cFuncs
)
10521 return TYPE_E_ELEMENTNOTFOUND
;
10523 func_desc
->helpcontext
= helpContext
;
10528 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10529 UINT index
, DWORD helpContext
)
10531 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10532 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10534 TRACE("%p %u %d\n", This
, index
, helpContext
);
10536 if(index
>= This
->cVars
)
10537 return TYPE_E_ELEMENTNOTFOUND
;
10539 var_desc
->HelpContext
= helpContext
;
10544 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10545 UINT index
, BSTR bstrMops
)
10547 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10548 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10552 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10555 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10557 TRACE("%p %p\n", This
, idlDesc
);
10560 return E_INVALIDARG
;
10562 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10563 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10568 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10570 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10572 TLBFuncDesc
*func_desc
;
10573 UINT user_vft
= 0, i
, depth
= 0;
10574 HRESULT hres
= S_OK
;
10576 TRACE("%p\n", This
);
10578 This
->needs_layout
= FALSE
;
10580 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10584 if (This
->typekind
== TKIND_INTERFACE
) {
10589 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10591 if (SUCCEEDED(hres
)) {
10592 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10594 if (SUCCEEDED(hres
)) {
10595 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10596 if (FAILED(hres
)) {
10597 ITypeInfo_Release(inh
);
10598 ITypeInfo_Release(tinfo
);
10601 This
->cbSizeVft
= attr
->cbSizeVft
* 4 / sizeof(void*);
10602 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10606 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10607 if(SUCCEEDED(hres
)){
10609 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10610 if(SUCCEEDED(hres
)){
10611 ITypeInfo_Release(inh
);
10615 }while(SUCCEEDED(hres
));
10618 ITypeInfo_Release(inh
);
10619 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10620 This
->cbSizeVft
= 0;
10623 ITypeInfo_Release(tinfo
);
10626 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10627 This
->cbSizeVft
= 0;
10630 ITypeInfo_Release(tinfo
);
10633 } else if (This
->typekind
== TKIND_DISPATCH
)
10634 This
->cbSizeVft
= 7 * sizeof(void*);
10636 This
->cbSizeVft
= 0;
10638 func_desc
= This
->funcdescs
;
10640 while (i
< This
->cFuncs
) {
10641 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10642 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10644 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10645 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10647 This
->cbSizeVft
+= sizeof(void*);
10649 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10652 BOOL reset
= FALSE
;
10654 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10656 iter
= This
->funcdescs
;
10657 while (j
< This
->cFuncs
) {
10658 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10660 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10663 ++func_desc
->funcdesc
.memid
;
10664 iter
= This
->funcdescs
;
10677 if (user_vft
> This
->cbSizeVft
)
10678 This
->cbSizeVft
= user_vft
+ sizeof(void*);
10680 ITypeInfo_Release(tinfo
);
10684 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10687 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10688 FIXME("%p %u - stub\n", This
, index
);
10692 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
10693 MEMBERID memid
, INVOKEKIND invKind
)
10695 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10696 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
10700 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
10703 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10704 FIXME("%p %u - stub\n", This
, index
);
10708 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
10711 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10712 FIXME("%p %x - stub\n", This
, memid
);
10716 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
10719 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10720 FIXME("%p %u - stub\n", This
, index
);
10724 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
10725 REFGUID guid
, VARIANT
*varVal
)
10729 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10731 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10733 if (!guid
|| !varVal
)
10734 return E_INVALIDARG
;
10736 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
);
10738 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10741 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
10742 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10744 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10745 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10749 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
10750 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
10752 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10753 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
10757 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
10758 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10760 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10761 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10765 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
10766 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10768 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10769 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10773 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
10774 ULONG helpStringContext
)
10776 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10778 TRACE("%p %u\n", This
, helpStringContext
);
10780 This
->dwHelpStringContext
= helpStringContext
;
10785 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
10786 UINT index
, ULONG helpStringContext
)
10788 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10789 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
10793 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
10794 UINT index
, ULONG helpStringContext
)
10796 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10797 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
10801 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
10803 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10804 FIXME("%p - stub\n", This
);
10808 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
10811 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10813 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
10816 return E_INVALIDARG
;
10818 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10823 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
10824 ICreateTypeInfo2_fnQueryInterface
,
10825 ICreateTypeInfo2_fnAddRef
,
10826 ICreateTypeInfo2_fnRelease
,
10827 ICreateTypeInfo2_fnSetGuid
,
10828 ICreateTypeInfo2_fnSetTypeFlags
,
10829 ICreateTypeInfo2_fnSetDocString
,
10830 ICreateTypeInfo2_fnSetHelpContext
,
10831 ICreateTypeInfo2_fnSetVersion
,
10832 ICreateTypeInfo2_fnAddRefTypeInfo
,
10833 ICreateTypeInfo2_fnAddFuncDesc
,
10834 ICreateTypeInfo2_fnAddImplType
,
10835 ICreateTypeInfo2_fnSetImplTypeFlags
,
10836 ICreateTypeInfo2_fnSetAlignment
,
10837 ICreateTypeInfo2_fnSetSchema
,
10838 ICreateTypeInfo2_fnAddVarDesc
,
10839 ICreateTypeInfo2_fnSetFuncAndParamNames
,
10840 ICreateTypeInfo2_fnSetVarName
,
10841 ICreateTypeInfo2_fnSetTypeDescAlias
,
10842 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
10843 ICreateTypeInfo2_fnSetFuncDocString
,
10844 ICreateTypeInfo2_fnSetVarDocString
,
10845 ICreateTypeInfo2_fnSetFuncHelpContext
,
10846 ICreateTypeInfo2_fnSetVarHelpContext
,
10847 ICreateTypeInfo2_fnSetMops
,
10848 ICreateTypeInfo2_fnSetTypeIdldesc
,
10849 ICreateTypeInfo2_fnLayOut
,
10850 ICreateTypeInfo2_fnDeleteFuncDesc
,
10851 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
10852 ICreateTypeInfo2_fnDeleteVarDesc
,
10853 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
10854 ICreateTypeInfo2_fnDeleteImplType
,
10855 ICreateTypeInfo2_fnSetCustData
,
10856 ICreateTypeInfo2_fnSetFuncCustData
,
10857 ICreateTypeInfo2_fnSetParamCustData
,
10858 ICreateTypeInfo2_fnSetVarCustData
,
10859 ICreateTypeInfo2_fnSetImplTypeCustData
,
10860 ICreateTypeInfo2_fnSetHelpStringContext
,
10861 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
10862 ICreateTypeInfo2_fnSetVarHelpStringContext
,
10863 ICreateTypeInfo2_fnInvalidate
,
10864 ICreateTypeInfo2_fnSetName