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
72 #include "wine/unicode.h"
75 #include "wine/debug.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
94 WORD type_id
; /* Type identifier */
95 WORD count
; /* Number of resources of this type */
96 DWORD resloader
; /* SetResourceHandler() */
102 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
103 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
104 static void TLB_FreeVarDesc(VARDESC
*);
106 /****************************************************************************
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD
FromLEWord(WORD p_iVal
)
115 return (((p_iVal
& 0x00FF) << 8) |
116 ((p_iVal
& 0xFF00) >> 8));
120 static DWORD
FromLEDWord(DWORD p_iVal
)
122 return (((p_iVal
& 0x000000FF) << 24) |
123 ((p_iVal
& 0x0000FF00) << 8) |
124 ((p_iVal
& 0x00FF0000) >> 8) |
125 ((p_iVal
& 0xFF000000) >> 24));
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val
, int p_iSize
)
145 p_iSize
/= sizeof(WORD
);
148 *Val
= FromLEWord(*Val
);
155 static void FromLEDWords(void *p_Val
, int p_iSize
)
159 p_iSize
/= sizeof(DWORD
);
162 *Val
= FromLEDWord(*Val
);
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
177 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
181 INT best_maj
= -1, best_min
= -1;
184 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
185 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
190 len
= sizeof(key_name
);
192 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
196 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
200 if (*wMaj
== 0xffff && *wMin
== 0xffff)
202 if (v_maj
> best_maj
) best_maj
= v_maj
;
203 if (v_min
> best_min
) best_min
= v_min
;
205 else if (*wMaj
== v_maj
)
212 break; /* exact match */
214 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
217 len
= sizeof(key_name
);
221 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
223 if (*wMaj
== 0xffff && *wMin
== 0xffff)
225 if (best_maj
>= 0 && best_min
>= 0)
233 if (*wMaj
== best_maj
&& best_min
>= 0)
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
245 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
249 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
250 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
258 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
261 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
269 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
270 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
274 sprintfW( buffer
, LcidFormatW
, lcid
);
277 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
278 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
279 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
281 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
287 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
290 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
291 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
292 SYSKIND syskind
, LCID lcid
, LPBSTR path
)
294 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
298 WCHAR Path
[MAX_PATH
];
301 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
303 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
304 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
306 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
307 if (res
== ERROR_FILE_NOT_FOUND
)
309 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
310 return TYPE_E_LIBNOTREGISTERED
;
312 else if (res
!= ERROR_SUCCESS
)
314 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
315 return TYPE_E_REGISTRYACCESS
;
320 LONG dwPathLen
= sizeof(Path
);
322 get_lcid_subkey( myLCID
, syskind
, buffer
);
324 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
328 else if (myLCID
== lcid
)
330 /* try with sub-langid */
331 myLCID
= SUBLANGID(lcid
);
333 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
335 /* try with system langid */
345 *path
= SysAllocString( Path
);
350 TRACE_(typelib
)("-- 0x%08x\n", hr
);
354 /****************************************************************************
355 * QueryPathOfRegTypeLib [OLEAUT32.164]
357 * Gets the path to a registered type library.
360 * guid [I] referenced guid
361 * wMaj [I] major version
362 * wMin [I] minor version
364 * path [O] path of typelib
368 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
369 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
372 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
375 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
);
379 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
);
382 /******************************************************************************
383 * CreateTypeLib [OLEAUT32.160] creates a typelib
389 HRESULT WINAPI
CreateTypeLib(
390 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
392 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
396 /******************************************************************************
397 * LoadTypeLib [OLEAUT32.161]
399 * Loads a type library
402 * szFile [I] Name of file to load from.
403 * pptLib [O] Pointer that receives ITypeLib object on success.
410 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
412 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
414 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
415 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
418 /******************************************************************************
419 * LoadTypeLibEx [OLEAUT32.183]
421 * Loads and optionally registers a type library
427 HRESULT WINAPI
LoadTypeLibEx(
428 LPCOLESTR szFile
, /* [in] Name of file to load from */
429 REGKIND regkind
, /* [in] Specify kind of registration */
430 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
432 WCHAR szPath
[MAX_PATH
+1];
435 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
439 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
444 case REGKIND_DEFAULT
:
445 /* don't register typelibs supplied with full path. Experimentation confirms the following */
446 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
447 (szFile
[0] && (szFile
[1] == ':'))) break;
448 /* else fall-through */
450 case REGKIND_REGISTER
:
451 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
453 ITypeLib_Release(*pptLib
);
461 TRACE(" returns %08x\n",res
);
465 /******************************************************************************
466 * LoadRegTypeLib [OLEAUT32.162]
468 * Loads a registered type library.
471 * rguid [I] GUID of the registered type library.
472 * wVerMajor [I] major version.
473 * wVerMinor [I] minor version.
474 * lcid [I] locale ID.
475 * ppTLib [O] pointer that receives an ITypeLib object on success.
479 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
482 HRESULT WINAPI
LoadRegTypeLib(
494 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
498 res
= LoadTypeLib(bstr
, ppTLib
);
502 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
508 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
509 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
510 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
511 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
512 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
513 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
515 /******************************************************************************
516 * RegisterTypeLib [OLEAUT32.163]
517 * Adds information about a type library to the System Registry
519 * Docs: ITypeLib FAR * ptlib
520 * Docs: OLECHAR FAR* szFullPath
521 * Docs: OLECHAR FAR* szHelpDir
527 HRESULT WINAPI
RegisterTypeLib(
528 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
529 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
530 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
533 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
534 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
535 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
545 if (ptlib
== NULL
|| szFullPath
== NULL
)
548 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
552 if (attr
->syskind
== SYS_WIN64
) 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
{
965 typedef struct tagTLBCustData
972 /* data structure for import typelibs */
973 typedef struct tagTLBImpLib
975 int offset
; /* offset in the file (MSFT)
976 offset in nametable (SLTG)
977 just used to identify library while reading
979 TLBGuid
*guid
; /* libid */
980 BSTR name
; /* name */
982 LCID lcid
; /* lcid of imported typelib */
984 WORD wVersionMajor
; /* major version number */
985 WORD wVersionMinor
; /* minor version number */
987 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
988 NULL if not yet loaded */
992 typedef struct tagTLBString
{
998 /* internal ITypeLib data */
999 typedef struct tagITypeLibImpl
1001 ITypeLib2 ITypeLib2_iface
;
1002 ITypeComp ITypeComp_iface
;
1003 ICreateTypeLib2 ICreateTypeLib2_iface
;
1014 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1015 * exported to the application as a UNICODE string.
1017 struct list string_list
;
1018 struct list name_list
;
1019 struct list guid_list
;
1021 const TLBString
*Name
;
1022 const TLBString
*DocString
;
1023 const TLBString
*HelpFile
;
1024 const TLBString
*HelpStringDll
;
1025 DWORD dwHelpContext
;
1026 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1027 struct tagITypeInfoImpl
**typeinfos
;
1028 struct list custdata_list
;
1029 struct list implib_list
;
1030 int ctTypeDesc
; /* number of items in type desc array */
1031 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1032 library. Only used while reading MSFT
1034 struct list ref_list
; /* list of ref types in this typelib */
1035 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1038 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1044 static const ITypeLib2Vtbl tlbvt
;
1045 static const ITypeCompVtbl tlbtcvt
;
1046 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1048 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1050 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1053 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1055 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1058 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1060 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1063 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1065 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1068 /* ITypeLib methods */
1069 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1070 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1072 /*======================= ITypeInfo implementation =======================*/
1074 /* data for referenced types */
1075 typedef struct tagTLBRefType
1077 INT index
; /* Type index for internal ref or for external ref
1078 it the format is SLTG. -2 indicates to
1082 TLBGuid
*guid
; /* guid of the referenced type */
1083 /* if index == TLB_REF_USE_GUID */
1085 HREFTYPE reference
; /* The href of this ref */
1086 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1087 TLB_REF_INTERNAL for internal refs
1088 TLB_REF_NOT_FOUND for broken refs */
1093 #define TLB_REF_USE_GUID -2
1095 #define TLB_REF_INTERNAL (void*)-2
1096 #define TLB_REF_NOT_FOUND (void*)-1
1098 /* internal Parameter data */
1099 typedef struct tagTLBParDesc
1101 const TLBString
*Name
;
1102 struct list custdata_list
;
1105 /* internal Function data */
1106 typedef struct tagTLBFuncDesc
1108 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1109 const TLBString
*Name
; /* the name of this function */
1110 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1112 int HelpStringContext
;
1113 const TLBString
*HelpString
;
1114 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1115 struct list custdata_list
;
1118 /* internal Variable data */
1119 typedef struct tagTLBVarDesc
1121 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1122 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1123 const TLBString
*Name
; /* the name of this variable */
1125 int HelpStringContext
;
1126 const TLBString
*HelpString
;
1127 struct list custdata_list
;
1130 /* internal implemented interface data */
1131 typedef struct tagTLBImplType
1133 HREFTYPE hRef
; /* hRef of interface */
1134 int implflags
; /* IMPLFLAG_*s */
1135 struct list custdata_list
;
1138 /* internal TypeInfo data */
1139 typedef struct tagITypeInfoImpl
1141 ITypeInfo2 ITypeInfo2_iface
;
1142 ITypeComp ITypeComp_iface
;
1143 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1145 BOOL not_attached_to_typelib
;
1150 MEMBERID memidConstructor
;
1151 MEMBERID memidDestructor
;
1152 LPOLESTR lpstrSchema
;
1153 ULONG cbSizeInstance
;
1163 TYPEDESC
*tdescAlias
;
1164 IDLDESC idldescType
;
1166 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1167 int index
; /* index in this typelib; */
1168 HREFTYPE hreftype
; /* hreftype for app object binding */
1169 /* type libs seem to store the doc strings in ascii
1170 * so why should we do it in unicode?
1172 const TLBString
*Name
;
1173 const TLBString
*DocString
;
1174 const TLBString
*DllName
;
1175 const TLBString
*Schema
;
1176 DWORD dwHelpContext
;
1177 DWORD dwHelpStringContext
;
1180 TLBFuncDesc
*funcdescs
;
1183 TLBVarDesc
*vardescs
;
1185 /* Implemented Interfaces */
1186 TLBImplType
*impltypes
;
1188 struct list
*pcustdata_list
;
1189 struct list custdata_list
;
1192 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1194 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1197 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1199 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1202 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1204 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1207 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1209 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1212 static const ITypeInfo2Vtbl tinfvt
;
1213 static const ITypeCompVtbl tcompvt
;
1214 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1216 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1217 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1219 typedef struct tagTLBContext
1221 unsigned int oStart
; /* start of TLB in file */
1222 unsigned int pos
; /* current pos */
1223 unsigned int length
; /* total length */
1224 void *mapping
; /* memory mapping */
1225 MSFT_SegDir
* pTblDir
;
1226 ITypeLibImpl
* pLibInfo
;
1230 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1232 return str
!= NULL
? str
->str
: NULL
;
1235 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1239 return memcmp(left
, str
->str
, len
);
1242 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1244 return guid
!= NULL
? &guid
->guid
: NULL
;
1247 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1249 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1252 static int get_ptr_size(SYSKIND syskind
)
1262 WARN("Unhandled syskind: 0x%x\n", syskind
);
1269 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1270 if (pTD
->vt
& VT_RESERVED
)
1271 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1272 if (pTD
->vt
& VT_BYREF
)
1273 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1274 if (pTD
->vt
& VT_ARRAY
)
1275 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1276 if (pTD
->vt
& VT_VECTOR
)
1277 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1278 switch(pTD
->vt
& VT_TYPEMASK
) {
1279 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1280 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1281 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1282 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1283 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1284 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1285 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1286 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1287 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1288 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1289 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1290 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1291 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1292 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1293 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1294 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1295 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1296 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1297 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1298 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1299 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1300 pTD
->u
.hreftype
); break;
1301 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1302 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1303 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1304 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1306 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1307 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1309 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1310 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1311 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1314 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1318 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1320 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1321 dump_TypeDesc(&edesc
->tdesc
,buf
);
1322 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1323 MESSAGE("\t\tu.paramdesc.wParamFlags");
1324 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1325 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1326 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1327 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1328 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1329 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1330 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1331 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1332 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1334 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1336 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1337 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1338 MESSAGE("Param %d:\n",i
);
1339 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1341 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1342 switch (funcdesc
->funckind
) {
1343 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1344 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1345 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1346 case FUNC_STATIC
: MESSAGE("static");break;
1347 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1348 default: MESSAGE("unknown");break;
1350 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1351 switch (funcdesc
->invkind
) {
1352 case INVOKE_FUNC
: MESSAGE("func");break;
1353 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1354 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1355 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1357 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1358 switch (funcdesc
->callconv
) {
1359 case CC_CDECL
: MESSAGE("cdecl");break;
1360 case CC_PASCAL
: MESSAGE("pascal");break;
1361 case CC_STDCALL
: MESSAGE("stdcall");break;
1362 case CC_SYSCALL
: MESSAGE("syscall");break;
1365 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1366 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1367 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1369 MESSAGE("\telemdescFunc (return value type):\n");
1370 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1373 static const char * const typekind_desc
[] =
1386 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1389 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1390 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1391 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1394 dump_FUNCDESC(&(pfd
->funcdesc
));
1396 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1397 if(pfd
->Entry
== NULL
)
1398 MESSAGE("\tentry: (null)\n");
1399 else if(pfd
->Entry
== (void*)-1)
1400 MESSAGE("\tentry: invalid\n");
1401 else if(IS_INTRESOURCE(pfd
->Entry
))
1402 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1404 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1406 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1410 dump_TLBFuncDescOne(pfd
);
1415 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1419 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1425 static void dump_TLBImpLib(const TLBImpLib
*import
)
1427 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1428 debugstr_w(import
->name
));
1429 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1430 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1433 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1437 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1439 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1440 if(ref
->index
== -1)
1441 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1443 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1445 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1447 TRACE_(typelib
)("in lib\n");
1448 dump_TLBImpLib(ref
->pImpTLInfo
);
1453 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1458 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1459 impl
->hRef
, impl
->implflags
);
1465 static void dump_Variant(const VARIANT
* pvar
)
1469 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1473 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1474 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1476 TRACE(",%p", V_BYREF(pvar
));
1478 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1480 TRACE(",%p", V_ARRAY(pvar
));
1482 else switch (V_TYPE(pvar
))
1484 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1485 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1486 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1487 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1489 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1491 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1492 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1493 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1494 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1495 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1496 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1497 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1498 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1499 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1500 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1501 V_CY(pvar
).s
.Lo
); break;
1503 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1504 TRACE(",<invalid>");
1506 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1507 st
.wHour
, st
.wMinute
, st
.wSecond
);
1511 case VT_USERDEFINED
:
1513 case VT_NULL
: break;
1514 default: TRACE(",?"); break;
1520 static void dump_DispParms(const DISPPARAMS
* pdp
)
1524 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1526 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1528 TRACE("named args:\n");
1529 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1530 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1533 if (pdp
->cArgs
&& pdp
->rgvarg
)
1536 for (index
= 0; index
< pdp
->cArgs
; index
++)
1537 dump_Variant( &pdp
->rgvarg
[index
] );
1541 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1543 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1544 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1545 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1546 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1547 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1548 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1549 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1550 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1552 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1553 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1554 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1557 static void dump_VARDESC(const VARDESC
*v
)
1559 MESSAGE("memid %d\n",v
->memid
);
1560 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1561 MESSAGE("oInst %d\n",v
->u
.oInst
);
1562 dump_ELEMDESC(&(v
->elemdescVar
));
1563 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1564 MESSAGE("varkind %d\n",v
->varkind
);
1567 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1569 /* VT_LPWSTR is largest type that, may appear in type description */
1570 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1571 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1572 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1573 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1574 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1575 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1576 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1577 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1580 static void TLB_abort(void)
1585 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1587 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1588 if (!ret
) ERR("cannot allocate memory\n");
1592 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1594 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1595 if (!ret
) ERR("cannot allocate memory\n");
1599 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1601 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1604 void heap_free(void *ptr
)
1606 HeapFree(GetProcessHeap(), 0, ptr
);
1609 /* returns the size required for a deep copy of a typedesc into a
1611 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1615 if (alloc_initial_space
)
1616 size
+= sizeof(TYPEDESC
);
1622 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1625 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1626 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1632 /* deep copy a typedesc into a flat buffer */
1633 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1638 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1647 dest
->u
.lptdesc
= buffer
;
1648 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1651 dest
->u
.lpadesc
= buffer
;
1652 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1653 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1654 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1660 /* free custom data allocated by MSFT_CustData */
1661 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1663 TLBCustData
*cd
, *cdn
;
1664 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1666 list_remove(&cd
->entry
);
1667 VariantClear(&cd
->data
);
1672 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1677 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1678 ret
= SysAllocStringLen(NULL
, len
- 1);
1679 if (!ret
) return ret
;
1680 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1684 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1685 UINT n
, MEMBERID memid
)
1688 if(funcdescs
->funcdesc
.memid
== memid
)
1696 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1697 UINT n
, const OLECHAR
*name
)
1700 if(!lstrcmpiW(TLB_get_bstr(funcdescs
->Name
), name
))
1708 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1709 UINT n
, MEMBERID memid
)
1712 if(vardescs
->vardesc
.memid
== memid
)
1720 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1721 UINT n
, const OLECHAR
*name
)
1724 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1732 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1734 TLBCustData
*cust_data
;
1735 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1736 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1741 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1742 UINT n
, const OLECHAR
*name
)
1745 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1753 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1755 list_init(&var_desc
->custdata_list
);
1758 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1762 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1767 TLBVarDesc_Constructor(&ret
[n
-1]);
1774 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1778 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1783 list_init(&ret
[n
-1].custdata_list
);
1790 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1792 list_init(&func_desc
->custdata_list
);
1795 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1799 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1804 TLBFuncDesc_Constructor(&ret
[n
-1]);
1811 static void TLBImplType_Constructor(TLBImplType
*impl
)
1813 list_init(&impl
->custdata_list
);
1816 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1820 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1825 TLBImplType_Constructor(&ret
[n
-1]);
1832 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1833 const GUID
*new_guid
, HREFTYPE hreftype
)
1837 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1838 if (IsEqualGUID(&guid
->guid
, new_guid
))
1842 guid
= heap_alloc(sizeof(TLBGuid
));
1846 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1847 guid
->hreftype
= hreftype
;
1849 list_add_tail(guid_list
, &guid
->entry
);
1854 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1856 TLBCustData
*cust_data
;
1868 return DISP_E_BADVARTYPE
;
1871 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1874 cust_data
= heap_alloc(sizeof(TLBCustData
));
1876 return E_OUTOFMEMORY
;
1878 cust_data
->guid
= tlbguid
;
1879 VariantInit(&cust_data
->data
);
1881 list_add_tail(custdata_list
, &cust_data
->entry
);
1883 VariantClear(&cust_data
->data
);
1885 return VariantCopy(&cust_data
->data
, var
);
1888 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1892 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1893 if (strcmpW(str
->str
, new_str
) == 0)
1897 str
= heap_alloc(sizeof(TLBString
));
1901 str
->str
= SysAllocString(new_str
);
1907 list_add_tail(string_list
, &str
->entry
);
1912 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1913 ULONG
*size
, WORD
*align
)
1919 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1923 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1925 ITypeInfo_Release(other
);
1930 *size
= attr
->cbSizeInstance
;
1932 *align
= attr
->cbAlignment
;
1934 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1935 ITypeInfo_Release(other
);
1940 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1941 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1943 ULONG i
, sub
, ptr_size
;
1946 ptr_size
= get_ptr_size(sys
);
1985 *size
= sizeof(DATE
);
1988 *size
= sizeof(VARIANT
);
1990 if(sys
== SYS_WIN32
)
1991 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1995 *size
= sizeof(DECIMAL
);
2002 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2003 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2004 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2009 case VT_USERDEFINED
:
2010 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2012 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2026 /**********************************************************************
2028 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2030 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
2035 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2037 if (where
!= DO_NOT_SEEK
)
2039 where
+= pcx
->oStart
;
2040 if (where
> pcx
->length
)
2043 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2051 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2053 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2054 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2056 MSFT_Seek(pcx
, where
);
2057 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2058 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2063 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2068 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2069 FromLEDWords(buffer
, ret
);
2074 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2079 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2080 FromLEWords(buffer
, ret
);
2085 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2088 MSFT_GuidEntry entry
;
2091 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2093 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2096 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2098 guid
= heap_alloc(sizeof(TLBGuid
));
2100 guid
->offset
= offs
;
2101 guid
->guid
= entry
.guid
;
2102 guid
->hreftype
= entry
.hreftype
;
2104 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2106 offs
+= sizeof(MSFT_GuidEntry
);
2110 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2114 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2115 if(ret
->offset
== offset
){
2116 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2124 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2126 MSFT_NameIntro niName
;
2130 ERR_(typelib
)("bad offset %d\n", offset
);
2134 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2135 pcx
->pTblDir
->pNametab
.offset
+offset
);
2137 return niName
.hreftype
;
2140 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2143 MSFT_NameIntro intro
;
2145 int offs
= 0, lengthInChars
;
2147 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2151 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2154 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2155 intro
.namelen
&= 0xFF;
2156 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2158 len_piece
= (len_piece
+ 4) & ~0x3;
2162 string
= heap_alloc(len_piece
+ 1);
2163 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2164 string
[intro
.namelen
] = '\0';
2166 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2167 string
, -1, NULL
, 0);
2168 if (!lengthInChars
) {
2170 return E_UNEXPECTED
;
2173 tlbstr
= heap_alloc(sizeof(TLBString
));
2175 tlbstr
->offset
= offs
;
2176 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2177 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2181 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2187 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2191 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2192 if (tlbstr
->offset
== offset
) {
2193 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2201 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2205 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2206 if (tlbstr
->offset
== offset
) {
2207 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2216 * read a value and fill a VARIANT structure
2218 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2222 TRACE_(typelib
)("\n");
2224 if(offset
<0) { /* data are packed in here */
2225 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2226 V_I4(pVar
) = offset
& 0x3ffffff;
2229 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2230 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2231 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2232 switch (V_VT(pVar
)){
2233 case VT_EMPTY
: /* FIXME: is this right? */
2234 case VT_NULL
: /* FIXME: is this right? */
2235 case VT_I2
: /* this should not happen */
2246 case VT_VOID
: /* FIXME: is this right? */
2254 case VT_DECIMAL
: /* FIXME: is this right? */
2257 /* pointer types with known behaviour */
2260 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2263 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
2266 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
2268 nullPos
= MSFT_Tell(pcx
);
2269 size
= nullPos
- origPos
;
2270 MSFT_Seek(pcx
, origPos
);
2272 ptr
= heap_alloc_zero(size
);/* allocate temp buffer */
2273 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
2274 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2275 /* FIXME: do we need a AtoW conversion here? */
2276 V_UNION(pVar
, bstrVal
[size
])='\0';
2277 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2281 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2288 case VT_USERDEFINED
:
2294 case VT_STREAMED_OBJECT
:
2295 case VT_STORED_OBJECT
:
2296 case VT_BLOB_OBJECT
:
2301 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2305 if(size
>0) /* (big|small) endian correct? */
2306 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2310 * create a linked list with custom data
2312 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2318 TRACE_(typelib
)("\n");
2320 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2324 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2325 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2326 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2327 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2328 list_add_head(custdata_list
, &pNew
->entry
);
2329 offset
= entry
.next
;
2334 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2337 pTd
->vt
=type
& VT_TYPEMASK
;
2339 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2341 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2344 static int TLB_is_propgetput(INVOKEKIND invkind
)
2346 return (invkind
== INVOKE_PROPERTYGET
||
2347 invkind
== INVOKE_PROPERTYPUT
||
2348 invkind
== INVOKE_PROPERTYPUTREF
);
2352 MSFT_DoFuncs(TLBContext
* pcx
,
2357 TLBFuncDesc
** pptfd
)
2360 * member information is stored in a data structure at offset
2361 * indicated by the memoffset field of the typeinfo structure
2362 * There are several distinctive parts.
2363 * The first part starts with a field that holds the total length
2364 * of this (first) part excluding this field. Then follow the records,
2365 * for each member there is one record.
2367 * The first entry is always the length of the record (including this
2369 * The rest of the record depends on the type of the member. If there is
2370 * a field indicating the member type (function, variable, interface, etc)
2371 * I have not found it yet. At this time we depend on the information
2372 * in the type info and the usual order how things are stored.
2374 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2377 * Third is an equal sized array with file offsets to the name entry
2380 * The fourth and last (?) part is an array with offsets to the records
2381 * in the first part of this file segment.
2384 int infolen
, nameoffset
, reclength
, i
;
2385 int recoffset
= offset
+ sizeof(INT
);
2387 char *recbuf
= heap_alloc(0xffff);
2388 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2389 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2391 TRACE_(typelib
)("\n");
2393 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2395 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2397 for ( i
= 0; i
< cFuncs
; i
++ )
2401 /* name, eventually add to a hash table */
2402 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2403 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2405 /* read the function information record */
2406 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2408 reclength
&= 0xffff;
2410 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2412 /* size without argument data */
2413 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2414 if (pFuncRec
->FKCCIC
& 0x1000)
2415 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2417 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2418 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2420 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2421 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2423 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2425 if (pFuncRec
->FKCCIC
& 0x2000 )
2427 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2428 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2429 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2432 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2435 ptfd
->Entry
= (TLBString
*)-1;
2437 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2438 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2440 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2441 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2443 /* fill the FuncDesc Structure */
2444 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2445 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2447 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2448 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2449 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2450 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2451 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2452 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2453 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2455 /* nameoffset is sometimes -1 on the second half of a propget/propput
2456 * pair of functions */
2457 if ((nameoffset
== -1) && (i
> 0) &&
2458 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2459 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2460 ptfd
->Name
= ptfd_prev
->Name
;
2462 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2466 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2468 /* do the parameters/arguments */
2469 if(pFuncRec
->nrargs
)
2472 MSFT_ParameterInfo paraminfo
;
2474 ptfd
->funcdesc
.lprgelemdescParam
=
2475 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2477 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2479 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2480 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2482 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2484 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2490 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2493 if (paraminfo
.oName
!= -1)
2494 ptfd
->pParamDesc
[j
].Name
=
2495 MSFT_ReadName( pcx
, paraminfo
.oName
);
2496 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2499 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2500 (pFuncRec
->FKCCIC
& 0x1000) )
2502 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2504 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2506 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2508 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2509 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2511 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2515 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2518 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2519 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2520 pFuncRec
->FKCCIC
& 0x80 )
2523 pFuncRec
->oArgCustData
[j
],
2524 &ptfd
->pParamDesc
[j
].custdata_list
);
2527 /* SEEK value = jump to offset,
2528 * from there jump to the end of record,
2529 * go back by (j-1) arguments
2531 MSFT_ReadLEDWords( ¶minfo
,
2532 sizeof(MSFT_ParameterInfo
), pcx
,
2533 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2534 * sizeof(MSFT_ParameterInfo
)));
2538 /* scode is not used: archaic win16 stuff FIXME: right? */
2539 ptfd
->funcdesc
.cScodes
= 0 ;
2540 ptfd
->funcdesc
.lprgscode
= NULL
;
2544 recoffset
+= reclength
;
2549 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2550 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2552 int infolen
, nameoffset
, reclength
;
2554 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2559 TRACE_(typelib
)("\n");
2561 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2562 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2563 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2564 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2565 recoffset
+= offset
+sizeof(INT
);
2566 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2567 /* name, eventually add to a hash table */
2568 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2569 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2570 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2571 /* read the variable information record */
2572 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2574 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2577 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2578 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2580 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2581 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2583 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2584 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2586 /* fill the VarDesc Structure */
2587 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2588 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2589 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2590 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2591 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2592 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2593 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2594 if(pVarRec
->VarKind
== VAR_CONST
){
2595 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2596 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2597 pVarRec
->OffsValue
, pcx
);
2599 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2600 recoffset
+= reclength
;
2604 /* process Implemented Interfaces of a com class */
2605 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2609 MSFT_RefRecord refrec
;
2612 TRACE_(typelib
)("\n");
2614 pTI
->impltypes
= TLBImplType_Alloc(count
);
2615 pImpl
= pTI
->impltypes
;
2616 for(i
=0;i
<count
;i
++){
2617 if(offset
<0) break; /* paranoia */
2618 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2619 pImpl
->hRef
= refrec
.reftype
;
2620 pImpl
->implflags
=refrec
.flags
;
2621 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2622 offset
=refrec
.onext
;
2628 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2629 * and some structures, and fix the alignment */
2630 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2632 if(info
->typekind
== TKIND_ALIAS
){
2633 switch(info
->tdescAlias
->vt
){
2641 info
->cbSizeInstance
= sizeof(void*);
2642 info
->cbAlignment
= sizeof(void*);
2645 case VT_USERDEFINED
:
2646 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2649 info
->cbSizeInstance
= sizeof(VARIANT
);
2650 info
->cbAlignment
= 8;
2652 if(info
->cbSizeInstance
< sizeof(void*))
2653 info
->cbAlignment
= info
->cbSizeInstance
;
2655 info
->cbAlignment
= sizeof(void*);
2658 }else if(info
->typekind
== TKIND_INTERFACE
||
2659 info
->typekind
== TKIND_DISPATCH
||
2660 info
->typekind
== TKIND_COCLASS
){
2661 info
->cbSizeInstance
= sizeof(void*);
2662 info
->cbAlignment
= sizeof(void*);
2668 * process a typeinfo record
2670 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2673 ITypeLibImpl
* pLibInfo
)
2675 MSFT_TypeInfoBase tiBase
;
2676 ITypeInfoImpl
*ptiRet
;
2678 TRACE_(typelib
)("count=%u\n", count
);
2680 ptiRet
= ITypeInfoImpl_Constructor();
2681 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2682 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2684 /* this is where we are coming from */
2685 ptiRet
->pTypeLib
= pLibInfo
;
2686 ptiRet
->index
=count
;
2688 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2689 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2690 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2691 ptiRet
->cbSizeInstance
=tiBase
.size
;
2692 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2693 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2694 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2695 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2696 ptiRet
->wTypeFlags
=tiBase
.flags
;
2697 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2698 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2699 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2700 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2701 if(ptiRet
->typekind
== TKIND_ALIAS
){
2703 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2704 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2705 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2709 /* IDLDESC idldescType; *//* never saw this one != zero */
2711 /* name, eventually add to a hash table */
2712 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2713 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2714 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2716 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2717 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2718 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2720 if (ptiRet
->typekind
== TKIND_MODULE
)
2721 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2723 /* note: InfoType's Help file and HelpStringDll come from the containing
2724 * library. Further HelpString and Docstring appear to be the same thing :(
2727 if(ptiRet
->cFuncs
>0 )
2728 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2730 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2732 if(ptiRet
->cVars
>0 )
2733 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2735 tiBase
.memoffset
, &ptiRet
->vardescs
);
2736 if(ptiRet
->cImplTypes
>0 ) {
2737 switch(ptiRet
->typekind
)
2740 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2743 case TKIND_DISPATCH
:
2744 /* This is not -1 when the interface is a non-base dual interface or
2745 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2746 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2750 if (tiBase
.datatype1
!= -1)
2752 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2753 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2757 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2758 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2762 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2764 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2765 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2766 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2767 typekind_desc
[ptiRet
->typekind
]);
2768 if (TRACE_ON(typelib
))
2769 dump_TypeInfo(ptiRet
);
2774 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2777 INT16 len_str
, len_piece
;
2778 int offs
= 0, lengthInChars
;
2780 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2784 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2787 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2788 len_piece
= len_str
+ sizeof(INT16
);
2790 len_piece
= (len_piece
+ 4) & ~0x3;
2794 string
= heap_alloc(len_piece
+ 1);
2795 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2796 string
[len_str
] = '\0';
2798 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2799 string
, -1, NULL
, 0);
2800 if (!lengthInChars
) {
2802 return E_UNEXPECTED
;
2805 tlbstr
= heap_alloc(sizeof(TLBString
));
2807 tlbstr
->offset
= offs
;
2808 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2809 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2813 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2819 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2824 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2825 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2826 MSFT_ImpInfo impinfo
;
2829 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2831 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2832 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2834 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2835 if(pImpLib
->offset
==impinfo
.oImpFile
)
2838 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2839 ref
->reference
= offs
;
2840 ref
->pImpTLInfo
= pImpLib
;
2841 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2842 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2843 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2844 ref
->index
= TLB_REF_USE_GUID
;
2846 ref
->index
= impinfo
.oGuid
;
2848 ERR("Cannot find a reference\n");
2849 ref
->reference
= -1;
2850 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2853 offs
+= sizeof(impinfo
);
2859 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2860 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2861 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2864 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2865 static CRITICAL_SECTION cache_section
;
2866 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2868 0, 0, &cache_section
,
2869 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2870 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2872 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2875 typedef struct TLB_PEFile
2877 IUnknown IUnknown_iface
;
2880 HRSRC typelib_resource
;
2881 HGLOBAL typelib_global
;
2882 LPVOID typelib_base
;
2885 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2887 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2890 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2892 if (IsEqualIID(riid
, &IID_IUnknown
))
2895 IUnknown_AddRef(iface
);
2899 return E_NOINTERFACE
;
2902 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2904 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2905 return InterlockedIncrement(&This
->refs
);
2908 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2910 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2911 ULONG refs
= InterlockedDecrement(&This
->refs
);
2914 if (This
->typelib_global
)
2915 FreeResource(This
->typelib_global
);
2917 FreeLibrary(This
->dll
);
2923 static const IUnknownVtbl TLB_PEFile_Vtable
=
2925 TLB_PEFile_QueryInterface
,
2930 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2933 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2935 This
= heap_alloc(sizeof(TLB_PEFile
));
2937 return E_OUTOFMEMORY
;
2939 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2942 This
->typelib_resource
= NULL
;
2943 This
->typelib_global
= NULL
;
2944 This
->typelib_base
= NULL
;
2946 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2947 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2951 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2952 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2953 if (This
->typelib_resource
)
2955 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2956 if (This
->typelib_global
)
2958 This
->typelib_base
= LockResource(This
->typelib_global
);
2960 if (This
->typelib_base
)
2962 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2963 *ppBase
= This
->typelib_base
;
2964 *ppFile
= &This
->IUnknown_iface
;
2970 TRACE("No TYPELIB resource found\n");
2974 TLB_PEFile_Release(&This
->IUnknown_iface
);
2978 typedef struct TLB_NEFile
2980 IUnknown IUnknown_iface
;
2982 LPVOID typelib_base
;
2985 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2987 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2990 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2992 if (IsEqualIID(riid
, &IID_IUnknown
))
2995 IUnknown_AddRef(iface
);
2999 return E_NOINTERFACE
;
3002 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3004 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3005 return InterlockedIncrement(&This
->refs
);
3008 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3010 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3011 ULONG refs
= InterlockedDecrement(&This
->refs
);
3014 heap_free(This
->typelib_base
);
3020 static const IUnknownVtbl TLB_NEFile_Vtable
=
3022 TLB_NEFile_QueryInterface
,
3027 /***********************************************************************
3028 * read_xx_header [internal]
3030 static int read_xx_header( HFILE lzfd
)
3032 IMAGE_DOS_HEADER mzh
;
3035 LZSeek( lzfd
, 0, SEEK_SET
);
3036 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3038 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3041 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3042 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3045 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3047 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3048 return IMAGE_OS2_SIGNATURE
;
3049 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3050 return IMAGE_NT_SIGNATURE
;
3053 WARN("Can't handle %s files.\n", magic
);
3058 /***********************************************************************
3059 * find_ne_resource [internal]
3061 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3062 DWORD
*resLen
, DWORD
*resOff
)
3064 IMAGE_OS2_HEADER nehd
;
3065 NE_TYPEINFO
*typeInfo
;
3066 NE_NAMEINFO
*nameInfo
;
3072 /* Read in NE header */
3073 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3074 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
3076 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3079 TRACE("No resources in NE dll\n" );
3083 /* Read in resource table */
3084 resTab
= heap_alloc( resTabSize
);
3085 if ( !resTab
) return FALSE
;
3087 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3088 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3090 heap_free( resTab
);
3095 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3097 if (!IS_INTRESOURCE(typeid)) /* named type */
3099 BYTE len
= strlen( typeid );
3100 while (typeInfo
->type_id
)
3102 if (!(typeInfo
->type_id
& 0x8000))
3104 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3105 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3107 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3108 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3111 else /* numeric type id */
3113 WORD id
= LOWORD(typeid) | 0x8000;
3114 while (typeInfo
->type_id
)
3116 if (typeInfo
->type_id
== id
) goto found_type
;
3117 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3118 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3121 TRACE("No typeid entry found for %p\n", typeid );
3122 heap_free( resTab
);
3126 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3128 if (!IS_INTRESOURCE(resid
)) /* named resource */
3130 BYTE len
= strlen( resid
);
3131 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3133 BYTE
*p
= resTab
+ nameInfo
->id
;
3134 if (nameInfo
->id
& 0x8000) continue;
3135 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3138 else /* numeric resource id */
3140 WORD id
= LOWORD(resid
) | 0x8000;
3141 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3142 if (nameInfo
->id
== id
) goto found_name
;
3144 TRACE("No resid entry found for %p\n", typeid );
3145 heap_free( resTab
);
3149 /* Return resource data */
3150 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3151 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3153 heap_free( resTab
);
3157 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3161 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3164 This
= heap_alloc(sizeof(TLB_NEFile
));
3165 if (!This
) return E_OUTOFMEMORY
;
3167 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3169 This
->typelib_base
= NULL
;
3171 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3172 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3174 DWORD reslen
, offset
;
3175 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3177 This
->typelib_base
= heap_alloc(reslen
);
3178 if( !This
->typelib_base
)
3182 LZSeek( lzfd
, offset
, SEEK_SET
);
3183 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3185 *ppBase
= This
->typelib_base
;
3186 *pdwTLBLength
= reslen
;
3187 *ppFile
= &This
->IUnknown_iface
;
3193 if( lzfd
>= 0) LZClose( lzfd
);
3194 TLB_NEFile_Release(&This
->IUnknown_iface
);
3198 typedef struct TLB_Mapping
3200 IUnknown IUnknown_iface
;
3204 LPVOID typelib_base
;
3207 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3209 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3212 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3214 if (IsEqualIID(riid
, &IID_IUnknown
))
3217 IUnknown_AddRef(iface
);
3221 return E_NOINTERFACE
;
3224 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3226 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3227 return InterlockedIncrement(&This
->refs
);
3230 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3232 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3233 ULONG refs
= InterlockedDecrement(&This
->refs
);
3236 if (This
->typelib_base
)
3237 UnmapViewOfFile(This
->typelib_base
);
3239 CloseHandle(This
->mapping
);
3240 if (This
->file
!= INVALID_HANDLE_VALUE
)
3241 CloseHandle(This
->file
);
3247 static const IUnknownVtbl TLB_Mapping_Vtable
=
3249 TLB_Mapping_QueryInterface
,
3254 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3258 This
= heap_alloc(sizeof(TLB_Mapping
));
3260 return E_OUTOFMEMORY
;
3262 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3264 This
->file
= INVALID_HANDLE_VALUE
;
3265 This
->mapping
= NULL
;
3266 This
->typelib_base
= NULL
;
3268 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3269 if (INVALID_HANDLE_VALUE
!= This
->file
)
3271 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3274 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3275 if(This
->typelib_base
)
3277 /* retrieve file size */
3278 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3279 *ppBase
= This
->typelib_base
;
3280 *ppFile
= &This
->IUnknown_iface
;
3286 IUnknown_Release(&This
->IUnknown_iface
);
3287 return TYPE_E_CANTLOADLIBRARY
;
3290 /****************************************************************************
3293 * find the type of the typelib file and map the typelib resource into
3297 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3298 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3300 ITypeLibImpl
*entry
;
3303 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3304 LPVOID pBase
= NULL
;
3305 DWORD dwTLBLength
= 0;
3306 IUnknown
*pFile
= NULL
;
3311 index_str
= strrchrW(pszFileName
, '\\');
3312 if(index_str
&& *++index_str
!= '\0')
3315 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3316 if(*end_ptr
== '\0')
3318 int str_len
= index_str
- pszFileName
- 1;
3320 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3321 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3326 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3328 if(strchrW(file
, '\\'))
3330 lstrcpyW(pszPath
, file
);
3334 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3335 pszPath
[len
] = '\\';
3336 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3340 if(file
!= pszFileName
) heap_free(file
);
3342 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_ALWAYS
,
3343 FILE_ATTRIBUTE_NORMAL
, NULL
);
3344 if(h
!= INVALID_HANDLE_VALUE
){
3345 FILE_NAME_INFORMATION
*info
;
3346 char data
[MAX_PATH
* sizeof(WCHAR
) + sizeof(info
->FileNameLength
)];
3349 info
= (FILE_NAME_INFORMATION
*)data
;
3350 /* GetFileInformationByHandleEx returns the path of the file without
3351 * WOW64 redirection */
3352 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, data
, sizeof(data
));
3354 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3355 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3360 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3362 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3363 EnterCriticalSection(&cache_section
);
3364 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3366 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3368 TRACE("cache hit\n");
3369 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3370 ITypeLib2_AddRef(*ppTypeLib
);
3371 LeaveCriticalSection(&cache_section
);
3375 LeaveCriticalSection(&cache_section
);
3377 /* now actually load and parse the typelib */
3379 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3380 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3381 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3382 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3383 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3386 if (dwTLBLength
>= 4)
3388 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3389 if (dwSignature
== MSFT_SIGNATURE
)
3390 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3391 else if (dwSignature
== SLTG_SIGNATURE
)
3392 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3395 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3396 ret
= TYPE_E_CANTLOADLIBRARY
;
3400 ret
= TYPE_E_CANTLOADLIBRARY
;
3401 IUnknown_Release(pFile
);
3405 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3407 TRACE("adding to cache\n");
3408 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3409 lstrcpyW(impl
->path
, pszPath
);
3410 /* We should really canonicalise the path here. */
3411 impl
->index
= index
;
3413 /* FIXME: check if it has added already in the meantime */
3414 EnterCriticalSection(&cache_section
);
3415 list_add_head(&tlb_cache
, &impl
->entry
);
3416 LeaveCriticalSection(&cache_section
);
3422 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3424 ret
= TYPE_E_CANTLOADLIBRARY
;
3431 /*================== ITypeLib(2) Methods ===================================*/
3433 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3435 ITypeLibImpl
* pTypeLibImpl
;
3437 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3438 if (!pTypeLibImpl
) return NULL
;
3440 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3441 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3442 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3443 pTypeLibImpl
->ref
= 1;
3445 list_init(&pTypeLibImpl
->implib_list
);
3446 list_init(&pTypeLibImpl
->custdata_list
);
3447 list_init(&pTypeLibImpl
->name_list
);
3448 list_init(&pTypeLibImpl
->string_list
);
3449 list_init(&pTypeLibImpl
->guid_list
);
3450 list_init(&pTypeLibImpl
->ref_list
);
3451 pTypeLibImpl
->dispatch_href
= -1;
3453 return pTypeLibImpl
;
3456 /****************************************************************************
3457 * ITypeLib2_Constructor_MSFT
3459 * loading an MSFT typelib from an in-memory image
3461 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3465 MSFT_Header tlbHeader
;
3466 MSFT_SegDir tlbSegDir
;
3467 ITypeLibImpl
* pTypeLibImpl
;
3470 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3472 pTypeLibImpl
= TypeLibImpl_Constructor();
3473 if (!pTypeLibImpl
) return NULL
;
3475 /* get pointer to beginning of typelib data */
3479 cx
.pLibInfo
= pTypeLibImpl
;
3480 cx
.length
= dwTLBLength
;
3483 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3484 TRACE_(typelib
)("header:\n");
3485 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3486 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3487 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3490 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3492 /* there is a small amount of information here until the next important
3494 * the segment directory . Try to calculate the amount of data */
3495 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3497 /* now read the segment directory */
3498 TRACE("read segment directory (at %d)\n",lPSegDir
);
3499 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3500 cx
.pTblDir
= &tlbSegDir
;
3502 /* just check two entries */
3503 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3505 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3506 heap_free(pTypeLibImpl
);
3510 MSFT_ReadAllNames(&cx
);
3511 MSFT_ReadAllStrings(&cx
);
3512 MSFT_ReadAllGuids(&cx
);
3514 /* now fill our internal data */
3515 /* TLIBATTR fields */
3516 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3518 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3519 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3520 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3521 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3522 pTypeLibImpl
->libflags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3524 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3525 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3527 /* name, eventually add to a hash table */
3528 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3531 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3532 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3534 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3537 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3538 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3541 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3544 if(tlbHeader
.CustomDataOffset
>= 0)
3546 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3549 /* fill in type descriptions */
3550 if(tlbSegDir
.pTypdescTab
.length
> 0)
3552 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3554 pTypeLibImpl
->ctTypeDesc
= cTD
;
3555 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3556 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3559 /* FIXME: add several sanity checks here */
3560 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3561 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3563 /* FIXME: check safearray */
3565 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3567 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3569 else if(td
[0] == VT_CARRAY
)
3571 /* array descr table here */
3572 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3574 else if(td
[0] == VT_USERDEFINED
)
3576 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3578 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3581 /* second time around to fill the array subscript info */
3584 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3585 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3587 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3588 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3591 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3593 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3595 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3597 for(j
= 0; j
<td
[2]; j
++)
3599 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3600 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3601 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3602 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3607 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3608 ERR("didn't find array description data\n");
3613 /* imported type libs */
3614 if(tlbSegDir
.pImpFiles
.offset
>0)
3617 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3620 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3624 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3625 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3626 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3628 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3629 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3630 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3631 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3634 name
= heap_alloc_zero(size
+1);
3635 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3636 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3639 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3640 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3642 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3646 MSFT_ReadAllRefs(&cx
);
3648 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3651 if(tlbHeader
.nrtypeinfos
>= 0 )
3653 ITypeInfoImpl
**ppTI
;
3655 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3657 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3659 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3662 (pTypeLibImpl
->TypeInfoCount
)++;
3667 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3668 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3669 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3673 TRACE("(%p)\n", pTypeLibImpl
);
3674 return &pTypeLibImpl
->ITypeLib2_iface
;
3678 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3684 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3685 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3689 guid
->Data4
[0] = s
>> 8;
3690 guid
->Data4
[1] = s
& 0xff;
3693 for(i
= 0; i
< 6; i
++) {
3694 memcpy(b
, str
+ 24 + 2 * i
, 2);
3695 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3700 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3707 bytelen
= *(const WORD
*)ptr
;
3708 if(bytelen
== 0xffff) return 2;
3710 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3711 tmp_str
= SysAllocStringLen(NULL
, len
);
3713 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3714 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3715 SysFreeString(tmp_str
);
3720 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3725 bytelen
= *(const WORD
*)ptr
;
3726 if(bytelen
== 0xffff) return 2;
3727 *str
= heap_alloc(bytelen
+ 1);
3728 memcpy(*str
, ptr
+ 2, bytelen
);
3729 (*str
)[bytelen
] = '\0';
3733 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3738 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3739 if (tlbstr
->offset
== offset
)
3743 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3744 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3745 SysFreeString(tmp_str
);
3750 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3752 char *ptr
= pLibBlk
;
3755 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3756 FIXME("libblk magic = %04x\n", w
);
3761 if((w
= *(WORD
*)ptr
) != 0xffff) {
3762 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3767 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3769 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3771 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3774 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3775 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3778 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3779 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3781 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3784 ptr
+= 4; /* skip res12 */
3786 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3789 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3792 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3795 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3796 ptr
+= sizeof(GUID
);
3798 return ptr
- (char*)pLibBlk
;
3801 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3806 } sltg_ref_lookup_t
;
3808 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3809 HREFTYPE
*typelib_ref
)
3811 if(table
&& typeinfo_ref
< table
->num
)
3813 *typelib_ref
= table
->refs
[typeinfo_ref
];
3817 ERR_(typelib
)("Unable to find reference\n");
3822 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3827 if((*pType
& 0xe00) == 0xe00) {
3829 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3830 pTD
= pTD
->u
.lptdesc
;
3832 switch(*pType
& 0x3f) {
3835 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3836 pTD
= pTD
->u
.lptdesc
;
3839 case VT_USERDEFINED
:
3840 pTD
->vt
= VT_USERDEFINED
;
3841 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3847 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3850 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3852 pTD
->vt
= VT_CARRAY
;
3853 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3854 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3855 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3856 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3858 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3864 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3868 pTD
->vt
= VT_SAFEARRAY
;
3869 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3870 pTD
= pTD
->u
.lptdesc
;
3874 pTD
->vt
= *pType
& 0x3f;
3883 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3884 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3886 /* Handle [in/out] first */
3887 if((*pType
& 0xc000) == 0xc000)
3888 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3889 else if(*pType
& 0x8000)
3890 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3891 else if(*pType
& 0x4000)
3892 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3894 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3897 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3900 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3902 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3906 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3911 TLBRefType
*ref_type
;
3912 sltg_ref_lookup_t
*table
;
3913 HREFTYPE typelib_ref
;
3915 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3916 FIXME("Ref magic = %x\n", pRef
->magic
);
3919 name
= ( (char*)pRef
->names
+ pRef
->number
);
3921 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3922 table
->num
= pRef
->number
>> 3;
3924 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3926 /* We don't want the first href to be 0 */
3927 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3929 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3931 unsigned int lib_offs
, type_num
;
3933 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3935 name
+= SLTG_ReadStringA(name
, &refname
);
3936 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3937 FIXME_(typelib
)("Can't sscanf ref\n");
3938 if(lib_offs
!= 0xffff) {
3941 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3942 if(import
->offset
== lib_offs
)
3945 if(&import
->entry
== &pTL
->implib_list
) {
3946 char fname
[MAX_PATH
+1];
3950 import
= heap_alloc_zero(sizeof(*import
));
3951 import
->offset
= lib_offs
;
3952 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3953 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3954 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3955 &import
->wVersionMajor
,
3956 &import
->wVersionMinor
,
3957 &import
->lcid
, fname
) != 4) {
3958 FIXME_(typelib
)("can't sscanf ref %s\n",
3959 pNameTable
+ lib_offs
+ 40);
3961 len
= strlen(fname
);
3962 if(fname
[len
-1] != '#')
3963 FIXME("fname = %s\n", fname
);
3964 fname
[len
-1] = '\0';
3965 import
->name
= TLB_MultiByteToBSTR(fname
);
3966 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3968 ref_type
->pImpTLInfo
= import
;
3970 /* Store a reference to IDispatch */
3971 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3972 pTL
->dispatch_href
= typelib_ref
;
3974 } else { /* internal ref */
3975 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3977 ref_type
->reference
= typelib_ref
;
3978 ref_type
->index
= type_num
;
3981 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3983 table
->refs
[ref
] = typelib_ref
;
3986 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3987 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3988 dump_TLBRefType(pTL
);
3992 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3993 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3995 SLTG_ImplInfo
*info
;
3996 TLBImplType
*pImplType
;
3997 /* I don't really get this structure, usually it's 0x16 bytes
3998 long, but iuser.tlb contains some that are 0x18 bytes long.
3999 That's ok because we can use the next ptr to jump to the next
4000 one. But how do we know the length of the last one? The WORD
4001 at offs 0x8 might be the clue. For now I'm just assuming that
4002 the last one is the regular 0x16 bytes. */
4004 info
= (SLTG_ImplInfo
*)pBlk
;
4007 if(info
->next
== 0xffff)
4009 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4012 info
= (SLTG_ImplInfo
*)pBlk
;
4013 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4014 pImplType
= pTI
->impltypes
;
4016 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4017 pImplType
->implflags
= info
->impltypeflags
;
4020 if(info
->next
== 0xffff)
4023 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4024 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4026 info
++; /* see comment at top of function */
4030 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4031 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4033 TLBVarDesc
*pVarDesc
;
4034 const TLBString
*prevName
= NULL
;
4035 SLTG_Variable
*pItem
;
4039 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4041 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4042 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4044 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4046 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4047 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4048 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4052 if (pItem
->name
== 0xfffe)
4053 pVarDesc
->Name
= prevName
;
4055 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4057 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4058 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4059 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4061 if(pItem
->flags
& 0x02)
4062 pType
= &pItem
->type
;
4064 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4066 if (pItem
->flags
& ~0xda)
4067 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4069 SLTG_DoElem(pType
, pBlk
,
4070 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4072 if (TRACE_ON(typelib
)) {
4074 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4075 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4078 if (pItem
->flags
& 0x40) {
4079 TRACE_(typelib
)("VAR_DISPATCH\n");
4080 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4082 else if (pItem
->flags
& 0x10) {
4083 TRACE_(typelib
)("VAR_CONST\n");
4084 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4085 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4086 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4087 if (pItem
->flags
& 0x08)
4088 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4090 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4096 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4098 TRACE_(typelib
)("len = %u\n", len
);
4099 if (len
== 0xffff) {
4102 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4103 str
= SysAllocStringLen(NULL
, alloc_len
);
4104 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4106 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4107 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4116 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4117 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4120 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4125 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4126 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4127 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4130 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4131 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4133 if (pItem
->flags
& 0x80)
4134 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4136 prevName
= pVarDesc
->Name
;
4141 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4142 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4144 SLTG_Function
*pFunc
;
4146 TLBFuncDesc
*pFuncDesc
;
4148 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4150 pFuncDesc
= pTI
->funcdescs
;
4151 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4152 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4157 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4158 case SLTG_FUNCTION_MAGIC
:
4159 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4161 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4162 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4164 case SLTG_STATIC_FUNCTION_MAGIC
:
4165 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4168 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4171 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4173 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4174 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4175 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4176 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4177 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4178 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4180 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4181 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4183 if(pFunc
->retnextopt
& 0x80)
4184 pType
= &pFunc
->rettype
;
4186 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4188 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4190 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4191 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4192 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4194 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4196 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4197 char *paramName
= pNameTable
+ *pArg
;
4199 /* If arg type follows then paramName points to the 2nd
4200 letter of the name, else the next WORD is an offset to
4201 the arg type and paramName points to the first letter.
4202 So let's take one char off paramName and see if we're
4203 pointing at an alpha-numeric char. However if *pArg is
4204 0xffff or 0xfffe then the param has no name, the former
4205 meaning that the next WORD is the type, the latter
4206 meaning that the next WORD is an offset to the type. */
4211 else if(*pArg
== 0xfffe) {
4215 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4220 if(HaveOffs
) { /* the next word is an offset to type */
4221 pType
= (WORD
*)(pBlk
+ *pArg
);
4222 SLTG_DoElem(pType
, pBlk
,
4223 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4228 pArg
= SLTG_DoElem(pArg
, pBlk
,
4229 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4232 /* Are we an optional param ? */
4233 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4234 pFuncDesc
->funcdesc
.cParamsOpt
)
4235 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4238 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4239 paramName
- pNameTable
, pTI
->pTypeLib
);
4241 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4245 pTI
->cFuncs
= cFuncs
;
4248 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4249 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4250 SLTG_TypeInfoTail
*pTITail
)
4253 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4255 if(pTIHeader
->href_table
!= 0xffffffff) {
4256 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4262 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4263 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4265 heap_free(ref_lookup
);
4269 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4270 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4271 const SLTG_TypeInfoTail
*pTITail
)
4274 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4276 if(pTIHeader
->href_table
!= 0xffffffff) {
4277 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4283 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4284 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4287 if (pTITail
->funcs_off
!= 0xffff)
4288 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4290 heap_free(ref_lookup
);
4292 if (TRACE_ON(typelib
))
4293 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4296 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4297 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4298 const SLTG_TypeInfoTail
*pTITail
)
4300 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4303 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4304 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4305 const SLTG_TypeInfoTail
*pTITail
)
4308 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4310 if (pTITail
->simple_alias
) {
4311 /* if simple alias, no more processing required */
4312 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4313 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4317 if(pTIHeader
->href_table
!= 0xffffffff) {
4318 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4322 /* otherwise it is an offset to a type */
4323 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4325 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4326 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4328 heap_free(ref_lookup
);
4331 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4332 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4333 const SLTG_TypeInfoTail
*pTITail
)
4335 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4336 if (pTIHeader
->href_table
!= 0xffffffff)
4337 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4340 if (pTITail
->vars_off
!= 0xffff)
4341 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4343 if (pTITail
->funcs_off
!= 0xffff)
4344 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4346 if (pTITail
->impls_off
!= 0xffff)
4347 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4349 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4350 * of dispinterface functions including the IDispatch ones, so
4351 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4352 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4354 heap_free(ref_lookup
);
4355 if (TRACE_ON(typelib
))
4356 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4359 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4360 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4361 const SLTG_TypeInfoTail
*pTITail
)
4363 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4366 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4367 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4368 const SLTG_TypeInfoTail
*pTITail
)
4370 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4371 if (pTIHeader
->href_table
!= 0xffffffff)
4372 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4375 if (pTITail
->vars_off
!= 0xffff)
4376 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4378 if (pTITail
->funcs_off
!= 0xffff)
4379 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4380 heap_free(ref_lookup
);
4381 if (TRACE_ON(typelib
))
4385 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4386 manageable copy of it into this */
4399 } SLTG_InternalOtherTypeInfo
;
4401 /****************************************************************************
4402 * ITypeLib2_Constructor_SLTG
4404 * loading a SLTG typelib from an in-memory image
4406 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4408 ITypeLibImpl
*pTypeLibImpl
;
4409 SLTG_Header
*pHeader
;
4410 SLTG_BlkEntry
*pBlkEntry
;
4414 LPVOID pBlk
, pFirstBlk
;
4415 SLTG_LibBlk
*pLibBlk
;
4416 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4417 char *pAfterOTIBlks
= NULL
;
4418 char *pNameTable
, *ptr
;
4421 ITypeInfoImpl
**ppTypeInfoImpl
;
4423 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4426 pTypeLibImpl
= TypeLibImpl_Constructor();
4427 if (!pTypeLibImpl
) return NULL
;
4431 TRACE_(typelib
)("header:\n");
4432 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4433 pHeader
->nrOfFileBlks
);
4434 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4435 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4436 pHeader
->SLTG_magic
);
4440 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4441 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4443 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4444 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4446 /* Next we have a magic block */
4447 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4449 /* Let's see if we're still in sync */
4450 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4451 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4452 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4455 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4456 sizeof(SLTG_DIR_MAGIC
))) {
4457 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4461 pIndex
= (SLTG_Index
*)(pMagic
+1);
4463 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4465 pFirstBlk
= pPad9
+ 1;
4467 /* We'll set up a ptr to the main library block, which is the last one. */
4469 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4470 pBlkEntry
[order
].next
!= 0;
4471 order
= pBlkEntry
[order
].next
- 1, i
++) {
4472 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4476 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4478 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4483 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4485 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4488 ptr
= (char*)pLibBlk
+ len
;
4490 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4494 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4496 w
= *(WORD
*)(ptr
+ 2);
4499 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4500 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4501 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4503 w
= *(WORD
*)(ptr
+ 4 + len
);
4505 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4507 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4508 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4509 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4511 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4512 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4513 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4515 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4516 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4519 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4520 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4521 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4522 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4523 len
+= sizeof(SLTG_OtherTypeInfo
);
4527 pAfterOTIBlks
= ptr
;
4529 /* Skip this WORD and get the next DWORD */
4530 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4532 /* Now add this to pLibBLk look at what we're pointing at and
4533 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4534 dust and we should be pointing at the beginning of the name
4537 pNameTable
= (char*)pLibBlk
+ len
;
4539 switch(*(WORD
*)pNameTable
) {
4546 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4550 pNameTable
+= 0x216;
4554 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4556 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4559 /* Hopefully we now have enough ptrs set up to actually read in
4560 some TypeInfos. It's not clear which order to do them in, so
4561 I'll just follow the links along the BlkEntry chain and read
4562 them in the order in which they are in the file */
4564 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4565 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4567 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4568 pBlkEntry
[order
].next
!= 0;
4569 order
= pBlkEntry
[order
].next
- 1, i
++) {
4571 SLTG_TypeInfoHeader
*pTIHeader
;
4572 SLTG_TypeInfoTail
*pTITail
;
4573 SLTG_MemberHeader
*pMemHeader
;
4575 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4576 FIXME_(typelib
)("Index strings don't match\n");
4577 heap_free(pOtherTypeInfoBlks
);
4582 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4583 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4584 heap_free(pOtherTypeInfoBlks
);
4587 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4588 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4589 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4591 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4592 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4593 (*ppTypeInfoImpl
)->index
= i
;
4594 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4595 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4596 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4597 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4598 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4599 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4600 (*ppTypeInfoImpl
)->wTypeFlags
=
4601 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4603 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4604 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4606 if((pTIHeader
->typeflags1
& 7) != 2)
4607 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4608 if(pTIHeader
->typeflags3
!= 2)
4609 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4611 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4612 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4613 typekind_desc
[pTIHeader
->typekind
],
4614 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4615 (*ppTypeInfoImpl
)->wTypeFlags
);
4617 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4619 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4621 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4622 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4623 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4625 switch(pTIHeader
->typekind
) {
4627 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4628 pTIHeader
, pTITail
);
4632 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4633 pTIHeader
, pTITail
);
4636 case TKIND_INTERFACE
:
4637 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4638 pTIHeader
, pTITail
);
4642 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4643 pTIHeader
, pTITail
);
4647 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4648 pTIHeader
, pTITail
);
4651 case TKIND_DISPATCH
:
4652 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4653 pTIHeader
, pTITail
);
4657 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4658 pTIHeader
, pTITail
);
4662 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4667 /* could get cFuncs, cVars and cImplTypes from here
4668 but we've already set those */
4669 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4685 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4688 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4689 FIXME("Somehow processed %d TypeInfos\n", i
);
4690 heap_free(pOtherTypeInfoBlks
);
4694 heap_free(pOtherTypeInfoBlks
);
4695 return &pTypeLibImpl
->ITypeLib2_iface
;
4698 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4700 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4702 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4704 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4705 IsEqualIID(riid
,&IID_ITypeLib
)||
4706 IsEqualIID(riid
,&IID_ITypeLib2
))
4708 *ppv
= &This
->ITypeLib2_iface
;
4710 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4711 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4713 *ppv
= &This
->ICreateTypeLib2_iface
;
4718 TRACE("-- Interface: E_NOINTERFACE\n");
4719 return E_NOINTERFACE
;
4722 IUnknown_AddRef((IUnknown
*)*ppv
);
4726 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4728 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4729 ULONG ref
= InterlockedIncrement(&This
->ref
);
4731 TRACE("(%p) ref=%u\n", This
, ref
);
4736 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4738 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4739 ULONG ref
= InterlockedDecrement(&This
->ref
);
4741 TRACE("(%p) ref=%u\n",This
, ref
);
4745 TLBImpLib
*pImpLib
, *pImpLibNext
;
4746 TLBRefType
*ref_type
;
4747 TLBString
*tlbstr
, *tlbstr_next
;
4748 TLBGuid
*tlbguid
, *tlbguid_next
;
4752 /* remove cache entry */
4755 TRACE("removing from cache list\n");
4756 EnterCriticalSection(&cache_section
);
4757 if(This
->entry
.next
)
4758 list_remove(&This
->entry
);
4759 LeaveCriticalSection(&cache_section
);
4760 heap_free(This
->path
);
4762 TRACE(" destroying ITypeLib(%p)\n",This
);
4764 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4765 list_remove(&tlbstr
->entry
);
4766 SysFreeString(tlbstr
->str
);
4770 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4771 list_remove(&tlbstr
->entry
);
4772 SysFreeString(tlbstr
->str
);
4776 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4777 list_remove(&tlbguid
->entry
);
4781 TLB_FreeCustData(&This
->custdata_list
);
4783 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4784 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4785 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4787 heap_free(This
->pTypeDesc
);
4789 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4791 if (pImpLib
->pImpTypeLib
)
4792 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4793 SysFreeString(pImpLib
->name
);
4795 list_remove(&pImpLib
->entry
);
4799 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4801 list_remove(&ref_type
->entry
);
4802 heap_free(ref_type
);
4805 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4806 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4807 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4809 heap_free(This
->typeinfos
);
4817 /* ITypeLib::GetTypeInfoCount
4819 * Returns the number of type descriptions in the type library
4821 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4823 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4824 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4825 return This
->TypeInfoCount
;
4828 /* ITypeLib::GetTypeInfo
4830 * retrieves the specified type description in the library.
4832 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4835 ITypeInfo
**ppTInfo
)
4837 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4839 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4842 return E_INVALIDARG
;
4844 if(index
>= This
->TypeInfoCount
)
4845 return TYPE_E_ELEMENTNOTFOUND
;
4847 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4848 ITypeInfo_AddRef(*ppTInfo
);
4854 /* ITypeLibs::GetTypeInfoType
4856 * Retrieves the type of a type description.
4858 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4863 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4865 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4868 return E_INVALIDARG
;
4870 if(index
>= This
->TypeInfoCount
)
4871 return TYPE_E_ELEMENTNOTFOUND
;
4873 *pTKind
= This
->typeinfos
[index
]->typekind
;
4878 /* ITypeLib::GetTypeInfoOfGuid
4880 * Retrieves the type description that corresponds to the specified GUID.
4883 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4886 ITypeInfo
**ppTInfo
)
4888 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4891 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4893 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4894 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4895 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4896 ITypeInfo_AddRef(*ppTInfo
);
4901 return TYPE_E_ELEMENTNOTFOUND
;
4904 /* ITypeLib::GetLibAttr
4906 * Retrieves the structure that contains the library's attributes.
4909 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4913 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4915 TRACE("(%p, %p)\n", This
, attr
);
4917 if (!attr
) return E_INVALIDARG
;
4919 *attr
= heap_alloc(sizeof(**attr
));
4920 if (!*attr
) return E_OUTOFMEMORY
;
4922 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4923 (*attr
)->lcid
= This
->set_lcid
;
4924 (*attr
)->syskind
= This
->syskind
;
4925 (*attr
)->wMajorVerNum
= This
->ver_major
;
4926 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4927 (*attr
)->wLibFlags
= This
->libflags
;
4932 /* ITypeLib::GetTypeComp
4934 * Enables a client compiler to bind to a library's types, variables,
4935 * constants, and global functions.
4938 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4940 ITypeComp
**ppTComp
)
4942 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4944 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4945 *ppTComp
= &This
->ITypeComp_iface
;
4946 ITypeComp_AddRef(*ppTComp
);
4951 /* ITypeLib::GetDocumentation
4953 * Retrieves the library's documentation string, the complete Help file name
4954 * and path, and the context identifier for the library Help topic in the Help
4957 * On a successful return all non-null BSTR pointers will have been set,
4960 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4964 BSTR
*pBstrDocString
,
4965 DWORD
*pdwHelpContext
,
4966 BSTR
*pBstrHelpFile
)
4968 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4969 HRESULT result
= E_INVALIDARG
;
4972 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4974 pBstrName
, pBstrDocString
,
4975 pdwHelpContext
, pBstrHelpFile
);
4979 /* documentation for the typelib */
4984 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4992 if (This
->DocString
)
4994 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4998 *pBstrDocString
= NULL
;
5002 *pdwHelpContext
= This
->dwHelpContext
;
5008 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5012 *pBstrHelpFile
= NULL
;
5019 /* for a typeinfo */
5020 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5022 if(SUCCEEDED(result
))
5024 result
= ITypeInfo_GetDocumentation(pTInfo
,
5028 pdwHelpContext
, pBstrHelpFile
);
5030 ITypeInfo_Release(pTInfo
);
5035 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5037 if (pBstrName
) SysFreeString (*pBstrName
);
5039 return STG_E_INSUFFICIENTMEMORY
;
5044 * Indicates whether a passed-in string contains the name of a type or member
5045 * described in the library.
5048 static HRESULT WINAPI
ITypeLib2_fnIsName(
5054 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5056 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5058 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5062 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5063 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5064 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5065 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5066 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5068 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5069 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5070 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5071 goto ITypeLib2_fnIsName_exit
;
5074 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5075 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5076 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5082 ITypeLib2_fnIsName_exit
:
5083 TRACE("(%p)slow! search for %s: %s found!\n", This
,
5084 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
5089 /* ITypeLib::FindName
5091 * Finds occurrences of a type description in a type library. This may be used
5092 * to quickly verify that a name exists in a type library.
5095 static HRESULT WINAPI
ITypeLib2_fnFindName(
5099 ITypeInfo
**ppTInfo
,
5103 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5108 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5110 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5111 return E_INVALIDARG
;
5113 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5114 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
5115 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5119 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
5120 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5121 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5124 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
5125 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
5126 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
5127 goto ITypeLib2_fnFindName_exit
;
5131 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5133 goto ITypeLib2_fnFindName_exit
;
5136 ITypeLib2_fnFindName_exit
:
5137 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5138 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5141 TRACE("found %d typeinfos\n", count
);
5148 /* ITypeLib::ReleaseTLibAttr
5150 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5153 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5155 TLIBATTR
*pTLibAttr
)
5157 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5158 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5159 heap_free(pTLibAttr
);
5162 /* ITypeLib2::GetCustData
5164 * gets the custom data
5166 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5171 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5172 TLBCustData
*pCData
;
5174 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5176 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5178 return TYPE_E_ELEMENTNOTFOUND
;
5180 VariantInit(pVarVal
);
5181 VariantCopy(pVarVal
, &pCData
->data
);
5186 /* ITypeLib2::GetLibStatistics
5188 * Returns statistics about a type library that are required for efficient
5189 * sizing of hash tables.
5192 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5194 ULONG
*pcUniqueNames
,
5195 ULONG
*pcchUniqueNames
)
5197 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5199 FIXME("(%p): stub!\n", This
);
5201 if(pcUniqueNames
) *pcUniqueNames
=1;
5202 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5206 /* ITypeLib2::GetDocumentation2
5208 * Retrieves the library's documentation string, the complete Help file name
5209 * and path, the localization context to use, and the context ID for the
5210 * library Help topic in the Help file.
5213 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5217 BSTR
*pbstrHelpString
,
5218 DWORD
*pdwHelpStringContext
,
5219 BSTR
*pbstrHelpStringDll
)
5221 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5225 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5227 /* the help string should be obtained from the helpstringdll,
5228 * using the _DLLGetDocumentation function, based on the supplied
5229 * lcid. Nice to do sometime...
5233 /* documentation for the typelib */
5235 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5236 if(pdwHelpStringContext
)
5237 *pdwHelpStringContext
=This
->dwHelpContext
;
5238 if(pbstrHelpStringDll
)
5239 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5245 /* for a typeinfo */
5246 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5248 if(SUCCEEDED(result
))
5250 ITypeInfo2
* pTInfo2
;
5251 result
= ITypeInfo_QueryInterface(pTInfo
,
5253 (LPVOID
*) &pTInfo2
);
5255 if(SUCCEEDED(result
))
5257 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5261 pdwHelpStringContext
,
5262 pbstrHelpStringDll
);
5264 ITypeInfo2_Release(pTInfo2
);
5267 ITypeInfo_Release(pTInfo
);
5273 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5275 TLBCustData
*pCData
;
5279 ct
= list_count(custdata_list
);
5281 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5282 if(!pCustData
->prgCustData
)
5283 return E_OUTOFMEMORY
;
5285 pCustData
->cCustData
= ct
;
5287 cdi
= pCustData
->prgCustData
;
5288 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5289 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5290 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5298 /* ITypeLib2::GetAllCustData
5300 * Gets all custom data items for the library.
5303 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5305 CUSTDATA
*pCustData
)
5307 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5308 TRACE("(%p)->(%p)\n", This
, pCustData
);
5309 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5312 static const ITypeLib2Vtbl tlbvt
= {
5313 ITypeLib2_fnQueryInterface
,
5315 ITypeLib2_fnRelease
,
5316 ITypeLib2_fnGetTypeInfoCount
,
5317 ITypeLib2_fnGetTypeInfo
,
5318 ITypeLib2_fnGetTypeInfoType
,
5319 ITypeLib2_fnGetTypeInfoOfGuid
,
5320 ITypeLib2_fnGetLibAttr
,
5321 ITypeLib2_fnGetTypeComp
,
5322 ITypeLib2_fnGetDocumentation
,
5324 ITypeLib2_fnFindName
,
5325 ITypeLib2_fnReleaseTLibAttr
,
5327 ITypeLib2_fnGetCustData
,
5328 ITypeLib2_fnGetLibStatistics
,
5329 ITypeLib2_fnGetDocumentation2
,
5330 ITypeLib2_fnGetAllCustData
5334 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5336 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5338 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5341 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5343 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5345 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5348 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5350 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5352 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5355 static HRESULT WINAPI
ITypeLibComp_fnBind(
5360 ITypeInfo
** ppTInfo
,
5361 DESCKIND
* pDescKind
,
5364 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5365 int typemismatch
=0, i
;
5367 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5369 *pDescKind
= DESCKIND_NONE
;
5370 pBindPtr
->lptcomp
= NULL
;
5373 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5374 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5375 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5377 /* FIXME: check wFlags here? */
5378 /* FIXME: we should use a hash table to look this info up using lHash
5379 * instead of an O(n) search */
5380 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5381 (pTypeInfo
->typekind
== TKIND_MODULE
))
5383 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5385 *pDescKind
= DESCKIND_TYPECOMP
;
5386 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5387 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5388 TRACE("module or enum: %s\n", debugstr_w(szName
));
5393 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5394 (pTypeInfo
->typekind
== TKIND_ENUM
))
5396 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5399 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5400 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5402 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5405 else if (hr
== TYPE_E_TYPEMISMATCH
)
5409 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5410 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5412 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5414 ITypeInfo
*subtypeinfo
;
5416 DESCKIND subdesckind
;
5418 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5419 &subtypeinfo
, &subdesckind
, &subbindptr
);
5420 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5422 TYPEDESC tdesc_appobject
;
5423 const VARDESC vardesc_appobject
=
5426 NULL
, /* lpstrSchema */
5441 VAR_STATIC
/* varkind */
5444 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5445 tdesc_appobject
.vt
= VT_USERDEFINED
;
5447 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5449 /* cleanup things filled in by Bind call so we can put our
5450 * application object data in there instead */
5451 switch (subdesckind
)
5453 case DESCKIND_FUNCDESC
:
5454 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5456 case DESCKIND_VARDESC
:
5457 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5462 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5464 if (pTypeInfo
->hreftype
== -1)
5465 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5467 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5471 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5472 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5473 ITypeInfo_AddRef(*ppTInfo
);
5476 else if (hr
== TYPE_E_TYPEMISMATCH
)
5483 TRACE("type mismatch %s\n", debugstr_w(szName
));
5484 return TYPE_E_TYPEMISMATCH
;
5488 TRACE("name not found %s\n", debugstr_w(szName
));
5493 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5497 ITypeInfo
** ppTInfo
,
5498 ITypeComp
** ppTComp
)
5500 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5501 ITypeInfoImpl
*info
;
5503 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5505 if(!szName
|| !ppTInfo
|| !ppTComp
)
5506 return E_INVALIDARG
;
5508 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5515 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5516 ITypeInfo_AddRef(*ppTInfo
);
5517 *ppTComp
= &info
->ITypeComp_iface
;
5518 ITypeComp_AddRef(*ppTComp
);
5523 static const ITypeCompVtbl tlbtcvt
=
5526 ITypeLibComp_fnQueryInterface
,
5527 ITypeLibComp_fnAddRef
,
5528 ITypeLibComp_fnRelease
,
5530 ITypeLibComp_fnBind
,
5531 ITypeLibComp_fnBindType
5534 /*================== ITypeInfo(2) Methods ===================================*/
5535 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5537 ITypeInfoImpl
*pTypeInfoImpl
;
5539 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5542 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5543 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5544 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5545 pTypeInfoImpl
->ref
= 0;
5546 pTypeInfoImpl
->hreftype
= -1;
5547 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5548 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5549 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5550 list_init(pTypeInfoImpl
->pcustdata_list
);
5552 TRACE("(%p)\n", pTypeInfoImpl
);
5553 return pTypeInfoImpl
;
5556 /* ITypeInfo::QueryInterface
5558 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5563 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5565 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5568 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5569 IsEqualIID(riid
,&IID_ITypeInfo
)||
5570 IsEqualIID(riid
,&IID_ITypeInfo2
))
5572 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5573 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5574 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5577 ITypeInfo2_AddRef(iface
);
5578 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5581 TRACE("-- Interface: E_NOINTERFACE\n");
5582 return E_NOINTERFACE
;
5585 /* ITypeInfo::AddRef
5587 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5589 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5590 ULONG ref
= InterlockedIncrement(&This
->ref
);
5592 TRACE("(%p)->ref is %u\n",This
, ref
);
5594 if (ref
== 1 /* incremented from 0 */)
5595 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5600 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5604 TRACE("destroying ITypeInfo(%p)\n",This
);
5606 for (i
= 0; i
< This
->cFuncs
; ++i
)
5609 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5610 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5612 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5613 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5614 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5615 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5617 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5618 heap_free(pFInfo
->pParamDesc
);
5619 TLB_FreeCustData(&pFInfo
->custdata_list
);
5621 heap_free(This
->funcdescs
);
5623 for(i
= 0; i
< This
->cVars
; ++i
)
5625 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5626 if (pVInfo
->vardesc_create
) {
5627 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5628 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5629 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5630 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5632 TLB_FreeCustData(&pVInfo
->custdata_list
);
5634 heap_free(This
->vardescs
);
5636 if(This
->impltypes
){
5637 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5638 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5639 TLB_FreeCustData(&pImpl
->custdata_list
);
5641 heap_free(This
->impltypes
);
5644 TLB_FreeCustData(&This
->custdata_list
);
5649 /* ITypeInfo::Release
5651 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5653 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5654 ULONG ref
= InterlockedDecrement(&This
->ref
);
5656 TRACE("(%p)->(%u)\n",This
, ref
);
5660 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5661 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5662 if (not_attached_to_typelib
)
5664 /* otherwise This will be freed when typelib is freed */
5670 /* ITypeInfo::GetTypeAttr
5672 * Retrieves a TYPEATTR structure that contains the attributes of the type
5676 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5677 LPTYPEATTR
*ppTypeAttr
)
5679 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5682 TRACE("(%p)\n",This
);
5684 size
= sizeof(**ppTypeAttr
);
5685 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5686 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5688 *ppTypeAttr
= heap_alloc(size
);
5690 return E_OUTOFMEMORY
;
5692 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5693 (*ppTypeAttr
)->lcid
= This
->lcid
;
5694 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5695 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5696 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5697 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5698 (*ppTypeAttr
)->typekind
= This
->typekind
;
5699 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5700 (*ppTypeAttr
)->cVars
= This
->cVars
;
5701 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5702 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5703 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5704 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5705 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5706 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5707 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5709 if (This
->tdescAlias
)
5710 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5711 This
->tdescAlias
, *ppTypeAttr
+ 1);
5713 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5714 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5717 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5718 /* This should include all the inherited funcs */
5719 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5720 /* This is always the size of IDispatch's vtbl */
5721 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5722 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5727 /* ITypeInfo::GetTypeComp
5729 * Retrieves the ITypeComp interface for the type description, which enables a
5730 * client compiler to bind to the type description's members.
5733 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5734 ITypeComp
* *ppTComp
)
5736 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5738 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5740 *ppTComp
= &This
->ITypeComp_iface
;
5741 ITypeComp_AddRef(*ppTComp
);
5745 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5747 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5748 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5749 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5753 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5756 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5757 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5759 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5760 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5761 *buffer
+= sizeof(PARAMDESCEX
);
5762 *pparamdescex_dest
= *pparamdescex_src
;
5763 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5764 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5765 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5766 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5769 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5773 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5775 UINT len
= SysStringLen(str
), i
;
5776 for (i
= 0; i
< len
; ++i
)
5782 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5784 if (V_VT(var
) == VT_INT
)
5785 return VariantChangeType(var
, var
, 0, VT_I4
);
5786 else if (V_VT(var
) == VT_UINT
)
5787 return VariantChangeType(var
, var
, 0, VT_UI4
);
5788 else if (V_VT(var
) == VT_BSTR
)
5789 return TLB_SanitizeBSTR(V_BSTR(var
));
5794 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5796 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5797 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5800 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5804 SIZE_T size
= sizeof(*src
);
5808 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5809 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5810 for (i
= 0; i
< src
->cParams
; i
++)
5812 size
+= sizeof(ELEMDESC
);
5813 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5816 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5817 if (!dest
) return E_OUTOFMEMORY
;
5820 if (dispinterface
) /* overwrite funckind */
5821 dest
->funckind
= FUNC_DISPATCH
;
5822 buffer
= (char *)(dest
+ 1);
5824 dest
->oVft
= dest
->oVft
& 0xFFFC;
5826 if (dest
->cScodes
) {
5827 dest
->lprgscode
= (SCODE
*)buffer
;
5828 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5829 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5831 dest
->lprgscode
= NULL
;
5833 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5836 SysFreeString((BSTR
)dest
);
5840 if (dest
->cParams
) {
5841 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5842 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5843 for (i
= 0; i
< src
->cParams
; i
++)
5845 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5851 /* undo the above actions */
5852 for (i
= i
- 1; i
>= 0; i
--)
5853 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5854 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5855 SysFreeString((BSTR
)dest
);
5859 dest
->lprgelemdescParam
= NULL
;
5861 /* special treatment for dispinterfaces: this makes functions appear
5862 * to return their [retval] value when it is really returning an
5864 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5866 if (dest
->cParams
&&
5867 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5869 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5870 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5872 ERR("elemdesc should have started with VT_PTR instead of:\n");
5874 dump_ELEMDESC(elemdesc
);
5875 return E_UNEXPECTED
;
5878 /* copy last parameter to the return value. we are using a flat
5879 * buffer so there is no danger of leaking memory in
5881 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5883 /* remove the last parameter */
5887 /* otherwise this function is made to appear to have no return
5889 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5897 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5899 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5900 if (var_desc
->varkind
== VAR_CONST
)
5901 VariantClear(var_desc
->u
.lpvarValue
);
5902 SysFreeString((BSTR
)var_desc
);
5905 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5907 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5909 if (index
>= This
->cFuncs
)
5910 return TYPE_E_ELEMENTNOTFOUND
;
5912 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5916 /* internal function to make the inherited interfaces' methods appear
5917 * part of the interface */
5918 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5919 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5921 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5923 UINT implemented_funcs
= 0;
5928 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5932 ITypeInfo
*pSubTypeInfo
;
5935 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5939 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5942 &sub_funcs
, hrefoffset
);
5943 implemented_funcs
+= sub_funcs
;
5944 ITypeInfo_Release(pSubTypeInfo
);
5947 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5951 *funcs
= implemented_funcs
+ This
->cFuncs
;
5955 if (index
< implemented_funcs
)
5956 return E_INVALIDARG
;
5957 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5961 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5963 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5966 switch (pTypeDesc
->vt
)
5968 case VT_USERDEFINED
:
5969 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5973 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5976 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5984 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5987 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5988 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5989 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5992 /* ITypeInfo::GetFuncDesc
5994 * Retrieves the FUNCDESC structure that contains information about a
5995 * specified function.
5998 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5999 LPFUNCDESC
*ppFuncDesc
)
6001 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6002 const FUNCDESC
*internal_funcdesc
;
6004 UINT hrefoffset
= 0;
6006 TRACE("(%p) index %d\n", This
, index
);
6009 return E_INVALIDARG
;
6011 if (This
->needs_layout
)
6012 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6014 if (This
->typekind
== TKIND_DISPATCH
)
6015 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6016 &internal_funcdesc
, NULL
,
6019 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6020 &internal_funcdesc
);
6023 WARN("description for function %d not found\n", index
);
6027 hr
= TLB_AllocAndInitFuncDesc(
6030 This
->typekind
== TKIND_DISPATCH
);
6032 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6033 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6035 TRACE("-- 0x%08x\n", hr
);
6039 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6043 SIZE_T size
= sizeof(*src
);
6046 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6047 if (src
->varkind
== VAR_CONST
)
6048 size
+= sizeof(VARIANT
);
6049 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6051 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6052 if (!dest
) return E_OUTOFMEMORY
;
6055 buffer
= (char *)(dest
+ 1);
6056 if (src
->lpstrSchema
)
6059 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6060 len
= strlenW(src
->lpstrSchema
);
6061 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6062 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6065 if (src
->varkind
== VAR_CONST
)
6069 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6070 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6071 buffer
+= sizeof(VARIANT
);
6072 VariantInit(dest
->u
.lpvarValue
);
6073 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6076 SysFreeString((BSTR
)dest
);
6080 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6083 if (src
->varkind
== VAR_CONST
)
6084 VariantClear(dest
->u
.lpvarValue
);
6085 SysFreeString((BSTR
)dest
);
6092 /* ITypeInfo::GetVarDesc
6094 * Retrieves a VARDESC structure that describes the specified variable.
6097 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6098 LPVARDESC
*ppVarDesc
)
6100 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6101 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6103 TRACE("(%p) index %d\n", This
, index
);
6105 if(index
>= This
->cVars
)
6106 return TYPE_E_ELEMENTNOTFOUND
;
6108 if (This
->needs_layout
)
6109 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6111 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6114 /* ITypeInfo_GetNames
6116 * Retrieves the variable with the specified member ID (or the name of the
6117 * property or method and its parameters) that correspond to the specified
6120 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6121 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6123 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6124 const TLBFuncDesc
*pFDesc
;
6125 const TLBVarDesc
*pVDesc
;
6127 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6130 return E_INVALIDARG
;
6134 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6137 if(!cMaxNames
|| !pFDesc
->Name
)
6140 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6143 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6144 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6146 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6152 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6155 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6160 if(This
->impltypes
&&
6161 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6162 /* recursive search */
6165 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6166 if(SUCCEEDED(result
))
6168 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6169 ITypeInfo_Release(pTInfo
);
6172 WARN("Could not search inherited interface!\n");
6176 WARN("no names found\n");
6179 return TYPE_E_ELEMENTNOTFOUND
;
6185 /* ITypeInfo::GetRefTypeOfImplType
6187 * If a type description describes a COM class, it retrieves the type
6188 * description of the implemented interface types. For an interface,
6189 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6193 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6198 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6201 TRACE("(%p) index %d\n", This
, index
);
6202 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6206 /* only valid on dual interfaces;
6207 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6210 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6216 hr
= TYPE_E_ELEMENTNOTFOUND
;
6219 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6221 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6222 *pRefType
= This
->pTypeLib
->dispatch_href
;
6226 if(index
>= This
->cImplTypes
)
6227 hr
= TYPE_E_ELEMENTNOTFOUND
;
6229 *pRefType
= This
->impltypes
[index
].hRef
;
6230 if(This
->typekind
== TKIND_INTERFACE
)
6238 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6240 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6246 /* ITypeInfo::GetImplTypeFlags
6248 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6249 * or base interface in a type description.
6251 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6252 UINT index
, INT
*pImplTypeFlags
)
6254 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6256 TRACE("(%p) index %d\n", This
, index
);
6259 return E_INVALIDARG
;
6261 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6262 *pImplTypeFlags
= 0;
6266 if(index
>= This
->cImplTypes
)
6267 return TYPE_E_ELEMENTNOTFOUND
;
6269 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6275 * Maps between member names and member IDs, and parameter names and
6278 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6279 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6281 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6282 const TLBVarDesc
*pVDesc
;
6286 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6289 /* init out parameters in case of failure */
6290 for (i
= 0; i
< cNames
; i
++)
6291 pMemId
[i
] = MEMBERID_NIL
;
6293 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6295 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6296 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6297 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6298 for(i
=1; i
< cNames
; i
++){
6299 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6300 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6302 if( j
<pFDesc
->funcdesc
.cParams
)
6305 ret
=DISP_E_UNKNOWNNAME
;
6307 TRACE("-- 0x%08x\n", ret
);
6311 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6314 *pMemId
= pVDesc
->vardesc
.memid
;
6317 /* not found, see if it can be found in an inherited interface */
6318 if(This
->impltypes
) {
6319 /* recursive search */
6321 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6323 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6324 ITypeInfo_Release(pTInfo
);
6327 WARN("Could not search inherited interface!\n");
6329 WARN("no names found\n");
6330 return DISP_E_UNKNOWNNAME
;
6336 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6337 __ASM_GLOBAL_FUNC( call_method
,
6339 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6340 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6341 "movl %esp,%ebp\n\t"
6342 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6344 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6346 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6347 "movl 12(%ebp),%edx\n\t"
6348 "movl %esp,%edi\n\t"
6351 "subl %edx,%edi\n\t"
6352 "andl $~15,%edi\n\t"
6353 "movl %edi,%esp\n\t"
6354 "movl 12(%ebp),%ecx\n\t"
6355 "movl 16(%ebp),%esi\n\t"
6358 "1:\tcall *8(%ebp)\n\t"
6359 "subl %esp,%edi\n\t"
6360 "movl 20(%ebp),%ecx\n\t"
6361 "movl %edi,(%ecx)\n\t"
6362 "leal -8(%ebp),%esp\n\t"
6364 __ASM_CFI(".cfi_same_value %edi\n\t")
6366 __ASM_CFI(".cfi_same_value %esi\n\t")
6368 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6369 __ASM_CFI(".cfi_same_value %ebp\n\t")
6372 /* same function but returning floating point */
6373 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6375 /* ITypeInfo::Invoke
6377 * Invokes a method, or accesses a property of an object, that implements the
6378 * interface described by the type description.
6381 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6385 if (TRACE_ON(ole
)) {
6387 TRACE("Calling %p(",func
);
6388 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6389 if (nrargs
> 30) TRACE("...");
6396 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6399 FIXME("unsupported calling convention %d\n",callconv
);
6403 TRACE("returns %08x\n",res
);
6407 #elif defined(__x86_64__)
6409 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6410 __ASM_GLOBAL_FUNC( call_method
,
6412 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6413 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6414 "movq %rsp,%rbp\n\t"
6415 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6417 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6419 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6420 "movq %rcx,%rax\n\t"
6423 "cmovgq %rdx,%rcx\n\t"
6424 "leaq 0(,%rcx,8),%rdx\n\t"
6425 "subq %rdx,%rsp\n\t"
6426 "andq $~15,%rsp\n\t"
6427 "movq %rsp,%rdi\n\t"
6430 "movq 0(%rsp),%rcx\n\t"
6431 "movq 8(%rsp),%rdx\n\t"
6432 "movq 16(%rsp),%r8\n\t"
6433 "movq 24(%rsp),%r9\n\t"
6434 "movq %rcx,%xmm0\n\t"
6435 "movq %rdx,%xmm1\n\t"
6436 "movq %r8,%xmm2\n\t"
6437 "movq %r9,%xmm3\n\t"
6439 "leaq -16(%rbp),%rsp\n\t"
6441 __ASM_CFI(".cfi_same_value %rdi\n\t")
6443 __ASM_CFI(".cfi_same_value %rsi\n\t")
6444 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6446 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6447 __ASM_CFI(".cfi_same_value %rbp\n\t")
6450 /* same function but returning floating point */
6451 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6453 #endif /* __x86_64__ */
6455 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6458 ITypeInfo
*tinfo2
= NULL
;
6459 TYPEATTR
*tattr
= NULL
;
6461 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6464 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6466 tdesc
->u
.hreftype
, hr
);
6469 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6472 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6473 ITypeInfo_Release(tinfo2
);
6477 switch (tattr
->typekind
)
6484 tdesc
= &tattr
->tdescAlias
;
6485 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6488 case TKIND_INTERFACE
:
6489 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6495 case TKIND_DISPATCH
:
6504 FIXME("TKIND_RECORD unhandled.\n");
6509 FIXME("TKIND_UNION unhandled.\n");
6514 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6518 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6519 ITypeInfo_Release(tinfo2
);
6523 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6527 /* enforce only one level of pointer indirection */
6528 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6530 tdesc
= tdesc
->u
.lptdesc
;
6532 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6533 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6534 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6535 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6536 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6538 VARTYPE vt_userdefined
= 0;
6539 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6540 if (tdesc
->vt
== VT_PTR
)
6542 vt_userdefined
= VT_BYREF
;
6543 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6545 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6547 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6548 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6550 *vt
|= vt_userdefined
;
6562 case VT_USERDEFINED
:
6563 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6570 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6571 hr
= DISP_E_BADVARTYPE
;
6575 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6590 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6596 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6600 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6602 ITypeInfo_Release(tinfo2
);
6606 switch(tattr
->typekind
) {
6608 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6611 case TKIND_INTERFACE
:
6612 case TKIND_DISPATCH
:
6613 *guid
= tattr
->guid
;
6617 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6618 hres
= E_UNEXPECTED
;
6621 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6622 ITypeInfo_Release(tinfo2
);
6626 /***********************************************************************
6627 * DispCallFunc (OLEAUT32.@)
6629 * Invokes a function of the specified calling convention, passing the
6630 * specified arguments and returns the result.
6633 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6634 * oVft [I] The offset in the vtable. See notes.
6635 * cc [I] Calling convention of the function to call.
6636 * vtReturn [I] The return type of the function.
6637 * cActuals [I] Number of parameters.
6638 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6639 * prgpvarg [I] The arguments to pass.
6640 * pvargResult [O] The return value of the function. Can be NULL.
6644 * Failure: HRESULT code.
6647 * The HRESULT return value of this function is not affected by the return
6648 * value of the user supplied function, which is returned in pvargResult.
6650 * If pvInstance is NULL then a non-object function is to be called and oVft
6651 * is the address of the function to call.
6653 * The cc parameter can be one of the following values:
6666 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6667 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6670 int argspos
, stack_offset
;
6675 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6676 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6677 pvargResult
, V_VT(pvargResult
));
6679 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6681 FIXME("unsupported calling convention %d\n",cc
);
6682 return E_INVALIDARG
;
6685 /* maximum size for an argument is sizeof(VARIANT) */
6686 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6688 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6692 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6693 func
= vtable
[oVft
/sizeof(void *)];
6694 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6696 else func
= (void *)oVft
;
6698 for (i
= 0; i
< cActuals
; i
++)
6700 VARIANT
*arg
= prgpvarg
[i
];
6711 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6712 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6716 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6717 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6719 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6720 args
[argspos
++] = V_BOOL(arg
);
6723 args
[argspos
++] = V_UI4(arg
);
6726 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6733 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6736 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6740 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6744 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6745 call_method( func
, argspos
, args
, &stack_offset
);
6750 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6753 WARN("invalid return type %u\n", vtReturn
);
6755 return E_INVALIDARG
;
6757 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6761 if (stack_offset
&& cc
== CC_STDCALL
)
6763 WARN( "stack pointer off by %d\n", stack_offset
);
6764 return DISP_E_BADCALLEE
;
6766 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6767 TRACE("retval: "); dump_Variant(pvargResult
);
6770 #elif defined(__x86_64__)
6776 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6777 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6778 pvargResult
, V_VT(pvargResult
));
6780 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6782 FIXME("unsupported calling convention %d\n",cc
);
6783 return E_INVALIDARG
;
6786 /* maximum size for an argument is sizeof(DWORD_PTR) */
6787 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6789 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6793 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6794 func
= vtable
[oVft
/sizeof(void *)];
6795 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6797 else func
= (void *)oVft
;
6799 for (i
= 0; i
< cActuals
; i
++)
6801 VARIANT
*arg
= prgpvarg
[i
];
6807 args
[argspos
++] = (ULONG_PTR
)arg
;
6809 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6810 args
[argspos
++] = V_BOOL(arg
);
6813 args
[argspos
++] = V_UI8(arg
);
6816 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6823 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6827 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6831 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6832 call_method( func
, argspos
, args
);
6835 WARN("invalid return type %u\n", vtReturn
);
6837 return E_INVALIDARG
;
6839 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6843 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6844 TRACE("retval: "); dump_Variant(pvargResult
);
6848 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6849 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6854 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6856 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6859 #define INVBUF_ELEMENT_SIZE \
6860 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6861 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6862 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6863 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6864 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6865 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6866 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6867 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6869 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6874 DISPPARAMS
*pDispParams
,
6875 VARIANT
*pVarResult
,
6876 EXCEPINFO
*pExcepInfo
,
6879 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6881 unsigned int var_index
;
6884 const TLBFuncDesc
*pFuncInfo
;
6887 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6888 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6891 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6892 return DISP_E_MEMBERNOTFOUND
;
6896 ERR("NULL pDispParams not allowed\n");
6897 return E_INVALIDARG
;
6900 dump_DispParms(pDispParams
);
6902 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6904 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6905 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6906 return E_INVALIDARG
;
6909 /* we do this instead of using GetFuncDesc since it will return a fake
6910 * FUNCDESC for dispinterfaces and we want the real function description */
6911 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6912 pFuncInfo
= &This
->funcdescs
[fdc
];
6913 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6914 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6915 !func_restricted( &pFuncInfo
->funcdesc
))
6919 if (fdc
< This
->cFuncs
) {
6920 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6924 TRACE("invoking:\n");
6925 dump_TLBFuncDescOne(pFuncInfo
);
6928 switch (func_desc
->funckind
) {
6929 case FUNC_PUREVIRTUAL
:
6930 case FUNC_VIRTUAL
: {
6931 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6933 VARIANT retval
; /* pointer for storing byref retvals in */
6934 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6935 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6936 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6937 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6938 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6939 UINT vargs_converted
=0;
6943 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6945 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6947 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6948 hres
= DISP_E_PARAMNOTFOUND
;
6953 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6955 ERR("functions with the vararg attribute do not support named arguments\n");
6956 hres
= DISP_E_NONAMEDARGS
;
6960 for (i
= 0; i
< func_desc
->cParams
; i
++)
6962 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6963 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6968 TRACE("changing args\n");
6969 for (i
= 0; i
< func_desc
->cParams
; i
++)
6971 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6972 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6973 VARIANTARG
*src_arg
;
6975 if (wParamFlags
& PARAMFLAG_FLCID
)
6978 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6980 V_I4(arg
) = This
->pTypeLib
->lcid
;
6989 for (j
= 0; j
< cNamedArgs
; j
++)
6990 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6992 src_arg
= &pDispParams
->rgvarg
[j
];
6997 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6999 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7003 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7005 /* under most conditions the caller is not allowed to
7006 * pass in a dispparam arg in the index of what would be
7007 * the retval parameter. however, there is an exception
7008 * where the extra parameter is used in an extra
7009 * IDispatch::Invoke below */
7010 if ((i
< pDispParams
->cArgs
) &&
7011 ((func_desc
->cParams
!= 1) || !pVarResult
||
7012 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7014 hres
= DISP_E_BADPARAMCOUNT
;
7018 /* note: this check is placed so that if the caller passes
7019 * in a VARIANTARG for the retval we just ignore it, like
7021 if (i
== func_desc
->cParams
- 1)
7024 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7025 memset(arg
, 0, sizeof(*arg
));
7026 V_VT(arg
) = rgvt
[i
];
7027 memset(&retval
, 0, sizeof(retval
));
7028 V_BYREF(arg
) = &retval
;
7032 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7033 hres
= E_UNEXPECTED
;
7039 dump_Variant(src_arg
);
7041 if(rgvt
[i
]!=V_VT(src_arg
))
7043 if (rgvt
[i
] == VT_VARIANT
)
7044 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7045 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7047 if (rgvt
[i
] == V_VT(src_arg
))
7048 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7051 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7052 if (wParamFlags
& PARAMFLAG_FIN
)
7053 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7054 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7056 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7058 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7061 SAFEARRAYBOUND bound
;
7065 bound
.cElements
= pDispParams
->cArgs
-i
;
7066 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7068 ERR("SafeArrayCreate failed\n");
7071 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7074 ERR("SafeArrayAccessData failed with %x\n", hres
);
7075 SafeArrayDestroy(a
);
7078 for (j
= 0; j
< bound
.cElements
; j
++)
7079 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7080 hres
= SafeArrayUnaccessData(a
);
7083 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7084 SafeArrayDestroy(a
);
7087 V_ARRAY(&rgvarg
[i
]) = a
;
7088 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7090 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7092 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7093 if (wParamFlags
& PARAMFLAG_FIN
)
7094 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7096 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7097 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7098 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7100 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7102 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7103 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7107 /* FIXME: this doesn't work for VT_BYREF arguments if
7108 * they are not the same type as in the paramdesc */
7109 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7110 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7111 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7116 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
7117 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
7118 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
7121 prgpvarg
[i
] = &rgvarg
[i
];
7125 prgpvarg
[i
] = src_arg
;
7128 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7129 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7130 && V_UNKNOWN(prgpvarg
[i
])) {
7131 IUnknown
*userdefined_iface
;
7134 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7138 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7140 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7144 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7145 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7148 else if (wParamFlags
& PARAMFLAG_FOPT
)
7151 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7152 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7154 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7160 VARIANTARG
*missing_arg
;
7161 /* if the function wants a pointer to a variant then
7162 * set that up, otherwise just pass the VT_ERROR in
7163 * the argument by value */
7164 if (rgvt
[i
] & VT_BYREF
)
7166 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7167 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7168 V_VARIANTREF(arg
) = missing_arg
;
7172 V_VT(missing_arg
) = VT_ERROR
;
7173 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7178 hres
= DISP_E_BADPARAMCOUNT
;
7182 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7184 /* VT_VOID is a special case for return types, so it is not
7185 * handled in the general function */
7186 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7187 V_VT(&varresult
) = VT_EMPTY
;
7190 V_VT(&varresult
) = 0;
7191 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7192 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7195 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7196 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7197 prgpvarg
, &varresult
);
7199 vargs_converted
= 0;
7201 for (i
= 0; i
< func_desc
->cParams
; i
++)
7203 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7204 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7206 if (wParamFlags
& PARAMFLAG_FLCID
)
7208 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7212 TRACE("[retval] value: ");
7213 dump_Variant(prgpvarg
[i
]);
7218 VariantInit(pVarResult
);
7219 /* deref return value */
7220 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7223 VARIANT_ClearInd(prgpvarg
[i
]);
7225 else if (vargs_converted
< pDispParams
->cArgs
)
7227 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7228 if (wParamFlags
& PARAMFLAG_FOUT
)
7230 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7232 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7236 ERR("failed to convert param %d to vt %d\n", i
,
7237 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7242 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7243 func_desc
->cParamsOpt
< 0 &&
7244 i
== func_desc
->cParams
-1)
7246 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7249 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7252 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7255 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7258 ERR("SafeArrayAccessData failed with %x\n", hres
);
7261 for (j
= 0; j
<= ubound
; j
++)
7262 VariantClear(&v
[j
]);
7263 hres
= SafeArrayUnaccessData(a
);
7266 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7270 VariantClear(&rgvarg
[i
]);
7273 else if (wParamFlags
& PARAMFLAG_FOPT
)
7275 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7276 VariantClear(&rgvarg
[i
]);
7279 VariantClear(&missing_arg
[i
]);
7282 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7284 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7285 hres
= DISP_E_EXCEPTION
;
7288 IErrorInfo
*pErrorInfo
;
7289 pExcepInfo
->scode
= V_ERROR(&varresult
);
7290 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7292 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7293 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7294 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7295 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7297 IErrorInfo_Release(pErrorInfo
);
7301 if (V_VT(&varresult
) != VT_ERROR
)
7303 TRACE("varresult value: ");
7304 dump_Variant(&varresult
);
7308 VariantClear(pVarResult
);
7309 *pVarResult
= varresult
;
7312 VariantClear(&varresult
);
7315 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7316 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7317 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7318 (pDispParams
->cArgs
!= 0))
7320 if (V_VT(pVarResult
) == VT_DISPATCH
)
7322 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7323 /* Note: not VariantClear; we still need the dispatch
7324 * pointer to be valid */
7325 VariantInit(pVarResult
);
7326 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7327 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7328 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7329 IDispatch_Release(pDispatch
);
7333 VariantClear(pVarResult
);
7334 hres
= DISP_E_NOTACOLLECTION
;
7342 case FUNC_DISPATCH
: {
7345 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7346 if (SUCCEEDED(hres
)) {
7347 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7348 hres
= IDispatch_Invoke(
7349 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7350 pVarResult
,pExcepInfo
,pArgErr
7353 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7354 IDispatch_Release(disp
);
7356 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7360 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7365 TRACE("-- 0x%08x\n", hres
);
7368 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7371 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7372 if(FAILED(hres
)) return hres
;
7374 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7375 dump_VARDESC(var_desc
);
7376 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7380 /* not found, look for it in inherited interfaces */
7381 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7382 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7383 if(This
->impltypes
) {
7384 /* recursive search */
7386 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7387 if(SUCCEEDED(hres
)){
7388 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7389 ITypeInfo_Release(pTInfo
);
7392 WARN("Could not search inherited interface!\n");
7395 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7396 return DISP_E_MEMBERNOTFOUND
;
7399 /* ITypeInfo::GetDocumentation
7401 * Retrieves the documentation string, the complete Help file name and path,
7402 * and the context ID for the Help topic for a specified type description.
7404 * (Can be tested by the Visual Basic Editor in Word for instance.)
7406 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7407 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7408 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7410 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7411 const TLBFuncDesc
*pFDesc
;
7412 const TLBVarDesc
*pVDesc
;
7413 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7414 " HelpContext(%p) HelpFile(%p)\n",
7415 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7416 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7418 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7420 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7422 *pdwHelpContext
=This
->dwHelpContext
;
7424 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7426 }else {/* for a member */
7427 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7430 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7432 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7434 *pdwHelpContext
=pFDesc
->helpcontext
;
7436 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7439 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7442 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7444 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7446 *pdwHelpContext
=pVDesc
->HelpContext
;
7448 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7453 if(This
->impltypes
&&
7454 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7455 /* recursive search */
7458 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7459 if(SUCCEEDED(result
)) {
7460 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7461 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7462 ITypeInfo_Release(pTInfo
);
7465 WARN("Could not search inherited interface!\n");
7468 WARN("member %d not found\n", memid
);
7469 return TYPE_E_ELEMENTNOTFOUND
;
7472 /* ITypeInfo::GetDllEntry
7474 * Retrieves a description or specification of an entry point for a function
7477 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7478 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7481 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7482 const TLBFuncDesc
*pFDesc
;
7484 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7486 if (pBstrDllName
) *pBstrDllName
= NULL
;
7487 if (pBstrName
) *pBstrName
= NULL
;
7488 if (pwOrdinal
) *pwOrdinal
= 0;
7490 if (This
->typekind
!= TKIND_MODULE
)
7491 return TYPE_E_BADMODULEKIND
;
7493 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7495 dump_TypeInfo(This
);
7497 dump_TLBFuncDescOne(pFDesc
);
7500 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7502 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7504 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7512 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7515 return TYPE_E_ELEMENTNOTFOUND
;
7518 /* internal function to make the inherited interfaces' methods appear
7519 * part of the interface */
7520 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7521 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7523 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7526 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7528 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7530 ITypeInfo
*pSubTypeInfo
;
7532 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7536 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7538 ITypeInfo_Release(pSubTypeInfo
);
7542 *hRefType
-= DISPATCH_HREF_OFFSET
;
7544 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7545 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7550 /* ITypeInfo::GetRefTypeInfo
7552 * If a type description references other type descriptions, it retrieves
7553 * the referenced type descriptions.
7555 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7558 ITypeInfo
**ppTInfo
)
7560 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7561 HRESULT result
= E_FAIL
;
7564 return E_INVALIDARG
;
7566 if ((INT
)hRefType
< 0) {
7567 ITypeInfoImpl
*pTypeInfoImpl
;
7569 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7570 !(This
->typekind
== TKIND_INTERFACE
||
7571 This
->typekind
== TKIND_DISPATCH
))
7572 return TYPE_E_ELEMENTNOTFOUND
;
7574 /* when we meet a DUAL typeinfo, we must create the alternate
7577 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7579 *pTypeInfoImpl
= *This
;
7580 pTypeInfoImpl
->ref
= 0;
7581 list_init(&pTypeInfoImpl
->custdata_list
);
7583 if (This
->typekind
== TKIND_INTERFACE
)
7584 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7586 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7588 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7589 /* the AddRef implicitly adds a reference to the parent typelib, which
7590 * stops the copied data from being destroyed until the new typeinfo's
7591 * refcount goes to zero, but we need to signal to the new instance to
7592 * not free its data structures when it is destroyed */
7593 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7595 ITypeInfo_AddRef(*ppTInfo
);
7598 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7599 (This
->typekind
== TKIND_DISPATCH
))
7601 HREFTYPE href_dispatch
= hRefType
;
7602 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7604 TLBRefType
*ref_type
;
7605 ITypeLib
*pTLib
= NULL
;
7608 if(!(hRefType
& 0x1)){
7609 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7611 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7614 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7615 ITypeInfo_AddRef(*ppTInfo
);
7621 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7623 if(ref_type
->reference
== (hRefType
& (~0x3)))
7626 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7628 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7632 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7634 TRACE("internal reference\n");
7635 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7637 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7638 TRACE("typeinfo in imported typelib that is already loaded\n");
7639 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7640 ITypeLib_AddRef(pTLib
);
7645 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7647 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7648 ref_type
->pImpTLInfo
->wVersionMajor
,
7649 ref_type
->pImpTLInfo
->wVersionMinor
,
7650 This
->pTypeLib
->syskind
,
7651 ref_type
->pImpTLInfo
->lcid
, &libnam
);
7653 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7655 result
= LoadTypeLib(libnam
, &pTLib
);
7656 SysFreeString(libnam
);
7658 if(SUCCEEDED(result
)) {
7659 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7660 ITypeLib_AddRef(pTLib
);
7664 if(SUCCEEDED(result
)) {
7665 if(ref_type
->index
== TLB_REF_USE_GUID
)
7666 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7668 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7671 ITypeLib_Release(pTLib
);
7675 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7676 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7680 /* ITypeInfo::AddressOfMember
7682 * Retrieves the addresses of static functions or variables, such as those
7685 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7686 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7688 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7694 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7696 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7700 module
= LoadLibraryW(dll
);
7703 ERR("couldn't load %s\n", debugstr_w(dll
));
7705 SysFreeString(entry
);
7706 return STG_E_FILENOTFOUND
;
7708 /* FIXME: store library somewhere where we can free it */
7713 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7714 entryA
= heap_alloc(len
);
7715 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7717 *ppv
= GetProcAddress(module
, entryA
);
7719 ERR("function not found %s\n", debugstr_a(entryA
));
7725 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7727 ERR("function not found %d\n", ordinal
);
7731 SysFreeString(entry
);
7734 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7739 /* ITypeInfo::CreateInstance
7741 * Creates a new instance of a type that describes a component object class
7744 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7745 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7747 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7751 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7757 WARN("Not able to aggregate\n");
7758 return CLASS_E_NOAGGREGATION
;
7761 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7762 if(FAILED(hr
)) return hr
;
7764 if(pTA
->typekind
!= TKIND_COCLASS
)
7766 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7772 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7775 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7776 TRACE("GetActiveObject rets %08x\n", hr
);
7779 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7780 IUnknown_Release(pUnk
);
7785 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7786 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7790 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7794 /* ITypeInfo::GetMops
7796 * Retrieves marshalling information.
7798 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7801 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7802 FIXME("(%p %d) stub!\n", This
, memid
);
7807 /* ITypeInfo::GetContainingTypeLib
7809 * Retrieves the containing type library and the index of the type description
7810 * within that type library.
7812 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7813 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7815 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7817 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7819 *pIndex
=This
->index
;
7820 TRACE("returning pIndex=%d\n", *pIndex
);
7824 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7825 ITypeLib_AddRef(*ppTLib
);
7826 TRACE("returning ppTLib=%p\n", *ppTLib
);
7832 /* ITypeInfo::ReleaseTypeAttr
7834 * Releases a TYPEATTR previously returned by Get
7837 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7838 TYPEATTR
* pTypeAttr
)
7840 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7841 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7842 heap_free(pTypeAttr
);
7845 /* ITypeInfo::ReleaseFuncDesc
7847 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7849 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7851 FUNCDESC
*pFuncDesc
)
7853 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7856 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7858 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7859 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7860 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7862 SysFreeString((BSTR
)pFuncDesc
);
7865 /* ITypeInfo::ReleaseVarDesc
7867 * Releases a VARDESC previously returned by GetVarDesc.
7869 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7872 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7873 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7875 TLB_FreeVarDesc(pVarDesc
);
7878 /* ITypeInfo2::GetTypeKind
7880 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7883 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7884 TYPEKIND
*pTypeKind
)
7886 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7887 *pTypeKind
=This
->typekind
;
7888 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7892 /* ITypeInfo2::GetTypeFlags
7894 * Returns the type flags without any allocations. This returns a DWORD type
7895 * flag, which expands the type flags without growing the TYPEATTR (type
7899 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7901 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7902 *pTypeFlags
=This
->wTypeFlags
;
7903 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7907 /* ITypeInfo2::GetFuncIndexOfMemId
7908 * Binds to a specific member based on a known DISPID, where the member name
7909 * is not known (for example, when binding to a default member).
7912 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7913 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7915 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7919 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7920 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7921 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7924 if(fdc
< This
->cFuncs
) {
7928 result
= TYPE_E_ELEMENTNOTFOUND
;
7930 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7931 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7935 /* TypeInfo2::GetVarIndexOfMemId
7937 * Binds to a specific member based on a known DISPID, where the member name
7938 * is not known (for example, when binding to a default member).
7941 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7942 MEMBERID memid
, UINT
*pVarIndex
)
7944 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7945 TLBVarDesc
*pVarInfo
;
7947 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7949 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7951 return TYPE_E_ELEMENTNOTFOUND
;
7953 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7958 /* ITypeInfo2::GetCustData
7960 * Gets the custom data
7962 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7967 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7968 TLBCustData
*pCData
;
7970 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7972 if(!guid
|| !pVarVal
)
7973 return E_INVALIDARG
;
7975 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
7977 VariantInit( pVarVal
);
7979 VariantCopy( pVarVal
, &pCData
->data
);
7981 VariantClear( pVarVal
);
7985 /* ITypeInfo2::GetFuncCustData
7987 * Gets the custom data
7989 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7995 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7996 TLBCustData
*pCData
;
7997 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7999 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8001 if(index
>= This
->cFuncs
)
8002 return TYPE_E_ELEMENTNOTFOUND
;
8004 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8006 return TYPE_E_ELEMENTNOTFOUND
;
8008 VariantInit(pVarVal
);
8009 VariantCopy(pVarVal
, &pCData
->data
);
8014 /* ITypeInfo2::GetParamCustData
8016 * Gets the custom data
8018 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8025 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8026 TLBCustData
*pCData
;
8027 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8029 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8030 debugstr_guid(guid
), pVarVal
);
8032 if(indexFunc
>= This
->cFuncs
)
8033 return TYPE_E_ELEMENTNOTFOUND
;
8035 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8036 return TYPE_E_ELEMENTNOTFOUND
;
8038 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8040 return TYPE_E_ELEMENTNOTFOUND
;
8042 VariantInit(pVarVal
);
8043 VariantCopy(pVarVal
, &pCData
->data
);
8048 /* ITypeInfo2::GetVarCustData
8050 * Gets the custom data
8052 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8058 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8059 TLBCustData
*pCData
;
8060 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8062 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8064 if(index
>= This
->cVars
)
8065 return TYPE_E_ELEMENTNOTFOUND
;
8067 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8069 return TYPE_E_ELEMENTNOTFOUND
;
8071 VariantInit(pVarVal
);
8072 VariantCopy(pVarVal
, &pCData
->data
);
8077 /* ITypeInfo2::GetImplCustData
8079 * Gets the custom data
8081 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8087 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8088 TLBCustData
*pCData
;
8089 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8091 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8093 if(index
>= This
->cImplTypes
)
8094 return TYPE_E_ELEMENTNOTFOUND
;
8096 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8098 return TYPE_E_ELEMENTNOTFOUND
;
8100 VariantInit(pVarVal
);
8101 VariantCopy(pVarVal
, &pCData
->data
);
8106 /* ITypeInfo2::GetDocumentation2
8108 * Retrieves the documentation string, the complete Help file name and path,
8109 * the localization context to use, and the context ID for the library Help
8110 * topic in the Help file.
8113 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8117 BSTR
*pbstrHelpString
,
8118 DWORD
*pdwHelpStringContext
,
8119 BSTR
*pbstrHelpStringDll
)
8121 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8122 const TLBFuncDesc
*pFDesc
;
8123 const TLBVarDesc
*pVDesc
;
8124 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8125 "HelpStringContext(%p) HelpStringDll(%p)\n",
8126 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8127 pbstrHelpStringDll
);
8128 /* the help string should be obtained from the helpstringdll,
8129 * using the _DLLGetDocumentation function, based on the supplied
8130 * lcid. Nice to do sometime...
8132 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8134 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8135 if(pdwHelpStringContext
)
8136 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8137 if(pbstrHelpStringDll
)
8138 *pbstrHelpStringDll
=
8139 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8141 }else {/* for a member */
8142 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8145 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8146 if(pdwHelpStringContext
)
8147 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8148 if(pbstrHelpStringDll
)
8149 *pbstrHelpStringDll
=
8150 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8153 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8156 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8157 if(pdwHelpStringContext
)
8158 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8159 if(pbstrHelpStringDll
)
8160 *pbstrHelpStringDll
=
8161 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8165 return TYPE_E_ELEMENTNOTFOUND
;
8168 /* ITypeInfo2::GetAllCustData
8170 * Gets all custom data items for the Type info.
8173 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8175 CUSTDATA
*pCustData
)
8177 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8179 TRACE("%p %p\n", This
, pCustData
);
8181 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8184 /* ITypeInfo2::GetAllFuncCustData
8186 * Gets all custom data items for the specified Function
8189 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8192 CUSTDATA
*pCustData
)
8194 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8195 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8197 TRACE("%p %u %p\n", This
, index
, pCustData
);
8199 if(index
>= This
->cFuncs
)
8200 return TYPE_E_ELEMENTNOTFOUND
;
8202 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8205 /* ITypeInfo2::GetAllParamCustData
8207 * Gets all custom data items for the Functions
8210 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8211 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8213 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8214 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8216 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8218 if(indexFunc
>= This
->cFuncs
)
8219 return TYPE_E_ELEMENTNOTFOUND
;
8221 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8222 return TYPE_E_ELEMENTNOTFOUND
;
8224 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8227 /* ITypeInfo2::GetAllVarCustData
8229 * Gets all custom data items for the specified Variable
8232 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8233 UINT index
, CUSTDATA
*pCustData
)
8235 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8236 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8238 TRACE("%p %u %p\n", This
, index
, pCustData
);
8240 if(index
>= This
->cVars
)
8241 return TYPE_E_ELEMENTNOTFOUND
;
8243 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8246 /* ITypeInfo2::GetAllImplCustData
8248 * Gets all custom data items for the specified implementation type
8251 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8254 CUSTDATA
*pCustData
)
8256 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8257 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8259 TRACE("%p %u %p\n", This
, index
, pCustData
);
8261 if(index
>= This
->cImplTypes
)
8262 return TYPE_E_ELEMENTNOTFOUND
;
8264 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8267 static const ITypeInfo2Vtbl tinfvt
=
8270 ITypeInfo_fnQueryInterface
,
8272 ITypeInfo_fnRelease
,
8274 ITypeInfo_fnGetTypeAttr
,
8275 ITypeInfo_fnGetTypeComp
,
8276 ITypeInfo_fnGetFuncDesc
,
8277 ITypeInfo_fnGetVarDesc
,
8278 ITypeInfo_fnGetNames
,
8279 ITypeInfo_fnGetRefTypeOfImplType
,
8280 ITypeInfo_fnGetImplTypeFlags
,
8281 ITypeInfo_fnGetIDsOfNames
,
8283 ITypeInfo_fnGetDocumentation
,
8284 ITypeInfo_fnGetDllEntry
,
8285 ITypeInfo_fnGetRefTypeInfo
,
8286 ITypeInfo_fnAddressOfMember
,
8287 ITypeInfo_fnCreateInstance
,
8288 ITypeInfo_fnGetMops
,
8289 ITypeInfo_fnGetContainingTypeLib
,
8290 ITypeInfo_fnReleaseTypeAttr
,
8291 ITypeInfo_fnReleaseFuncDesc
,
8292 ITypeInfo_fnReleaseVarDesc
,
8294 ITypeInfo2_fnGetTypeKind
,
8295 ITypeInfo2_fnGetTypeFlags
,
8296 ITypeInfo2_fnGetFuncIndexOfMemId
,
8297 ITypeInfo2_fnGetVarIndexOfMemId
,
8298 ITypeInfo2_fnGetCustData
,
8299 ITypeInfo2_fnGetFuncCustData
,
8300 ITypeInfo2_fnGetParamCustData
,
8301 ITypeInfo2_fnGetVarCustData
,
8302 ITypeInfo2_fnGetImplTypeCustData
,
8303 ITypeInfo2_fnGetDocumentation2
,
8304 ITypeInfo2_fnGetAllCustData
,
8305 ITypeInfo2_fnGetAllFuncCustData
,
8306 ITypeInfo2_fnGetAllParamCustData
,
8307 ITypeInfo2_fnGetAllVarCustData
,
8308 ITypeInfo2_fnGetAllImplTypeCustData
,
8311 /******************************************************************************
8312 * CreateDispTypeInfo [OLEAUT32.31]
8314 * Build type information for an object so it can be called through an
8315 * IDispatch interface.
8318 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8319 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8322 * This call allows an objects methods to be accessed through IDispatch, by
8323 * building an ITypeInfo object that IDispatch can use to call through.
8325 HRESULT WINAPI
CreateDispTypeInfo(
8326 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8327 LCID lcid
, /* [I] Locale Id */
8328 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8330 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8331 ITypeLibImpl
*pTypeLibImpl
;
8332 unsigned int param
, func
;
8333 TLBFuncDesc
*pFuncDesc
;
8337 pTypeLibImpl
= TypeLibImpl_Constructor();
8338 if (!pTypeLibImpl
) return E_FAIL
;
8340 pTypeLibImpl
->TypeInfoCount
= 2;
8341 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8343 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8344 pTIIface
->pTypeLib
= pTypeLibImpl
;
8345 pTIIface
->index
= 0;
8346 pTIIface
->Name
= NULL
;
8347 pTIIface
->dwHelpContext
= -1;
8348 pTIIface
->guid
= NULL
;
8349 pTIIface
->lcid
= lcid
;
8350 pTIIface
->typekind
= TKIND_INTERFACE
;
8351 pTIIface
->wMajorVerNum
= 0;
8352 pTIIface
->wMinorVerNum
= 0;
8353 pTIIface
->cbAlignment
= 2;
8354 pTIIface
->cbSizeInstance
= -1;
8355 pTIIface
->cbSizeVft
= -1;
8356 pTIIface
->cFuncs
= 0;
8357 pTIIface
->cImplTypes
= 0;
8358 pTIIface
->cVars
= 0;
8359 pTIIface
->wTypeFlags
= 0;
8360 pTIIface
->hreftype
= 0;
8362 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8363 pFuncDesc
= pTIIface
->funcdescs
;
8364 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8365 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8366 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8367 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8368 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8369 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8370 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8371 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8372 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8373 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8374 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8375 pFuncDesc
->funcdesc
.cScodes
= 0;
8376 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8377 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8378 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8379 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8380 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8381 md
->cArgs
* sizeof(ELEMDESC
));
8382 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8383 for(param
= 0; param
< md
->cArgs
; param
++) {
8384 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8385 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8387 pFuncDesc
->helpcontext
= 0;
8388 pFuncDesc
->HelpStringContext
= 0;
8389 pFuncDesc
->HelpString
= NULL
;
8390 pFuncDesc
->Entry
= NULL
;
8391 list_init(&pFuncDesc
->custdata_list
);
8396 dump_TypeInfo(pTIIface
);
8398 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8399 pTIClass
->pTypeLib
= pTypeLibImpl
;
8400 pTIClass
->index
= 1;
8401 pTIClass
->Name
= NULL
;
8402 pTIClass
->dwHelpContext
= -1;
8403 pTIClass
->guid
= NULL
;
8404 pTIClass
->lcid
= lcid
;
8405 pTIClass
->typekind
= TKIND_COCLASS
;
8406 pTIClass
->wMajorVerNum
= 0;
8407 pTIClass
->wMinorVerNum
= 0;
8408 pTIClass
->cbAlignment
= 2;
8409 pTIClass
->cbSizeInstance
= -1;
8410 pTIClass
->cbSizeVft
= -1;
8411 pTIClass
->cFuncs
= 0;
8412 pTIClass
->cImplTypes
= 1;
8413 pTIClass
->cVars
= 0;
8414 pTIClass
->wTypeFlags
= 0;
8415 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8417 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8419 ref
= heap_alloc_zero(sizeof(*ref
));
8420 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8421 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8423 dump_TypeInfo(pTIClass
);
8425 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8427 ITypeInfo_AddRef(*pptinfo
);
8428 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8434 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8436 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8438 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8441 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8443 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8445 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8448 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8450 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8452 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8455 static HRESULT WINAPI
ITypeComp_fnBind(
8460 ITypeInfo
** ppTInfo
,
8461 DESCKIND
* pDescKind
,
8464 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8465 const TLBFuncDesc
*pFDesc
;
8466 const TLBVarDesc
*pVDesc
;
8467 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8470 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8472 *pDescKind
= DESCKIND_NONE
;
8473 pBindPtr
->lpfuncdesc
= NULL
;
8476 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8477 pFDesc
= &This
->funcdescs
[fdc
];
8478 if (!strcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8479 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8482 /* name found, but wrong flags */
8483 hr
= TYPE_E_TYPEMISMATCH
;
8487 if (fdc
< This
->cFuncs
)
8489 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8491 &pBindPtr
->lpfuncdesc
,
8492 This
->typekind
== TKIND_DISPATCH
);
8495 *pDescKind
= DESCKIND_FUNCDESC
;
8496 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8497 ITypeInfo_AddRef(*ppTInfo
);
8500 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8502 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8505 *pDescKind
= DESCKIND_VARDESC
;
8506 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8507 ITypeInfo_AddRef(*ppTInfo
);
8511 /* FIXME: search each inherited interface, not just the first */
8512 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8513 /* recursive search */
8517 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8520 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8521 ITypeInfo_Release(pTInfo
);
8525 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8526 ITypeComp_Release(pTComp
);
8529 WARN("Could not search inherited interface!\n");
8531 if (hr
== DISP_E_MEMBERNOTFOUND
)
8533 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8537 static HRESULT WINAPI
ITypeComp_fnBindType(
8541 ITypeInfo
** ppTInfo
,
8542 ITypeComp
** ppTComp
)
8544 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8546 /* strange behaviour (does nothing) but like the
8549 if (!ppTInfo
|| !ppTComp
)
8558 static const ITypeCompVtbl tcompvt
=
8561 ITypeComp_fnQueryInterface
,
8563 ITypeComp_fnRelease
,
8566 ITypeComp_fnBindType
8569 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8570 ICreateTypeLib2
** ppctlib
)
8575 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8577 if (!szFile
) return E_INVALIDARG
;
8579 This
= TypeLibImpl_Constructor();
8581 return E_OUTOFMEMORY
;
8583 This
->lcid
= GetSystemDefaultLCID();
8584 This
->syskind
= syskind
;
8585 This
->ptr_size
= get_ptr_size(syskind
);
8587 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8589 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8590 return E_OUTOFMEMORY
;
8592 lstrcpyW(This
->path
, szFile
);
8594 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8595 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8599 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8600 REFIID riid
, void **object
)
8602 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8604 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8607 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8609 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8611 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8614 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8616 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8618 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8621 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8622 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8624 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8625 ITypeInfoImpl
*info
;
8628 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8630 if (!ctinfo
|| !name
)
8631 return E_INVALIDARG
;
8633 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8635 return TYPE_E_NAMECONFLICT
;
8637 if (This
->typeinfos
)
8638 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8639 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8641 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8643 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8645 info
->pTypeLib
= This
;
8646 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8647 info
->index
= This
->TypeInfoCount
;
8648 info
->typekind
= kind
;
8649 info
->cbAlignment
= 4;
8651 switch(info
->typekind
) {
8653 case TKIND_INTERFACE
:
8654 case TKIND_DISPATCH
:
8656 info
->cbSizeInstance
= This
->ptr_size
;
8660 info
->cbSizeInstance
= 0;
8663 info
->cbSizeInstance
= 2;
8666 info
->cbSizeInstance
= -0x75;
8669 FIXME("unrecognized typekind %d\n", info
->typekind
);
8670 info
->cbSizeInstance
= 0xdeadbeef;
8674 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8675 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8677 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8681 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8683 ++This
->TypeInfoCount
;
8688 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8691 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8693 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8696 return E_INVALIDARG
;
8698 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8703 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8704 WORD majorVerNum
, WORD minorVerNum
)
8706 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8708 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8710 This
->ver_major
= majorVerNum
;
8711 This
->ver_minor
= minorVerNum
;
8716 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8719 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8721 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8723 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8728 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8731 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8733 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8736 return E_INVALIDARG
;
8738 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8743 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8744 LPOLESTR helpFileName
)
8746 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8748 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8751 return E_INVALIDARG
;
8753 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8758 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8761 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8763 TRACE("%p %d\n", This
, helpContext
);
8765 This
->dwHelpContext
= helpContext
;
8770 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8773 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8775 TRACE("%p %x\n", This
, lcid
);
8777 This
->set_lcid
= lcid
;
8782 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8785 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8787 TRACE("%p %x\n", This
, libFlags
);
8789 This
->libflags
= libFlags
;
8794 typedef struct tagWMSFT_SegContents
{
8797 } WMSFT_SegContents
;
8799 typedef struct tagWMSFT_TLBFile
{
8801 WMSFT_SegContents typeinfo_seg
;
8802 WMSFT_SegContents impfile_seg
;
8803 WMSFT_SegContents impinfo_seg
;
8804 WMSFT_SegContents ref_seg
;
8805 WMSFT_SegContents guidhash_seg
;
8806 WMSFT_SegContents guid_seg
;
8807 WMSFT_SegContents namehash_seg
;
8808 WMSFT_SegContents name_seg
;
8809 WMSFT_SegContents string_seg
;
8810 WMSFT_SegContents typdesc_seg
;
8811 WMSFT_SegContents arraydesc_seg
;
8812 WMSFT_SegContents custdata_seg
;
8813 WMSFT_SegContents cdguids_seg
;
8815 WMSFT_SegContents aux_seg
;
8818 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8819 WMSFT_TLBFile
*file
)
8825 file
->string_seg
.len
= 0;
8826 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8829 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8831 return E_UNEXPECTED
;
8833 size
+= sizeof(INT16
);
8835 size
= (size
+ 4) & ~0x3;
8839 file
->string_seg
.len
+= size
;
8841 /* temporarily use str->offset to store the length of the aligned,
8842 * converted string */
8846 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8849 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8852 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8853 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8855 heap_free(file
->string_seg
.data
);
8856 return E_UNEXPECTED
;
8859 *((INT16
*)data
) = size
;
8861 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8865 str
->offset
= last_offs
;
8872 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8873 WMSFT_TLBFile
*file
)
8878 MSFT_NameIntro
*last_intro
= NULL
;
8880 file
->header
.nametablecount
= 0;
8881 file
->header
.nametablechars
= 0;
8883 file
->name_seg
.len
= 0;
8884 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8887 size
= strlenW(str
->str
);
8888 file
->header
.nametablechars
+= size
;
8889 file
->header
.nametablecount
++;
8891 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8893 return E_UNEXPECTED
;
8895 size
+= sizeof(MSFT_NameIntro
);
8897 size
= (size
+ 4) & ~0x3;
8901 file
->name_seg
.len
+= size
;
8903 /* temporarily use str->offset to store the length of the aligned,
8904 * converted string */
8908 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8909 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8912 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8914 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8916 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8917 data
+ sizeof(MSFT_NameIntro
),
8918 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8920 heap_free(file
->name_seg
.data
);
8921 return E_UNEXPECTED
;
8923 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8925 intro
->hreftype
= -1; /* TODO? */
8926 intro
->namelen
= size
& 0xFF;
8927 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8928 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8929 intro
->namelen
|= hash
<< 16;
8930 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8931 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
8933 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8934 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8936 /* update str->offset to actual value to use in other
8937 * compilation functions that require positions within
8938 * the string table */
8942 str
->offset
= last_offs
;
8947 last_intro
->hreftype
= 0; /* last one is 0? */
8952 static inline int hash_guid(GUID
*guid
)
8956 for (i
= 0; i
< 8; i
++)
8957 hash
^= ((const short *)guid
)[i
];
8962 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8965 MSFT_GuidEntry
*entry
;
8967 int hash_key
, *guidhashtab
;
8969 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8970 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8972 entry
= file
->guid_seg
.data
;
8974 guidhashtab
= file
->guidhash_seg
.data
;
8975 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
8976 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
8977 entry
->hreftype
= guid
->hreftype
;
8979 hash_key
= hash_guid(&guid
->guid
);
8980 entry
->next_hash
= guidhashtab
[hash_key
];
8981 guidhashtab
[hash_key
] = offs
;
8983 guid
->offset
= offs
;
8984 offs
+= sizeof(MSFT_GuidEntry
);
8991 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
8994 VARTYPE arg_type
= V_VT(value
);
8997 DWORD ret
= file
->custdata_seg
.len
;
8999 if(arg_type
== VT_INT
)
9001 if(arg_type
== VT_UINT
)
9005 if(V_VT(value
) != arg_type
) {
9006 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9008 ERR("VariantChangeType failed: %08x\n", hres
);
9013 /* Check if default value can be stored in-place */
9018 if(V_UI4(&v
) > 0x3ffffff)
9031 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9034 /* have to allocate space in custdata_seg */
9043 /* Construct the data to be allocated */
9046 if(file
->custdata_seg
.data
){
9047 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9048 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9049 file
->custdata_seg
.len
+= sizeof(int) * 2;
9051 file
->custdata_seg
.len
= sizeof(int) * 2;
9052 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9055 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9056 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9058 /* TODO: Check if the encoded data is already present in custdata_seg */
9064 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9067 if(file
->custdata_seg
.data
){
9068 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9069 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9070 file
->custdata_seg
.len
+= len
;
9072 file
->custdata_seg
.len
= len
;
9073 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9076 *((unsigned short *)data
) = V_VT(value
);
9077 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9078 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9079 if(V_BSTR(&v
)[i
] <= 0x7f)
9080 data
[i
+6] = V_BSTR(&v
)[i
];
9084 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9085 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9088 /* TODO: Check if the encoded data is already present in custdata_seg */
9093 FIXME("Argument type not yet handled\n");
9098 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9100 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9102 DWORD offs
= file
->arraydesc_seg
.len
;
9106 /* TODO: we should check for duplicates, but that's harder because each
9107 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9108 * at the library-level) */
9110 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9111 if(!file
->arraydesc_seg
.data
)
9112 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9114 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9115 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
9117 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9118 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9119 for(i
= 0; i
< desc
->cDims
; ++i
){
9120 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9121 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9127 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9133 VARTYPE vt
, subtype
;
9144 vt
= desc
->vt
& VT_TYPEMASK
;
9178 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9181 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9183 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9184 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9186 *out_size
+= 2 * sizeof(DWORD
);
9187 }else if(vt
== VT_CARRAY
){
9188 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9189 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9191 }else if(vt
== VT_USERDEFINED
){
9192 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9193 encoded
[1] = desc
->u
.hreftype
;
9194 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9196 FIXME("Don't know what to do! VT: 0x%x\n", desc
->vt
);
9197 *out_mix
= desc
->vt
;
9198 return 0x80000000 | (desc
->vt
<< 16) | desc
->vt
;
9201 data
= file
->typdesc_seg
.data
;
9202 while(offs
< file
->typdesc_seg
.len
){
9203 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9205 offs
+= sizeof(encoded
);
9208 file
->typdesc_seg
.len
+= sizeof(encoded
);
9209 if(!file
->typdesc_seg
.data
)
9210 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9212 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9214 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9219 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9221 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9222 DWORD ret
= cdguids_seg
->len
, offs
;
9223 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9226 if(list_empty(custdata_list
))
9229 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9230 if(!cdguids_seg
->data
){
9231 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9233 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9235 offs
= ret
+ sizeof(MSFT_CDGuid
);
9236 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9237 cdguid
->GuidOffset
= cd
->guid
->offset
;
9238 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9239 cdguid
->next
= offs
;
9240 offs
+= sizeof(MSFT_CDGuid
);
9250 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9251 WMSFT_TLBFile
*file
)
9253 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9254 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9255 MSFT_VarRecord
*varrecord
;
9256 MSFT_FuncRecord
*funcrecord
;
9258 DWORD
*name
, *offsets
, offs
;
9260 for(i
= 0; i
< info
->cFuncs
; ++i
){
9261 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9263 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9265 /* optional fields */
9266 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9267 if(!list_empty(&desc
->custdata_list
))
9268 recorded_size
+= 7 * sizeof(INT
);
9269 else if(desc
->HelpStringContext
!= 0)
9270 recorded_size
+= 6 * sizeof(INT
);
9272 else if(desc
->Entry
)
9273 recorded_size
+= 3 * sizeof(INT
);
9274 else if(desc
->HelpString
)
9275 recorded_size
+= 2 * sizeof(INT
);
9276 else if(desc
->helpcontext
)
9277 recorded_size
+= sizeof(INT
);
9279 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9281 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9282 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9283 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9288 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9291 for(i
= 0; i
< info
->cVars
; ++i
){
9292 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9294 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9296 /* optional fields */
9297 if(desc
->HelpStringContext
!= 0)
9298 recorded_size
+= 5 * sizeof(INT
);
9299 else if(!list_empty(&desc
->custdata_list
))
9300 recorded_size
+= 4 * sizeof(INT
);
9302 else if(desc
->HelpString
)
9303 recorded_size
+= 2 * sizeof(INT
);
9304 else if(desc
->HelpContext
!= 0)
9305 recorded_size
+= sizeof(INT
);
9307 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9310 if(!recorded_size
&& !extra_size
)
9313 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9315 aux_seg
->len
+= recorded_size
+ extra_size
;
9317 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9320 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9322 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9324 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9326 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9329 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9330 for(i
= 0; i
< info
->cFuncs
; ++i
){
9331 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9332 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9334 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9335 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9336 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9337 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9340 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9345 * ^has_param_defaults
9346 * ^oEntry_is_intresource
9348 funcrecord
->FKCCIC
=
9349 desc
->funcdesc
.funckind
|
9350 (desc
->funcdesc
.invkind
<< 3) |
9351 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9352 (desc
->funcdesc
.callconv
<< 8);
9354 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9355 funcrecord
->FKCCIC
|= 0x2000;
9357 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9358 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9359 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9360 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9363 if(paramdefault_size
> 0)
9364 funcrecord
->FKCCIC
|= 0x1000;
9366 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9367 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9369 /* optional fields */
9371 if(!list_empty(&desc
->custdata_list
)){
9372 size
+= 7 * sizeof(INT
);
9373 funcrecord
->HelpContext
= desc
->helpcontext
;
9374 if(desc
->HelpString
)
9375 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9377 funcrecord
->oHelpString
= -1;
9379 funcrecord
->oEntry
= -1;
9380 else if(IS_INTRESOURCE(desc
->Entry
))
9381 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9383 funcrecord
->oEntry
= desc
->Entry
->offset
;
9384 funcrecord
->res9
= -1;
9385 funcrecord
->resA
= -1;
9386 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9387 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9388 }else if(desc
->HelpStringContext
!= 0){
9389 size
+= 6 * sizeof(INT
);
9390 funcrecord
->HelpContext
= desc
->helpcontext
;
9391 if(desc
->HelpString
)
9392 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9394 funcrecord
->oHelpString
= -1;
9396 funcrecord
->oEntry
= -1;
9397 else if(IS_INTRESOURCE(desc
->Entry
))
9398 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9400 funcrecord
->oEntry
= desc
->Entry
->offset
;
9401 funcrecord
->res9
= -1;
9402 funcrecord
->resA
= -1;
9403 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9404 }else if(desc
->Entry
){
9405 size
+= 3 * sizeof(INT
);
9406 funcrecord
->HelpContext
= desc
->helpcontext
;
9407 if(desc
->HelpString
)
9408 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9410 funcrecord
->oHelpString
= -1;
9412 funcrecord
->oEntry
= -1;
9413 else if(IS_INTRESOURCE(desc
->Entry
))
9414 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9416 funcrecord
->oEntry
= desc
->Entry
->offset
;
9417 }else if(desc
->HelpString
){
9418 size
+= 2 * sizeof(INT
);
9419 funcrecord
->HelpContext
= desc
->helpcontext
;
9420 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9421 }else if(desc
->helpcontext
){
9422 size
+= sizeof(INT
);
9423 funcrecord
->HelpContext
= desc
->helpcontext
;
9426 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9427 size
+= paramdefault_size
;
9429 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9430 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9432 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9433 if(desc
->pParamDesc
[j
].Name
)
9434 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9437 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9439 if(paramdefault_size
){
9440 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9441 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9442 else if(paramdefault_size
)
9447 size
+= sizeof(MSFT_ParameterInfo
);
9450 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9456 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9459 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9460 for(i
= 0; i
< info
->cVars
; ++i
){
9461 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9462 DWORD size
= 5 * sizeof(INT
);
9464 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9465 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9466 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9467 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9469 if(desc
->vardesc
.varkind
== VAR_CONST
){
9470 varrecord
->vardescsize
+= sizeof(VARIANT
);
9471 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9473 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9476 if(desc
->HelpStringContext
!= 0){
9477 size
+= 5 * sizeof(INT
);
9478 varrecord
->HelpContext
= desc
->HelpContext
;
9479 if(desc
->HelpString
)
9480 varrecord
->HelpString
= desc
->HelpString
->offset
;
9482 varrecord
->HelpString
= -1;
9483 varrecord
->res9
= -1;
9484 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9485 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9486 }else if(!list_empty(&desc
->custdata_list
)){
9487 size
+= 4 * sizeof(INT
);
9488 varrecord
->HelpContext
= desc
->HelpContext
;
9489 if(desc
->HelpString
)
9490 varrecord
->HelpString
= desc
->HelpString
->offset
;
9492 varrecord
->HelpString
= -1;
9493 varrecord
->res9
= -1;
9494 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9495 }else if(desc
->HelpString
){
9496 size
+= 2 * sizeof(INT
);
9497 varrecord
->HelpContext
= desc
->HelpContext
;
9498 if(desc
->HelpString
)
9499 varrecord
->HelpString
= desc
->HelpString
->offset
;
9501 varrecord
->HelpString
= -1;
9502 }else if(desc
->HelpContext
!= 0){
9503 size
+= sizeof(INT
);
9504 varrecord
->HelpContext
= desc
->HelpContext
;
9507 varrecord
->Info
= size
| (i
<< 16);
9513 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9516 memid
= (MEMBERID
*)varrecord
;
9517 for(i
= 0; i
< info
->cFuncs
; ++i
){
9518 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9519 *memid
= desc
->funcdesc
.memid
;
9522 for(i
= 0; i
< info
->cVars
; ++i
){
9523 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9524 *memid
= desc
->vardesc
.memid
;
9528 name
= (UINT
*)memid
;
9529 for(i
= 0; i
< info
->cFuncs
; ++i
){
9530 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9532 *name
= desc
->Name
->offset
;
9537 for(i
= 0; i
< info
->cVars
; ++i
){
9538 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9540 *name
= desc
->Name
->offset
;
9549 typedef struct tagWMSFT_RefChunk
{
9556 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9558 DWORD offs
= file
->ref_seg
.len
, i
;
9559 WMSFT_RefChunk
*chunk
;
9561 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9562 if(!file
->ref_seg
.data
)
9563 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9565 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9567 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9569 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9570 chunk
->href
= info
->impltypes
[i
].hRef
;
9571 chunk
->res04
= info
->impltypes
[i
].implflags
;
9573 if(i
< info
->cImplTypes
- 1)
9574 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9583 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9587 size
= sizeof(MSFT_TypeInfoBase
);
9590 MSFT_TypeInfoBase
*base
= (void*)data
;
9591 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9592 base
->typekind
= TKIND_DISPATCH
;
9594 base
->typekind
= info
->typekind
;
9595 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9596 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9597 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9602 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9608 base
->posguid
= info
->guid
->offset
;
9611 base
->flags
= info
->wTypeFlags
;
9613 base
->NameOffset
= info
->Name
->offset
;
9615 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9616 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9618 base
->NameOffset
= -1;
9620 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9622 base
->docstringoffs
= info
->DocString
->offset
;
9624 base
->docstringoffs
= -1;
9625 base
->helpstringcontext
= info
->dwHelpStringContext
;
9626 base
->helpcontext
= info
->dwHelpContext
;
9627 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9628 base
->cImplTypes
= info
->cImplTypes
;
9629 base
->cbSizeVft
= info
->cbSizeVft
;
9630 base
->size
= info
->cbSizeInstance
;
9631 if(info
->typekind
== TKIND_COCLASS
){
9632 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9633 }else if(info
->typekind
== TKIND_ALIAS
){
9634 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9635 }else if(info
->typekind
== TKIND_MODULE
){
9637 base
->datatype1
= info
->DllName
->offset
;
9639 base
->datatype1
= -1;
9641 if(info
->cImplTypes
> 0)
9642 base
->datatype1
= info
->impltypes
[0].hRef
;
9644 base
->datatype1
= -1;
9646 base
->datatype2
= index
; /* FIXME: i think there's more here */
9654 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9658 file
->typeinfo_seg
.len
= 0;
9659 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9660 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9661 *junk
= file
->typeinfo_seg
.len
;
9663 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9666 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9667 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9669 file
->aux_seg
.len
= 0;
9670 file
->aux_seg
.data
= NULL
;
9672 file
->typeinfo_seg
.len
= 0;
9673 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9674 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9675 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9676 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9680 typedef struct tagWMSFT_ImpFile
{
9686 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9689 WMSFT_ImpFile
*impfile
;
9691 DWORD last_offs
= 0;
9693 file
->impfile_seg
.len
= 0;
9694 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9698 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9702 path
= implib
->name
;
9703 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9705 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9708 size
+= sizeof(INT16
);
9710 size
= (size
+ 4) & ~0x3;
9714 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9717 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9719 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9720 int strlen
= 0, size
;
9722 impfile
= (WMSFT_ImpFile
*)data
;
9723 impfile
->guid_offs
= implib
->guid
->offset
;
9724 impfile
->lcid
= implib
->lcid
;
9725 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9727 data
+= sizeof(WMSFT_ImpFile
);
9730 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9734 path
= implib
->name
;
9735 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9736 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9738 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9741 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9743 size
= strlen
+ sizeof(INT16
);
9745 size
= (size
+ 4) & ~0x3;
9748 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9751 implib
->offset
= last_offs
;
9752 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9756 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9759 TLBRefType
*ref_type
;
9762 WMSFT_compile_impfile(This
, file
);
9764 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9765 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9767 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9768 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9769 if(ref_type
->index
== TLB_REF_USE_GUID
){
9770 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9771 info
->oGuid
= ref_type
->guid
->offset
;
9773 info
->oGuid
= ref_type
->index
;
9774 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9780 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9782 file
->guidhash_seg
.len
= 0x80;
9783 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9784 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9787 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9789 file
->namehash_seg
.len
= 0x200;
9790 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9791 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9794 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9796 if(contents
&& contents
->len
){
9797 segdir
->offset
= *running_offset
;
9798 segdir
->length
= contents
->len
;
9799 *running_offset
+= segdir
->length
;
9801 segdir
->offset
= -1;
9805 /* TODO: do these ever change? */
9807 segdir
->res0c
= 0xf;
9810 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9814 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9817 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9821 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9823 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9824 base
->memoffset
+= file_len
;
9831 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9833 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9834 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9835 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9836 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9837 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9838 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9839 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9840 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9841 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9842 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9843 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9844 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9845 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9846 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9849 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9851 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9853 DWORD written
, junk_size
, junk_offs
, running_offset
;
9860 TRACE("%p\n", This
);
9862 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9863 if(This
->typeinfos
[i
]->needs_layout
)
9864 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9866 memset(&file
, 0, sizeof(file
));
9868 file
.header
.magic1
= 0x5446534D;
9869 file
.header
.magic2
= 0x00010002;
9870 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9871 file
.header
.lcid2
= This
->set_lcid
;
9872 file
.header
.varflags
= 0x40 | This
->syskind
;
9874 file
.header
.varflags
|= 0x10;
9875 if (This
->HelpStringDll
)
9876 file
.header
.varflags
|= HELPDLLFLAG
;
9877 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9878 file
.header
.flags
= This
->libflags
;
9879 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9880 file
.header
.helpcontext
= This
->dwHelpContext
;
9881 file
.header
.res44
= 0x20;
9882 file
.header
.res48
= 0x80;
9883 file
.header
.dispatchpos
= This
->dispatch_href
;
9885 WMSFT_compile_namehash(This
, &file
);
9886 /* do name and string compilation to get offsets for other compilations */
9887 hres
= WMSFT_compile_names(This
, &file
);
9889 WMSFT_free_file(&file
);
9893 hres
= WMSFT_compile_strings(This
, &file
);
9895 WMSFT_free_file(&file
);
9899 WMSFT_compile_guidhash(This
, &file
);
9900 hres
= WMSFT_compile_guids(This
, &file
);
9902 WMSFT_free_file(&file
);
9907 file
.header
.helpfile
= This
->HelpFile
->offset
;
9909 file
.header
.helpfile
= -1;
9912 file
.header
.helpstring
= This
->DocString
->offset
;
9914 file
.header
.helpstring
= -1;
9916 /* do some more segment compilation */
9917 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9918 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9921 file
.header
.NameOffset
= This
->Name
->offset
;
9923 file
.header
.NameOffset
= -1;
9925 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9928 file
.header
.posguid
= This
->guid
->offset
;
9930 file
.header
.posguid
= -1;
9932 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9933 if(file
.header
.varflags
& HELPDLLFLAG
)
9934 junk_size
+= sizeof(DWORD
);
9936 junk
= heap_alloc_zero(junk_size
);
9937 if(file
.header
.varflags
& HELPDLLFLAG
){
9938 *junk
= This
->HelpStringDll
->offset
;
9947 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9948 WMSFT_compile_impinfo(This
, &file
);
9952 TRACE("header at: 0x%x\n", running_offset
);
9953 running_offset
+= sizeof(file
.header
);
9955 TRACE("junk at: 0x%x\n", running_offset
);
9956 running_offset
+= junk_size
;
9958 TRACE("segdir at: 0x%x\n", running_offset
);
9959 running_offset
+= sizeof(file
.segdir
);
9961 TRACE("typeinfo at: 0x%x\n", running_offset
);
9962 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9964 TRACE("guidhashtab at: 0x%x\n", running_offset
);
9965 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
9967 TRACE("guidtab at: 0x%x\n", running_offset
);
9968 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9970 TRACE("reftab at: 0x%x\n", running_offset
);
9971 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9973 TRACE("impinfo at: 0x%x\n", running_offset
);
9974 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9976 TRACE("impfiles at: 0x%x\n", running_offset
);
9977 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9979 TRACE("namehashtab at: 0x%x\n", running_offset
);
9980 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
9982 TRACE("nametab at: 0x%x\n", running_offset
);
9983 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9985 TRACE("stringtab at: 0x%x\n", running_offset
);
9986 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9988 TRACE("typdesc at: 0x%x\n", running_offset
);
9989 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
9991 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
9992 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
9994 TRACE("custdata at: 0x%x\n", running_offset
);
9995 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
9997 TRACE("cdguids at: 0x%x\n", running_offset
);
9998 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10000 TRACE("res0e at: 0x%x\n", running_offset
);
10001 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10003 TRACE("res0f at: 0x%x\n", running_offset
);
10004 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10006 TRACE("aux_seg at: 0x%x\n", running_offset
);
10008 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10010 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10011 FILE_ATTRIBUTE_NORMAL
, 0);
10012 if (outfile
== INVALID_HANDLE_VALUE
){
10013 WMSFT_free_file(&file
);
10015 return TYPE_E_IOERROR
;
10018 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10020 WMSFT_free_file(&file
);
10021 CloseHandle(outfile
);
10023 return TYPE_E_IOERROR
;
10026 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10029 WMSFT_free_file(&file
);
10030 CloseHandle(outfile
);
10031 return TYPE_E_IOERROR
;
10034 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10036 WMSFT_free_file(&file
);
10037 CloseHandle(outfile
);
10038 return TYPE_E_IOERROR
;
10041 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10042 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10043 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10044 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10045 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10046 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10047 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10048 WMSFT_write_segment(outfile
, &file
.name_seg
);
10049 WMSFT_write_segment(outfile
, &file
.string_seg
);
10050 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10051 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10052 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10053 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10054 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10056 WMSFT_free_file(&file
);
10058 CloseHandle(outfile
);
10063 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10066 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10067 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10071 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10072 REFGUID guid
, VARIANT
*varVal
)
10074 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10075 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10079 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10080 ULONG helpStringContext
)
10082 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10083 FIXME("%p %u - stub\n", This
, helpStringContext
);
10087 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10090 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10091 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10094 return E_INVALIDARG
;
10096 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10101 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10102 ICreateTypeLib2_fnQueryInterface
,
10103 ICreateTypeLib2_fnAddRef
,
10104 ICreateTypeLib2_fnRelease
,
10105 ICreateTypeLib2_fnCreateTypeInfo
,
10106 ICreateTypeLib2_fnSetName
,
10107 ICreateTypeLib2_fnSetVersion
,
10108 ICreateTypeLib2_fnSetGuid
,
10109 ICreateTypeLib2_fnSetDocString
,
10110 ICreateTypeLib2_fnSetHelpFileName
,
10111 ICreateTypeLib2_fnSetHelpContext
,
10112 ICreateTypeLib2_fnSetLcid
,
10113 ICreateTypeLib2_fnSetLibFlags
,
10114 ICreateTypeLib2_fnSaveAllChanges
,
10115 ICreateTypeLib2_fnDeleteTypeInfo
,
10116 ICreateTypeLib2_fnSetCustData
,
10117 ICreateTypeLib2_fnSetHelpStringContext
,
10118 ICreateTypeLib2_fnSetHelpStringDll
10121 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10122 REFIID riid
, void **object
)
10124 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10126 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10129 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10131 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10133 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10136 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10138 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10140 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10143 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10146 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10148 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10150 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10155 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10158 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10162 TRACE("%p %x\n", This
, typeFlags
);
10164 if (typeFlags
& TYPEFLAG_FDUAL
) {
10165 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10167 ITypeInfo
*dispatch
;
10171 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10175 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10176 ITypeLib_Release(stdole
);
10180 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10181 ITypeInfo_Release(dispatch
);
10186 old_flags
= This
->wTypeFlags
;
10187 This
->wTypeFlags
= typeFlags
;
10189 hres
= ICreateTypeInfo2_LayOut(iface
);
10190 if (FAILED(hres
)) {
10191 This
->wTypeFlags
= old_flags
;
10198 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10201 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10203 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10206 return E_INVALIDARG
;
10208 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10213 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10216 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10218 TRACE("%p %d\n", This
, helpContext
);
10220 This
->dwHelpContext
= helpContext
;
10225 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10226 WORD majorVerNum
, WORD minorVerNum
)
10228 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10230 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10232 This
->wMajorVerNum
= majorVerNum
;
10233 This
->wMinorVerNum
= minorVerNum
;
10238 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10239 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10241 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10243 ITypeLib
*container
;
10244 TLBRefType
*ref_type
;
10246 TYPEATTR
*typeattr
;
10250 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10252 if (!typeInfo
|| !refType
)
10253 return E_INVALIDARG
;
10255 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10259 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10260 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10262 ITypeLib_Release(container
);
10264 *refType
= target
->hreftype
;
10269 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10270 if (FAILED(hres
)) {
10271 ITypeLib_Release(container
);
10275 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10276 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10277 implib
->lcid
== libattr
->lcid
&&
10278 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10279 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10283 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10284 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10286 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10287 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10288 implib
->name
= SysAllocString(our_container
->path
);
10290 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10291 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10293 implib
->name
= NULL
;
10294 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10298 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10299 implib
->lcid
= libattr
->lcid
;
10300 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10301 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10303 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10306 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10307 ITypeLib_Release(container
);
10309 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10314 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10315 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10316 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10317 ref_type
->tkind
== typeattr
->typekind
)
10322 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10323 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10325 ref_type
->tkind
= typeattr
->typekind
;
10326 ref_type
->pImpTLInfo
= implib
;
10327 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10329 ref_type
->index
= TLB_REF_USE_GUID
;
10331 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10333 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10336 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10338 *refType
= ref_type
->reference
| 0x1;
10340 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10341 This
->pTypeLib
->dispatch_href
= *refType
;
10346 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10347 UINT index
, FUNCDESC
*funcDesc
)
10349 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10350 TLBFuncDesc tmp_func_desc
, *func_desc
;
10355 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10357 if (!funcDesc
|| funcDesc
->oVft
& 3)
10358 return E_INVALIDARG
;
10360 switch (This
->typekind
) {
10362 if (funcDesc
->funckind
!= FUNC_STATIC
)
10363 return TYPE_E_BADMODULEKIND
;
10365 case TKIND_DISPATCH
:
10366 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10367 return TYPE_E_BADMODULEKIND
;
10370 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10371 return TYPE_E_BADMODULEKIND
;
10374 if (index
> This
->cFuncs
)
10375 return TYPE_E_ELEMENTNOTFOUND
;
10377 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10378 !funcDesc
->cParams
)
10379 return TYPE_E_INCONSISTENTPROPFUNCS
;
10382 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10383 funcDesc
->oVft
% 8 != 0)
10384 return E_INVALIDARG
;
10387 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10388 TLBFuncDesc_Constructor(&tmp_func_desc
);
10390 tmp_func_desc
.funcdesc
= *funcDesc
;
10392 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10393 tmp_func_desc
.funcdesc
.oVft
|= 1;
10395 if (funcDesc
->cScodes
) {
10396 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10397 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10399 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10401 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10402 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10403 buf_size
+= sizeof(ELEMDESC
);
10404 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10406 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10407 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10409 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10410 if (FAILED(hres
)) {
10411 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10412 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10416 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10417 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10418 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10419 if (FAILED(hres
)) {
10420 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10421 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10424 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10425 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10426 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10427 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10428 if (FAILED(hres
)) {
10429 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10430 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10436 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10438 if (This
->funcdescs
) {
10439 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10440 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10442 if (index
< This
->cFuncs
) {
10443 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10444 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10445 func_desc
= This
->funcdescs
+ index
;
10447 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10449 /* move custdata lists to the new memory location */
10450 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10452 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10453 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10454 list_init(&fd
->custdata_list
);
10456 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10457 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10462 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10464 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10465 list_init(&func_desc
->custdata_list
);
10469 This
->needs_layout
= TRUE
;
10474 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10475 UINT index
, HREFTYPE refType
)
10477 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10478 TLBImplType
*impl_type
;
10481 TRACE("%p %u %d\n", This
, index
, refType
);
10483 switch(This
->typekind
){
10484 case TKIND_COCLASS
: {
10486 FIXME("Unhandled index: -1\n");
10490 if(index
!= This
->cImplTypes
)
10491 return TYPE_E_ELEMENTNOTFOUND
;
10495 case TKIND_INTERFACE
:
10496 case TKIND_DISPATCH
:
10497 if (index
!= 0 || This
->cImplTypes
)
10498 return TYPE_E_ELEMENTNOTFOUND
;
10501 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10505 if (This
->impltypes
){
10508 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10509 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10511 if (index
< This
->cImplTypes
) {
10512 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10513 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10514 impl_type
= This
->impltypes
+ index
;
10516 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10518 /* move custdata lists to the new memory location */
10519 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10521 TLBImplType
*it
= &This
->impltypes
[i
];
10522 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10523 list_init(&it
->custdata_list
);
10525 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10526 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10531 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10533 memset(impl_type
, 0, sizeof(TLBImplType
));
10534 TLBImplType_Constructor(impl_type
);
10535 impl_type
->hRef
= refType
;
10537 ++This
->cImplTypes
;
10539 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10540 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10542 hres
= ICreateTypeInfo2_LayOut(iface
);
10549 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10550 UINT index
, INT implTypeFlags
)
10552 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10553 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10555 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10557 if (This
->typekind
!= TKIND_COCLASS
)
10558 return TYPE_E_BADMODULEKIND
;
10560 if (index
>= This
->cImplTypes
)
10561 return TYPE_E_ELEMENTNOTFOUND
;
10563 impl_type
->implflags
= implTypeFlags
;
10568 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10571 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10573 TRACE("%p %d\n", This
, alignment
);
10575 This
->cbAlignment
= alignment
;
10580 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10583 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10585 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10588 return E_INVALIDARG
;
10590 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10592 This
->lpstrSchema
= This
->Schema
->str
;
10597 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10598 UINT index
, VARDESC
*varDesc
)
10600 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10601 TLBVarDesc
*var_desc
;
10603 TRACE("%p %u %p\n", This
, index
, varDesc
);
10605 if (This
->vardescs
){
10608 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10609 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10611 if (index
< This
->cVars
) {
10612 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10613 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10614 var_desc
= This
->vardescs
+ index
;
10616 var_desc
= This
->vardescs
+ This
->cVars
;
10618 /* move custdata lists to the new memory location */
10619 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10621 TLBVarDesc
*var
= &This
->vardescs
[i
];
10622 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10623 list_init(&var
->custdata_list
);
10625 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10626 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10631 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10633 TLBVarDesc_Constructor(var_desc
);
10634 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10635 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10639 This
->needs_layout
= TRUE
;
10644 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10645 UINT index
, LPOLESTR
*names
, UINT numNames
)
10647 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10648 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10651 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10654 return E_INVALIDARG
;
10656 if (index
>= This
->cFuncs
|| numNames
== 0)
10657 return TYPE_E_ELEMENTNOTFOUND
;
10659 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10660 if(numNames
> func_desc
->funcdesc
.cParams
)
10661 return TYPE_E_ELEMENTNOTFOUND
;
10663 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10664 return TYPE_E_ELEMENTNOTFOUND
;
10666 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10667 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10668 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10669 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10670 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10671 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10673 return TYPE_E_AMBIGUOUSNAME
;
10677 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10679 for (i
= 1; i
< numNames
; ++i
) {
10680 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10681 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10687 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10688 UINT index
, LPOLESTR name
)
10690 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10692 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10695 return E_INVALIDARG
;
10697 if(index
>= This
->cVars
)
10698 return TYPE_E_ELEMENTNOTFOUND
;
10700 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10704 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10705 TYPEDESC
*tdescAlias
)
10707 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10710 TRACE("%p %p\n", This
, tdescAlias
);
10713 return E_INVALIDARG
;
10715 if(This
->typekind
!= TKIND_ALIAS
)
10716 return TYPE_E_BADMODULEKIND
;
10718 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10722 heap_free(This
->tdescAlias
);
10723 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10724 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10729 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10730 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10732 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10733 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10737 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10738 UINT index
, LPOLESTR docString
)
10740 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10741 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
10745 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10746 UINT index
, LPOLESTR docString
)
10748 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10749 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10751 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10754 return E_INVALIDARG
;
10756 if(index
>= This
->cVars
)
10757 return TYPE_E_ELEMENTNOTFOUND
;
10759 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10764 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10765 UINT index
, DWORD helpContext
)
10767 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10768 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10770 TRACE("%p %u %d\n", This
, index
, helpContext
);
10772 if(index
>= This
->cFuncs
)
10773 return TYPE_E_ELEMENTNOTFOUND
;
10775 func_desc
->helpcontext
= helpContext
;
10780 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10781 UINT index
, DWORD helpContext
)
10783 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10784 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10786 TRACE("%p %u %d\n", This
, index
, helpContext
);
10788 if(index
>= This
->cVars
)
10789 return TYPE_E_ELEMENTNOTFOUND
;
10791 var_desc
->HelpContext
= helpContext
;
10796 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10797 UINT index
, BSTR bstrMops
)
10799 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10800 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10804 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10807 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10809 TRACE("%p %p\n", This
, idlDesc
);
10812 return E_INVALIDARG
;
10814 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10815 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10820 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10822 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10824 TLBFuncDesc
*func_desc
;
10825 UINT user_vft
= 0, i
, depth
= 0;
10826 HRESULT hres
= S_OK
;
10828 TRACE("%p\n", This
);
10830 This
->needs_layout
= FALSE
;
10832 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10836 if (This
->typekind
== TKIND_INTERFACE
) {
10841 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10843 if (SUCCEEDED(hres
)) {
10844 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10846 if (SUCCEEDED(hres
)) {
10847 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10848 if (FAILED(hres
)) {
10849 ITypeInfo_Release(inh
);
10850 ITypeInfo_Release(tinfo
);
10853 This
->cbSizeVft
= attr
->cbSizeVft
;
10854 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10858 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10859 if(SUCCEEDED(hres
)){
10861 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10862 if(SUCCEEDED(hres
)){
10863 ITypeInfo_Release(inh
);
10867 }while(SUCCEEDED(hres
));
10870 ITypeInfo_Release(inh
);
10871 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10872 This
->cbSizeVft
= 0;
10875 ITypeInfo_Release(tinfo
);
10878 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10879 This
->cbSizeVft
= 0;
10882 ITypeInfo_Release(tinfo
);
10885 } else if (This
->typekind
== TKIND_DISPATCH
)
10886 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10888 This
->cbSizeVft
= 0;
10890 func_desc
= This
->funcdescs
;
10892 while (i
< This
->cFuncs
) {
10893 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10894 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10896 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10897 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10899 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10901 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10904 BOOL reset
= FALSE
;
10906 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10908 iter
= This
->funcdescs
;
10909 while (j
< This
->cFuncs
) {
10910 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10912 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10915 ++func_desc
->funcdesc
.memid
;
10916 iter
= This
->funcdescs
;
10929 if (user_vft
> This
->cbSizeVft
)
10930 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10932 for(i
= 0; i
< This
->cVars
; ++i
){
10933 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10934 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
10936 BOOL reset
= FALSE
;
10939 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
10941 iter
= This
->vardescs
;
10942 while (j
< This
->cVars
) {
10943 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
10945 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
10948 ++var_desc
->vardesc
.memid
;
10949 iter
= This
->vardescs
;
10959 ITypeInfo_Release(tinfo
);
10963 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10966 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10967 FIXME("%p %u - stub\n", This
, index
);
10971 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
10972 MEMBERID memid
, INVOKEKIND invKind
)
10974 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10975 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
10979 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
10982 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10983 FIXME("%p %u - stub\n", This
, index
);
10987 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
10990 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10991 FIXME("%p %x - stub\n", This
, memid
);
10995 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
10998 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10999 FIXME("%p %u - stub\n", This
, index
);
11003 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11004 REFGUID guid
, VARIANT
*varVal
)
11008 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11010 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11012 if (!guid
|| !varVal
)
11013 return E_INVALIDARG
;
11015 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11017 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11020 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11021 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11023 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11024 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11028 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11029 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11031 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11032 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11036 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11037 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11039 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11040 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11044 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11045 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11047 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11048 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11052 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11053 ULONG helpStringContext
)
11055 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11057 TRACE("%p %u\n", This
, helpStringContext
);
11059 This
->dwHelpStringContext
= helpStringContext
;
11064 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11065 UINT index
, ULONG helpStringContext
)
11067 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11068 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11072 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11073 UINT index
, ULONG helpStringContext
)
11075 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11076 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11080 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11082 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11083 FIXME("%p - stub\n", This
);
11087 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11090 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11092 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11095 return E_INVALIDARG
;
11097 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11102 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11103 ICreateTypeInfo2_fnQueryInterface
,
11104 ICreateTypeInfo2_fnAddRef
,
11105 ICreateTypeInfo2_fnRelease
,
11106 ICreateTypeInfo2_fnSetGuid
,
11107 ICreateTypeInfo2_fnSetTypeFlags
,
11108 ICreateTypeInfo2_fnSetDocString
,
11109 ICreateTypeInfo2_fnSetHelpContext
,
11110 ICreateTypeInfo2_fnSetVersion
,
11111 ICreateTypeInfo2_fnAddRefTypeInfo
,
11112 ICreateTypeInfo2_fnAddFuncDesc
,
11113 ICreateTypeInfo2_fnAddImplType
,
11114 ICreateTypeInfo2_fnSetImplTypeFlags
,
11115 ICreateTypeInfo2_fnSetAlignment
,
11116 ICreateTypeInfo2_fnSetSchema
,
11117 ICreateTypeInfo2_fnAddVarDesc
,
11118 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11119 ICreateTypeInfo2_fnSetVarName
,
11120 ICreateTypeInfo2_fnSetTypeDescAlias
,
11121 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11122 ICreateTypeInfo2_fnSetFuncDocString
,
11123 ICreateTypeInfo2_fnSetVarDocString
,
11124 ICreateTypeInfo2_fnSetFuncHelpContext
,
11125 ICreateTypeInfo2_fnSetVarHelpContext
,
11126 ICreateTypeInfo2_fnSetMops
,
11127 ICreateTypeInfo2_fnSetTypeIdldesc
,
11128 ICreateTypeInfo2_fnLayOut
,
11129 ICreateTypeInfo2_fnDeleteFuncDesc
,
11130 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11131 ICreateTypeInfo2_fnDeleteVarDesc
,
11132 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11133 ICreateTypeInfo2_fnDeleteImplType
,
11134 ICreateTypeInfo2_fnSetCustData
,
11135 ICreateTypeInfo2_fnSetFuncCustData
,
11136 ICreateTypeInfo2_fnSetParamCustData
,
11137 ICreateTypeInfo2_fnSetVarCustData
,
11138 ICreateTypeInfo2_fnSetImplTypeCustData
,
11139 ICreateTypeInfo2_fnSetHelpStringContext
,
11140 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11141 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11142 ICreateTypeInfo2_fnInvalidate
,
11143 ICreateTypeInfo2_fnSetName
11146 /******************************************************************************
11147 * ClearCustData (OLEAUT32.171)
11149 * Clear a custom data type's data.
11152 * lpCust [I] The custom data type instance
11157 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11159 if (lpCust
&& lpCust
->cCustData
)
11161 if (lpCust
->prgCustData
)
11165 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11166 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11168 /* FIXME - Should be using a per-thread IMalloc */
11169 heap_free(lpCust
->prgCustData
);
11170 lpCust
->prgCustData
= NULL
;
11172 lpCust
->cCustData
= 0;