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: %sfound!\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 (!lstrcmpiW(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
);
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
);
8527 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8528 This
->typekind
== TKIND_DISPATCH
)
8530 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8531 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8532 SysFreeString((BSTR
)tmp
);
8536 WARN("Could not search inherited interface!\n");
8538 if (hr
== DISP_E_MEMBERNOTFOUND
)
8540 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8544 static HRESULT WINAPI
ITypeComp_fnBindType(
8548 ITypeInfo
** ppTInfo
,
8549 ITypeComp
** ppTComp
)
8551 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8553 /* strange behaviour (does nothing) but like the
8556 if (!ppTInfo
|| !ppTComp
)
8565 static const ITypeCompVtbl tcompvt
=
8568 ITypeComp_fnQueryInterface
,
8570 ITypeComp_fnRelease
,
8573 ITypeComp_fnBindType
8576 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8577 ICreateTypeLib2
** ppctlib
)
8582 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8584 if (!szFile
) return E_INVALIDARG
;
8586 This
= TypeLibImpl_Constructor();
8588 return E_OUTOFMEMORY
;
8590 This
->lcid
= GetSystemDefaultLCID();
8591 This
->syskind
= syskind
;
8592 This
->ptr_size
= get_ptr_size(syskind
);
8594 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8596 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8597 return E_OUTOFMEMORY
;
8599 lstrcpyW(This
->path
, szFile
);
8601 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8602 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8606 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8607 REFIID riid
, void **object
)
8609 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8611 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8614 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8616 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8618 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8621 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8623 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8625 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8628 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8629 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8631 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8632 ITypeInfoImpl
*info
;
8635 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8637 if (!ctinfo
|| !name
)
8638 return E_INVALIDARG
;
8640 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8642 return TYPE_E_NAMECONFLICT
;
8644 if (This
->typeinfos
)
8645 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8646 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8648 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8650 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8652 info
->pTypeLib
= This
;
8653 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8654 info
->index
= This
->TypeInfoCount
;
8655 info
->typekind
= kind
;
8656 info
->cbAlignment
= 4;
8658 switch(info
->typekind
) {
8660 case TKIND_INTERFACE
:
8661 case TKIND_DISPATCH
:
8663 info
->cbSizeInstance
= This
->ptr_size
;
8667 info
->cbSizeInstance
= 0;
8670 info
->cbSizeInstance
= 2;
8673 info
->cbSizeInstance
= -0x75;
8676 FIXME("unrecognized typekind %d\n", info
->typekind
);
8677 info
->cbSizeInstance
= 0xdeadbeef;
8681 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8682 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8684 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8688 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8690 ++This
->TypeInfoCount
;
8695 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8698 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8700 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8703 return E_INVALIDARG
;
8705 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8710 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8711 WORD majorVerNum
, WORD minorVerNum
)
8713 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8715 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8717 This
->ver_major
= majorVerNum
;
8718 This
->ver_minor
= minorVerNum
;
8723 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8726 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8728 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8730 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8735 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8738 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8740 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8743 return E_INVALIDARG
;
8745 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8750 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8751 LPOLESTR helpFileName
)
8753 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8755 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8758 return E_INVALIDARG
;
8760 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8765 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8768 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8770 TRACE("%p %d\n", This
, helpContext
);
8772 This
->dwHelpContext
= helpContext
;
8777 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8780 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8782 TRACE("%p %x\n", This
, lcid
);
8784 This
->set_lcid
= lcid
;
8789 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8792 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8794 TRACE("%p %x\n", This
, libFlags
);
8796 This
->libflags
= libFlags
;
8801 typedef struct tagWMSFT_SegContents
{
8804 } WMSFT_SegContents
;
8806 typedef struct tagWMSFT_TLBFile
{
8808 WMSFT_SegContents typeinfo_seg
;
8809 WMSFT_SegContents impfile_seg
;
8810 WMSFT_SegContents impinfo_seg
;
8811 WMSFT_SegContents ref_seg
;
8812 WMSFT_SegContents guidhash_seg
;
8813 WMSFT_SegContents guid_seg
;
8814 WMSFT_SegContents namehash_seg
;
8815 WMSFT_SegContents name_seg
;
8816 WMSFT_SegContents string_seg
;
8817 WMSFT_SegContents typdesc_seg
;
8818 WMSFT_SegContents arraydesc_seg
;
8819 WMSFT_SegContents custdata_seg
;
8820 WMSFT_SegContents cdguids_seg
;
8822 WMSFT_SegContents aux_seg
;
8825 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8826 WMSFT_TLBFile
*file
)
8832 file
->string_seg
.len
= 0;
8833 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8836 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8838 return E_UNEXPECTED
;
8840 size
+= sizeof(INT16
);
8842 size
= (size
+ 4) & ~0x3;
8846 file
->string_seg
.len
+= size
;
8848 /* temporarily use str->offset to store the length of the aligned,
8849 * converted string */
8853 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8856 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8859 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8860 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8862 heap_free(file
->string_seg
.data
);
8863 return E_UNEXPECTED
;
8866 *((INT16
*)data
) = size
;
8868 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8872 str
->offset
= last_offs
;
8879 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8880 WMSFT_TLBFile
*file
)
8885 MSFT_NameIntro
*last_intro
= NULL
;
8887 file
->header
.nametablecount
= 0;
8888 file
->header
.nametablechars
= 0;
8890 file
->name_seg
.len
= 0;
8891 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8894 size
= strlenW(str
->str
);
8895 file
->header
.nametablechars
+= size
;
8896 file
->header
.nametablecount
++;
8898 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8900 return E_UNEXPECTED
;
8902 size
+= sizeof(MSFT_NameIntro
);
8904 size
= (size
+ 4) & ~0x3;
8908 file
->name_seg
.len
+= size
;
8910 /* temporarily use str->offset to store the length of the aligned,
8911 * converted string */
8915 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8916 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8919 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8921 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8923 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8924 data
+ sizeof(MSFT_NameIntro
),
8925 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8927 heap_free(file
->name_seg
.data
);
8928 return E_UNEXPECTED
;
8930 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8932 intro
->hreftype
= -1; /* TODO? */
8933 intro
->namelen
= size
& 0xFF;
8934 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8935 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8936 intro
->namelen
|= hash
<< 16;
8937 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8938 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
8940 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8941 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8943 /* update str->offset to actual value to use in other
8944 * compilation functions that require positions within
8945 * the string table */
8949 str
->offset
= last_offs
;
8954 last_intro
->hreftype
= 0; /* last one is 0? */
8959 static inline int hash_guid(GUID
*guid
)
8963 for (i
= 0; i
< 8; i
++)
8964 hash
^= ((const short *)guid
)[i
];
8969 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8972 MSFT_GuidEntry
*entry
;
8974 int hash_key
, *guidhashtab
;
8976 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8977 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8979 entry
= file
->guid_seg
.data
;
8981 guidhashtab
= file
->guidhash_seg
.data
;
8982 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
8983 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
8984 entry
->hreftype
= guid
->hreftype
;
8986 hash_key
= hash_guid(&guid
->guid
);
8987 entry
->next_hash
= guidhashtab
[hash_key
];
8988 guidhashtab
[hash_key
] = offs
;
8990 guid
->offset
= offs
;
8991 offs
+= sizeof(MSFT_GuidEntry
);
8998 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9001 VARTYPE arg_type
= V_VT(value
);
9004 DWORD ret
= file
->custdata_seg
.len
;
9006 if(arg_type
== VT_INT
)
9008 if(arg_type
== VT_UINT
)
9012 if(V_VT(value
) != arg_type
) {
9013 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9015 ERR("VariantChangeType failed: %08x\n", hres
);
9020 /* Check if default value can be stored in-place */
9025 if(V_UI4(&v
) > 0x3ffffff)
9038 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9041 /* have to allocate space in custdata_seg */
9050 /* Construct the data to be allocated */
9053 if(file
->custdata_seg
.data
){
9054 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9055 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9056 file
->custdata_seg
.len
+= sizeof(int) * 2;
9058 file
->custdata_seg
.len
= sizeof(int) * 2;
9059 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9062 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9063 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9065 /* TODO: Check if the encoded data is already present in custdata_seg */
9071 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9074 if(file
->custdata_seg
.data
){
9075 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9076 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9077 file
->custdata_seg
.len
+= len
;
9079 file
->custdata_seg
.len
= len
;
9080 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9083 *((unsigned short *)data
) = V_VT(value
);
9084 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9085 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9086 if(V_BSTR(&v
)[i
] <= 0x7f)
9087 data
[i
+6] = V_BSTR(&v
)[i
];
9091 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9092 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9095 /* TODO: Check if the encoded data is already present in custdata_seg */
9100 FIXME("Argument type not yet handled\n");
9105 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9107 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9109 DWORD offs
= file
->arraydesc_seg
.len
;
9113 /* TODO: we should check for duplicates, but that's harder because each
9114 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9115 * at the library-level) */
9117 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9118 if(!file
->arraydesc_seg
.data
)
9119 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9121 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9122 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
9124 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9125 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9126 for(i
= 0; i
< desc
->cDims
; ++i
){
9127 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9128 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9134 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9140 VARTYPE vt
, subtype
;
9151 vt
= desc
->vt
& VT_TYPEMASK
;
9153 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9155 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9156 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9158 *out_size
+= 2 * sizeof(DWORD
);
9159 }else if(vt
== VT_CARRAY
){
9160 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9161 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9163 }else if(vt
== VT_USERDEFINED
){
9164 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9165 encoded
[1] = desc
->u
.hreftype
;
9166 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9168 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9186 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9189 data
= file
->typdesc_seg
.data
;
9190 while(offs
< file
->typdesc_seg
.len
){
9191 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9193 offs
+= sizeof(encoded
);
9196 file
->typdesc_seg
.len
+= sizeof(encoded
);
9197 if(!file
->typdesc_seg
.data
)
9198 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9200 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9202 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9207 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9209 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9210 DWORD ret
= cdguids_seg
->len
, offs
;
9211 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9214 if(list_empty(custdata_list
))
9217 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9218 if(!cdguids_seg
->data
){
9219 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9221 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9223 offs
= ret
+ sizeof(MSFT_CDGuid
);
9224 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9225 cdguid
->GuidOffset
= cd
->guid
->offset
;
9226 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9227 cdguid
->next
= offs
;
9228 offs
+= sizeof(MSFT_CDGuid
);
9238 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9239 WMSFT_TLBFile
*file
)
9241 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9242 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9243 MSFT_VarRecord
*varrecord
;
9244 MSFT_FuncRecord
*funcrecord
;
9246 DWORD
*name
, *offsets
, offs
;
9248 for(i
= 0; i
< info
->cFuncs
; ++i
){
9249 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9251 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9253 /* optional fields */
9254 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9255 if(!list_empty(&desc
->custdata_list
))
9256 recorded_size
+= 7 * sizeof(INT
);
9257 else if(desc
->HelpStringContext
!= 0)
9258 recorded_size
+= 6 * sizeof(INT
);
9260 else if(desc
->Entry
)
9261 recorded_size
+= 3 * sizeof(INT
);
9262 else if(desc
->HelpString
)
9263 recorded_size
+= 2 * sizeof(INT
);
9264 else if(desc
->helpcontext
)
9265 recorded_size
+= sizeof(INT
);
9267 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9269 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9270 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9271 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9276 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9279 for(i
= 0; i
< info
->cVars
; ++i
){
9280 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9282 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9284 /* optional fields */
9285 if(desc
->HelpStringContext
!= 0)
9286 recorded_size
+= 5 * sizeof(INT
);
9287 else if(!list_empty(&desc
->custdata_list
))
9288 recorded_size
+= 4 * sizeof(INT
);
9290 else if(desc
->HelpString
)
9291 recorded_size
+= 2 * sizeof(INT
);
9292 else if(desc
->HelpContext
!= 0)
9293 recorded_size
+= sizeof(INT
);
9295 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9298 if(!recorded_size
&& !extra_size
)
9301 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9303 aux_seg
->len
+= recorded_size
+ extra_size
;
9305 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9308 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9310 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9312 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9314 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9317 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9318 for(i
= 0; i
< info
->cFuncs
; ++i
){
9319 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9320 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9322 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9323 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9324 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9325 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9328 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9333 * ^has_param_defaults
9334 * ^oEntry_is_intresource
9336 funcrecord
->FKCCIC
=
9337 desc
->funcdesc
.funckind
|
9338 (desc
->funcdesc
.invkind
<< 3) |
9339 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9340 (desc
->funcdesc
.callconv
<< 8);
9342 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9343 funcrecord
->FKCCIC
|= 0x2000;
9345 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9346 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9347 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9348 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9351 if(paramdefault_size
> 0)
9352 funcrecord
->FKCCIC
|= 0x1000;
9354 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9355 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9357 /* optional fields */
9359 if(!list_empty(&desc
->custdata_list
)){
9360 size
+= 7 * sizeof(INT
);
9361 funcrecord
->HelpContext
= desc
->helpcontext
;
9362 if(desc
->HelpString
)
9363 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9365 funcrecord
->oHelpString
= -1;
9367 funcrecord
->oEntry
= -1;
9368 else if(IS_INTRESOURCE(desc
->Entry
))
9369 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9371 funcrecord
->oEntry
= desc
->Entry
->offset
;
9372 funcrecord
->res9
= -1;
9373 funcrecord
->resA
= -1;
9374 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9375 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9376 }else if(desc
->HelpStringContext
!= 0){
9377 size
+= 6 * sizeof(INT
);
9378 funcrecord
->HelpContext
= desc
->helpcontext
;
9379 if(desc
->HelpString
)
9380 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9382 funcrecord
->oHelpString
= -1;
9384 funcrecord
->oEntry
= -1;
9385 else if(IS_INTRESOURCE(desc
->Entry
))
9386 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9388 funcrecord
->oEntry
= desc
->Entry
->offset
;
9389 funcrecord
->res9
= -1;
9390 funcrecord
->resA
= -1;
9391 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9392 }else if(desc
->Entry
){
9393 size
+= 3 * sizeof(INT
);
9394 funcrecord
->HelpContext
= desc
->helpcontext
;
9395 if(desc
->HelpString
)
9396 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9398 funcrecord
->oHelpString
= -1;
9400 funcrecord
->oEntry
= -1;
9401 else if(IS_INTRESOURCE(desc
->Entry
))
9402 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9404 funcrecord
->oEntry
= desc
->Entry
->offset
;
9405 }else if(desc
->HelpString
){
9406 size
+= 2 * sizeof(INT
);
9407 funcrecord
->HelpContext
= desc
->helpcontext
;
9408 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9409 }else if(desc
->helpcontext
){
9410 size
+= sizeof(INT
);
9411 funcrecord
->HelpContext
= desc
->helpcontext
;
9414 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9415 size
+= paramdefault_size
;
9417 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9418 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9420 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9421 if(desc
->pParamDesc
[j
].Name
)
9422 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9425 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9427 if(paramdefault_size
){
9428 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9429 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9430 else if(paramdefault_size
)
9435 size
+= sizeof(MSFT_ParameterInfo
);
9438 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9444 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9447 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9448 for(i
= 0; i
< info
->cVars
; ++i
){
9449 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9450 DWORD size
= 5 * sizeof(INT
);
9452 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9453 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9454 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9455 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9457 if(desc
->vardesc
.varkind
== VAR_CONST
){
9458 varrecord
->vardescsize
+= sizeof(VARIANT
);
9459 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9461 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9464 if(desc
->HelpStringContext
!= 0){
9465 size
+= 5 * sizeof(INT
);
9466 varrecord
->HelpContext
= desc
->HelpContext
;
9467 if(desc
->HelpString
)
9468 varrecord
->HelpString
= desc
->HelpString
->offset
;
9470 varrecord
->HelpString
= -1;
9471 varrecord
->res9
= -1;
9472 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9473 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9474 }else if(!list_empty(&desc
->custdata_list
)){
9475 size
+= 4 * sizeof(INT
);
9476 varrecord
->HelpContext
= desc
->HelpContext
;
9477 if(desc
->HelpString
)
9478 varrecord
->HelpString
= desc
->HelpString
->offset
;
9480 varrecord
->HelpString
= -1;
9481 varrecord
->res9
= -1;
9482 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9483 }else if(desc
->HelpString
){
9484 size
+= 2 * sizeof(INT
);
9485 varrecord
->HelpContext
= desc
->HelpContext
;
9486 if(desc
->HelpString
)
9487 varrecord
->HelpString
= desc
->HelpString
->offset
;
9489 varrecord
->HelpString
= -1;
9490 }else if(desc
->HelpContext
!= 0){
9491 size
+= sizeof(INT
);
9492 varrecord
->HelpContext
= desc
->HelpContext
;
9495 varrecord
->Info
= size
| (i
<< 16);
9501 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9504 memid
= (MEMBERID
*)varrecord
;
9505 for(i
= 0; i
< info
->cFuncs
; ++i
){
9506 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9507 *memid
= desc
->funcdesc
.memid
;
9510 for(i
= 0; i
< info
->cVars
; ++i
){
9511 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9512 *memid
= desc
->vardesc
.memid
;
9516 name
= (UINT
*)memid
;
9517 for(i
= 0; i
< info
->cFuncs
; ++i
){
9518 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9520 *name
= desc
->Name
->offset
;
9525 for(i
= 0; i
< info
->cVars
; ++i
){
9526 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9528 *name
= desc
->Name
->offset
;
9537 typedef struct tagWMSFT_RefChunk
{
9544 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9546 DWORD offs
= file
->ref_seg
.len
, i
;
9547 WMSFT_RefChunk
*chunk
;
9549 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9550 if(!file
->ref_seg
.data
)
9551 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9553 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9555 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9557 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9558 chunk
->href
= info
->impltypes
[i
].hRef
;
9559 chunk
->res04
= info
->impltypes
[i
].implflags
;
9561 if(i
< info
->cImplTypes
- 1)
9562 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9571 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9575 size
= sizeof(MSFT_TypeInfoBase
);
9578 MSFT_TypeInfoBase
*base
= (void*)data
;
9579 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9580 base
->typekind
= TKIND_DISPATCH
;
9582 base
->typekind
= info
->typekind
;
9583 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9584 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9585 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9590 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9596 base
->posguid
= info
->guid
->offset
;
9599 base
->flags
= info
->wTypeFlags
;
9601 base
->NameOffset
= info
->Name
->offset
;
9603 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9604 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9606 base
->NameOffset
= -1;
9608 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9610 base
->docstringoffs
= info
->DocString
->offset
;
9612 base
->docstringoffs
= -1;
9613 base
->helpstringcontext
= info
->dwHelpStringContext
;
9614 base
->helpcontext
= info
->dwHelpContext
;
9615 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9616 base
->cImplTypes
= info
->cImplTypes
;
9617 base
->cbSizeVft
= info
->cbSizeVft
;
9618 base
->size
= info
->cbSizeInstance
;
9619 if(info
->typekind
== TKIND_COCLASS
){
9620 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9621 }else if(info
->typekind
== TKIND_ALIAS
){
9622 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9623 }else if(info
->typekind
== TKIND_MODULE
){
9625 base
->datatype1
= info
->DllName
->offset
;
9627 base
->datatype1
= -1;
9629 if(info
->cImplTypes
> 0)
9630 base
->datatype1
= info
->impltypes
[0].hRef
;
9632 base
->datatype1
= -1;
9634 base
->datatype2
= index
; /* FIXME: i think there's more here */
9642 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9646 file
->typeinfo_seg
.len
= 0;
9647 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9648 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9649 *junk
= file
->typeinfo_seg
.len
;
9651 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9654 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9655 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9657 file
->aux_seg
.len
= 0;
9658 file
->aux_seg
.data
= NULL
;
9660 file
->typeinfo_seg
.len
= 0;
9661 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9662 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9663 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9664 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9668 typedef struct tagWMSFT_ImpFile
{
9674 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9677 WMSFT_ImpFile
*impfile
;
9679 DWORD last_offs
= 0;
9681 file
->impfile_seg
.len
= 0;
9682 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9686 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9690 path
= implib
->name
;
9691 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9693 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9696 size
+= sizeof(INT16
);
9698 size
= (size
+ 4) & ~0x3;
9702 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9705 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9707 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9708 int strlen
= 0, size
;
9710 impfile
= (WMSFT_ImpFile
*)data
;
9711 impfile
->guid_offs
= implib
->guid
->offset
;
9712 impfile
->lcid
= implib
->lcid
;
9713 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9715 data
+= sizeof(WMSFT_ImpFile
);
9718 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9722 path
= implib
->name
;
9723 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9724 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9726 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9729 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9731 size
= strlen
+ sizeof(INT16
);
9733 size
= (size
+ 4) & ~0x3;
9736 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9739 implib
->offset
= last_offs
;
9740 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9744 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9747 TLBRefType
*ref_type
;
9750 WMSFT_compile_impfile(This
, file
);
9752 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9753 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9755 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9756 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9757 if(ref_type
->index
== TLB_REF_USE_GUID
){
9758 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9759 info
->oGuid
= ref_type
->guid
->offset
;
9761 info
->oGuid
= ref_type
->index
;
9762 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9768 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9770 file
->guidhash_seg
.len
= 0x80;
9771 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9772 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9775 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9777 file
->namehash_seg
.len
= 0x200;
9778 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9779 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9782 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9784 if(contents
&& contents
->len
){
9785 segdir
->offset
= *running_offset
;
9786 segdir
->length
= contents
->len
;
9787 *running_offset
+= segdir
->length
;
9789 segdir
->offset
= -1;
9793 /* TODO: do these ever change? */
9795 segdir
->res0c
= 0xf;
9798 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9802 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9805 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9809 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9811 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9812 base
->memoffset
+= file_len
;
9819 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9821 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9822 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9823 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9824 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9825 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9826 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9827 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9828 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9829 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9830 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9831 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9832 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9833 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9834 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9837 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9839 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9841 DWORD written
, junk_size
, junk_offs
, running_offset
;
9848 TRACE("%p\n", This
);
9850 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9851 if(This
->typeinfos
[i
]->needs_layout
)
9852 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9854 memset(&file
, 0, sizeof(file
));
9856 file
.header
.magic1
= 0x5446534D;
9857 file
.header
.magic2
= 0x00010002;
9858 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9859 file
.header
.lcid2
= This
->set_lcid
;
9860 file
.header
.varflags
= 0x40 | This
->syskind
;
9862 file
.header
.varflags
|= 0x10;
9863 if (This
->HelpStringDll
)
9864 file
.header
.varflags
|= HELPDLLFLAG
;
9865 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9866 file
.header
.flags
= This
->libflags
;
9867 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9868 file
.header
.helpcontext
= This
->dwHelpContext
;
9869 file
.header
.res44
= 0x20;
9870 file
.header
.res48
= 0x80;
9871 file
.header
.dispatchpos
= This
->dispatch_href
;
9873 WMSFT_compile_namehash(This
, &file
);
9874 /* do name and string compilation to get offsets for other compilations */
9875 hres
= WMSFT_compile_names(This
, &file
);
9877 WMSFT_free_file(&file
);
9881 hres
= WMSFT_compile_strings(This
, &file
);
9883 WMSFT_free_file(&file
);
9887 WMSFT_compile_guidhash(This
, &file
);
9888 hres
= WMSFT_compile_guids(This
, &file
);
9890 WMSFT_free_file(&file
);
9895 file
.header
.helpfile
= This
->HelpFile
->offset
;
9897 file
.header
.helpfile
= -1;
9900 file
.header
.helpstring
= This
->DocString
->offset
;
9902 file
.header
.helpstring
= -1;
9904 /* do some more segment compilation */
9905 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9906 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9909 file
.header
.NameOffset
= This
->Name
->offset
;
9911 file
.header
.NameOffset
= -1;
9913 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9916 file
.header
.posguid
= This
->guid
->offset
;
9918 file
.header
.posguid
= -1;
9920 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9921 if(file
.header
.varflags
& HELPDLLFLAG
)
9922 junk_size
+= sizeof(DWORD
);
9924 junk
= heap_alloc_zero(junk_size
);
9925 if(file
.header
.varflags
& HELPDLLFLAG
){
9926 *junk
= This
->HelpStringDll
->offset
;
9935 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9936 WMSFT_compile_impinfo(This
, &file
);
9940 TRACE("header at: 0x%x\n", running_offset
);
9941 running_offset
+= sizeof(file
.header
);
9943 TRACE("junk at: 0x%x\n", running_offset
);
9944 running_offset
+= junk_size
;
9946 TRACE("segdir at: 0x%x\n", running_offset
);
9947 running_offset
+= sizeof(file
.segdir
);
9949 TRACE("typeinfo at: 0x%x\n", running_offset
);
9950 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9952 TRACE("guidhashtab at: 0x%x\n", running_offset
);
9953 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
9955 TRACE("guidtab at: 0x%x\n", running_offset
);
9956 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9958 TRACE("reftab at: 0x%x\n", running_offset
);
9959 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9961 TRACE("impinfo at: 0x%x\n", running_offset
);
9962 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9964 TRACE("impfiles at: 0x%x\n", running_offset
);
9965 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9967 TRACE("namehashtab at: 0x%x\n", running_offset
);
9968 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
9970 TRACE("nametab at: 0x%x\n", running_offset
);
9971 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9973 TRACE("stringtab at: 0x%x\n", running_offset
);
9974 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9976 TRACE("typdesc at: 0x%x\n", running_offset
);
9977 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
9979 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
9980 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
9982 TRACE("custdata at: 0x%x\n", running_offset
);
9983 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
9985 TRACE("cdguids at: 0x%x\n", running_offset
);
9986 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
9988 TRACE("res0e at: 0x%x\n", running_offset
);
9989 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
9991 TRACE("res0f at: 0x%x\n", running_offset
);
9992 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
9994 TRACE("aux_seg at: 0x%x\n", running_offset
);
9996 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
9998 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
9999 FILE_ATTRIBUTE_NORMAL
, 0);
10000 if (outfile
== INVALID_HANDLE_VALUE
){
10001 WMSFT_free_file(&file
);
10003 return TYPE_E_IOERROR
;
10006 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10008 WMSFT_free_file(&file
);
10009 CloseHandle(outfile
);
10011 return TYPE_E_IOERROR
;
10014 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10017 WMSFT_free_file(&file
);
10018 CloseHandle(outfile
);
10019 return TYPE_E_IOERROR
;
10022 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10024 WMSFT_free_file(&file
);
10025 CloseHandle(outfile
);
10026 return TYPE_E_IOERROR
;
10029 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10030 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10031 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10032 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10033 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10034 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10035 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10036 WMSFT_write_segment(outfile
, &file
.name_seg
);
10037 WMSFT_write_segment(outfile
, &file
.string_seg
);
10038 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10039 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10040 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10041 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10042 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10044 WMSFT_free_file(&file
);
10046 CloseHandle(outfile
);
10051 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10054 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10055 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10059 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10060 REFGUID guid
, VARIANT
*varVal
)
10062 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10063 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10067 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10068 ULONG helpStringContext
)
10070 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10071 FIXME("%p %u - stub\n", This
, helpStringContext
);
10075 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10078 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10079 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10082 return E_INVALIDARG
;
10084 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10089 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10090 ICreateTypeLib2_fnQueryInterface
,
10091 ICreateTypeLib2_fnAddRef
,
10092 ICreateTypeLib2_fnRelease
,
10093 ICreateTypeLib2_fnCreateTypeInfo
,
10094 ICreateTypeLib2_fnSetName
,
10095 ICreateTypeLib2_fnSetVersion
,
10096 ICreateTypeLib2_fnSetGuid
,
10097 ICreateTypeLib2_fnSetDocString
,
10098 ICreateTypeLib2_fnSetHelpFileName
,
10099 ICreateTypeLib2_fnSetHelpContext
,
10100 ICreateTypeLib2_fnSetLcid
,
10101 ICreateTypeLib2_fnSetLibFlags
,
10102 ICreateTypeLib2_fnSaveAllChanges
,
10103 ICreateTypeLib2_fnDeleteTypeInfo
,
10104 ICreateTypeLib2_fnSetCustData
,
10105 ICreateTypeLib2_fnSetHelpStringContext
,
10106 ICreateTypeLib2_fnSetHelpStringDll
10109 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10110 REFIID riid
, void **object
)
10112 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10114 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10117 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10119 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10121 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10124 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10126 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10128 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10131 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10134 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10136 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10138 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10143 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10146 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10150 TRACE("%p %x\n", This
, typeFlags
);
10152 if (typeFlags
& TYPEFLAG_FDUAL
) {
10153 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10155 ITypeInfo
*dispatch
;
10159 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10163 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10164 ITypeLib_Release(stdole
);
10168 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10169 ITypeInfo_Release(dispatch
);
10174 old_flags
= This
->wTypeFlags
;
10175 This
->wTypeFlags
= typeFlags
;
10177 hres
= ICreateTypeInfo2_LayOut(iface
);
10178 if (FAILED(hres
)) {
10179 This
->wTypeFlags
= old_flags
;
10186 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10189 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10191 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10194 return E_INVALIDARG
;
10196 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10201 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10204 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10206 TRACE("%p %d\n", This
, helpContext
);
10208 This
->dwHelpContext
= helpContext
;
10213 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10214 WORD majorVerNum
, WORD minorVerNum
)
10216 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10218 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10220 This
->wMajorVerNum
= majorVerNum
;
10221 This
->wMinorVerNum
= minorVerNum
;
10226 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10227 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10229 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10231 ITypeLib
*container
;
10232 TLBRefType
*ref_type
;
10234 TYPEATTR
*typeattr
;
10238 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10240 if (!typeInfo
|| !refType
)
10241 return E_INVALIDARG
;
10243 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10247 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10248 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10250 ITypeLib_Release(container
);
10252 *refType
= target
->hreftype
;
10257 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10258 if (FAILED(hres
)) {
10259 ITypeLib_Release(container
);
10263 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10264 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10265 implib
->lcid
== libattr
->lcid
&&
10266 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10267 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10271 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10272 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10274 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10275 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10276 implib
->name
= SysAllocString(our_container
->path
);
10278 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10279 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10281 implib
->name
= NULL
;
10282 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10286 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10287 implib
->lcid
= libattr
->lcid
;
10288 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10289 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10291 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10294 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10295 ITypeLib_Release(container
);
10297 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10302 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10303 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10304 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10305 ref_type
->tkind
== typeattr
->typekind
)
10310 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10311 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10313 ref_type
->tkind
= typeattr
->typekind
;
10314 ref_type
->pImpTLInfo
= implib
;
10315 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10317 ref_type
->index
= TLB_REF_USE_GUID
;
10319 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10321 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10324 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10326 *refType
= ref_type
->reference
| 0x1;
10328 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10329 This
->pTypeLib
->dispatch_href
= *refType
;
10334 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10335 UINT index
, FUNCDESC
*funcDesc
)
10337 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10338 TLBFuncDesc tmp_func_desc
, *func_desc
;
10343 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10345 if (!funcDesc
|| funcDesc
->oVft
& 3)
10346 return E_INVALIDARG
;
10348 switch (This
->typekind
) {
10350 if (funcDesc
->funckind
!= FUNC_STATIC
)
10351 return TYPE_E_BADMODULEKIND
;
10353 case TKIND_DISPATCH
:
10354 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10355 return TYPE_E_BADMODULEKIND
;
10358 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10359 return TYPE_E_BADMODULEKIND
;
10362 if (index
> This
->cFuncs
)
10363 return TYPE_E_ELEMENTNOTFOUND
;
10365 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10366 !funcDesc
->cParams
)
10367 return TYPE_E_INCONSISTENTPROPFUNCS
;
10370 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10371 funcDesc
->oVft
% 8 != 0)
10372 return E_INVALIDARG
;
10375 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10376 TLBFuncDesc_Constructor(&tmp_func_desc
);
10378 tmp_func_desc
.funcdesc
= *funcDesc
;
10380 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10381 tmp_func_desc
.funcdesc
.oVft
|= 1;
10383 if (funcDesc
->cScodes
) {
10384 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10385 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10387 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10389 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10390 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10391 buf_size
+= sizeof(ELEMDESC
);
10392 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10394 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10395 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10397 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10398 if (FAILED(hres
)) {
10399 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10400 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10404 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10405 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10406 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10407 if (FAILED(hres
)) {
10408 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10409 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10412 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10413 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10414 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10415 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10416 if (FAILED(hres
)) {
10417 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10418 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10424 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10426 if (This
->funcdescs
) {
10427 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10428 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10430 if (index
< This
->cFuncs
) {
10431 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10432 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10433 func_desc
= This
->funcdescs
+ index
;
10435 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10437 /* move custdata lists to the new memory location */
10438 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10440 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10441 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10442 list_init(&fd
->custdata_list
);
10444 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10445 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10450 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10452 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10453 list_init(&func_desc
->custdata_list
);
10457 This
->needs_layout
= TRUE
;
10462 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10463 UINT index
, HREFTYPE refType
)
10465 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10466 TLBImplType
*impl_type
;
10469 TRACE("%p %u %d\n", This
, index
, refType
);
10471 switch(This
->typekind
){
10472 case TKIND_COCLASS
: {
10474 FIXME("Unhandled index: -1\n");
10478 if(index
!= This
->cImplTypes
)
10479 return TYPE_E_ELEMENTNOTFOUND
;
10483 case TKIND_INTERFACE
:
10484 case TKIND_DISPATCH
:
10485 if (index
!= 0 || This
->cImplTypes
)
10486 return TYPE_E_ELEMENTNOTFOUND
;
10489 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10493 if (This
->impltypes
){
10496 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10497 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10499 if (index
< This
->cImplTypes
) {
10500 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10501 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10502 impl_type
= This
->impltypes
+ index
;
10504 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10506 /* move custdata lists to the new memory location */
10507 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10509 TLBImplType
*it
= &This
->impltypes
[i
];
10510 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10511 list_init(&it
->custdata_list
);
10513 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10514 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10519 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10521 memset(impl_type
, 0, sizeof(TLBImplType
));
10522 TLBImplType_Constructor(impl_type
);
10523 impl_type
->hRef
= refType
;
10525 ++This
->cImplTypes
;
10527 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10528 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10530 hres
= ICreateTypeInfo2_LayOut(iface
);
10537 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10538 UINT index
, INT implTypeFlags
)
10540 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10541 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10543 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10545 if (This
->typekind
!= TKIND_COCLASS
)
10546 return TYPE_E_BADMODULEKIND
;
10548 if (index
>= This
->cImplTypes
)
10549 return TYPE_E_ELEMENTNOTFOUND
;
10551 impl_type
->implflags
= implTypeFlags
;
10556 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10559 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10561 TRACE("%p %d\n", This
, alignment
);
10563 This
->cbAlignment
= alignment
;
10568 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10571 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10573 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10576 return E_INVALIDARG
;
10578 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10580 This
->lpstrSchema
= This
->Schema
->str
;
10585 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10586 UINT index
, VARDESC
*varDesc
)
10588 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10589 TLBVarDesc
*var_desc
;
10591 TRACE("%p %u %p\n", This
, index
, varDesc
);
10593 if (This
->vardescs
){
10596 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10597 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10599 if (index
< This
->cVars
) {
10600 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10601 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10602 var_desc
= This
->vardescs
+ index
;
10604 var_desc
= This
->vardescs
+ This
->cVars
;
10606 /* move custdata lists to the new memory location */
10607 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10609 TLBVarDesc
*var
= &This
->vardescs
[i
];
10610 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10611 list_init(&var
->custdata_list
);
10613 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10614 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10619 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10621 TLBVarDesc_Constructor(var_desc
);
10622 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10623 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10627 This
->needs_layout
= TRUE
;
10632 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10633 UINT index
, LPOLESTR
*names
, UINT numNames
)
10635 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10636 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10639 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10642 return E_INVALIDARG
;
10644 if (index
>= This
->cFuncs
|| numNames
== 0)
10645 return TYPE_E_ELEMENTNOTFOUND
;
10647 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10648 if(numNames
> func_desc
->funcdesc
.cParams
)
10649 return TYPE_E_ELEMENTNOTFOUND
;
10651 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10652 return TYPE_E_ELEMENTNOTFOUND
;
10654 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10655 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10656 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10657 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10658 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10659 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10661 return TYPE_E_AMBIGUOUSNAME
;
10665 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10667 for (i
= 1; i
< numNames
; ++i
) {
10668 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10669 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10675 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10676 UINT index
, LPOLESTR name
)
10678 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10680 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10683 return E_INVALIDARG
;
10685 if(index
>= This
->cVars
)
10686 return TYPE_E_ELEMENTNOTFOUND
;
10688 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10692 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10693 TYPEDESC
*tdescAlias
)
10695 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10698 TRACE("%p %p\n", This
, tdescAlias
);
10701 return E_INVALIDARG
;
10703 if(This
->typekind
!= TKIND_ALIAS
)
10704 return TYPE_E_BADMODULEKIND
;
10706 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10710 heap_free(This
->tdescAlias
);
10711 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10712 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10717 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10718 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10720 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10721 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10725 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10726 UINT index
, LPOLESTR docString
)
10728 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10729 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
10733 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10734 UINT index
, LPOLESTR docString
)
10736 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10737 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10739 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10742 return E_INVALIDARG
;
10744 if(index
>= This
->cVars
)
10745 return TYPE_E_ELEMENTNOTFOUND
;
10747 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10752 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10753 UINT index
, DWORD helpContext
)
10755 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10756 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10758 TRACE("%p %u %d\n", This
, index
, helpContext
);
10760 if(index
>= This
->cFuncs
)
10761 return TYPE_E_ELEMENTNOTFOUND
;
10763 func_desc
->helpcontext
= helpContext
;
10768 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10769 UINT index
, DWORD helpContext
)
10771 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10772 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10774 TRACE("%p %u %d\n", This
, index
, helpContext
);
10776 if(index
>= This
->cVars
)
10777 return TYPE_E_ELEMENTNOTFOUND
;
10779 var_desc
->HelpContext
= helpContext
;
10784 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10785 UINT index
, BSTR bstrMops
)
10787 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10788 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10792 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10795 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10797 TRACE("%p %p\n", This
, idlDesc
);
10800 return E_INVALIDARG
;
10802 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10803 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10808 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10810 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10812 TLBFuncDesc
*func_desc
;
10813 UINT user_vft
= 0, i
, depth
= 0;
10814 HRESULT hres
= S_OK
;
10816 TRACE("%p\n", This
);
10818 This
->needs_layout
= FALSE
;
10820 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10824 if (This
->typekind
== TKIND_INTERFACE
) {
10829 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10831 if (SUCCEEDED(hres
)) {
10832 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10834 if (SUCCEEDED(hres
)) {
10835 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10836 if (FAILED(hres
)) {
10837 ITypeInfo_Release(inh
);
10838 ITypeInfo_Release(tinfo
);
10841 This
->cbSizeVft
= attr
->cbSizeVft
;
10842 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10846 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10847 if(SUCCEEDED(hres
)){
10849 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10850 if(SUCCEEDED(hres
)){
10851 ITypeInfo_Release(inh
);
10855 }while(SUCCEEDED(hres
));
10858 ITypeInfo_Release(inh
);
10859 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10860 This
->cbSizeVft
= 0;
10863 ITypeInfo_Release(tinfo
);
10866 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10867 This
->cbSizeVft
= 0;
10870 ITypeInfo_Release(tinfo
);
10873 } else if (This
->typekind
== TKIND_DISPATCH
)
10874 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10876 This
->cbSizeVft
= 0;
10878 func_desc
= This
->funcdescs
;
10880 while (i
< This
->cFuncs
) {
10881 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10882 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10884 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10885 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10887 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10889 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10892 BOOL reset
= FALSE
;
10894 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10896 iter
= This
->funcdescs
;
10897 while (j
< This
->cFuncs
) {
10898 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10900 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10903 ++func_desc
->funcdesc
.memid
;
10904 iter
= This
->funcdescs
;
10917 if (user_vft
> This
->cbSizeVft
)
10918 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10920 for(i
= 0; i
< This
->cVars
; ++i
){
10921 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10922 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
10924 BOOL reset
= FALSE
;
10927 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
10929 iter
= This
->vardescs
;
10930 while (j
< This
->cVars
) {
10931 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
10933 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
10936 ++var_desc
->vardesc
.memid
;
10937 iter
= This
->vardescs
;
10947 ITypeInfo_Release(tinfo
);
10951 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10954 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10955 FIXME("%p %u - stub\n", This
, index
);
10959 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
10960 MEMBERID memid
, INVOKEKIND invKind
)
10962 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10963 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
10967 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
10970 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10971 FIXME("%p %u - stub\n", This
, index
);
10975 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
10978 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10979 FIXME("%p %x - stub\n", This
, memid
);
10983 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
10986 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10987 FIXME("%p %u - stub\n", This
, index
);
10991 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
10992 REFGUID guid
, VARIANT
*varVal
)
10996 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10998 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11000 if (!guid
|| !varVal
)
11001 return E_INVALIDARG
;
11003 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11005 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11008 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11009 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11011 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11012 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11016 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11017 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11019 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11020 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11024 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11025 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11027 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11028 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11032 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11033 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11035 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11036 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11040 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11041 ULONG helpStringContext
)
11043 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11045 TRACE("%p %u\n", This
, helpStringContext
);
11047 This
->dwHelpStringContext
= helpStringContext
;
11052 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11053 UINT index
, ULONG helpStringContext
)
11055 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11056 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11060 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11061 UINT index
, ULONG helpStringContext
)
11063 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11064 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11068 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11070 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11071 FIXME("%p - stub\n", This
);
11075 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11078 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11080 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11083 return E_INVALIDARG
;
11085 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11090 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11091 ICreateTypeInfo2_fnQueryInterface
,
11092 ICreateTypeInfo2_fnAddRef
,
11093 ICreateTypeInfo2_fnRelease
,
11094 ICreateTypeInfo2_fnSetGuid
,
11095 ICreateTypeInfo2_fnSetTypeFlags
,
11096 ICreateTypeInfo2_fnSetDocString
,
11097 ICreateTypeInfo2_fnSetHelpContext
,
11098 ICreateTypeInfo2_fnSetVersion
,
11099 ICreateTypeInfo2_fnAddRefTypeInfo
,
11100 ICreateTypeInfo2_fnAddFuncDesc
,
11101 ICreateTypeInfo2_fnAddImplType
,
11102 ICreateTypeInfo2_fnSetImplTypeFlags
,
11103 ICreateTypeInfo2_fnSetAlignment
,
11104 ICreateTypeInfo2_fnSetSchema
,
11105 ICreateTypeInfo2_fnAddVarDesc
,
11106 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11107 ICreateTypeInfo2_fnSetVarName
,
11108 ICreateTypeInfo2_fnSetTypeDescAlias
,
11109 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11110 ICreateTypeInfo2_fnSetFuncDocString
,
11111 ICreateTypeInfo2_fnSetVarDocString
,
11112 ICreateTypeInfo2_fnSetFuncHelpContext
,
11113 ICreateTypeInfo2_fnSetVarHelpContext
,
11114 ICreateTypeInfo2_fnSetMops
,
11115 ICreateTypeInfo2_fnSetTypeIdldesc
,
11116 ICreateTypeInfo2_fnLayOut
,
11117 ICreateTypeInfo2_fnDeleteFuncDesc
,
11118 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11119 ICreateTypeInfo2_fnDeleteVarDesc
,
11120 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11121 ICreateTypeInfo2_fnDeleteImplType
,
11122 ICreateTypeInfo2_fnSetCustData
,
11123 ICreateTypeInfo2_fnSetFuncCustData
,
11124 ICreateTypeInfo2_fnSetParamCustData
,
11125 ICreateTypeInfo2_fnSetVarCustData
,
11126 ICreateTypeInfo2_fnSetImplTypeCustData
,
11127 ICreateTypeInfo2_fnSetHelpStringContext
,
11128 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11129 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11130 ICreateTypeInfo2_fnInvalidate
,
11131 ICreateTypeInfo2_fnSetName
11134 /******************************************************************************
11135 * ClearCustData (OLEAUT32.171)
11137 * Clear a custom data type's data.
11140 * lpCust [I] The custom data type instance
11145 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11147 if (lpCust
&& lpCust
->cCustData
)
11149 if (lpCust
->prgCustData
)
11153 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11154 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11156 /* FIXME - Should be using a per-thread IMalloc */
11157 heap_free(lpCust
->prgCustData
);
11158 lpCust
->prgCustData
= NULL
;
11160 lpCust
->cCustData
= 0;