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
)
1895 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1896 if (strcmpW(str
->str
, new_str
) == 0)
1900 str
= heap_alloc(sizeof(TLBString
));
1904 str
->str
= SysAllocString(new_str
);
1910 list_add_tail(string_list
, &str
->entry
);
1915 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1916 ULONG
*size
, WORD
*align
)
1922 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1926 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1928 ITypeInfo_Release(other
);
1933 *size
= attr
->cbSizeInstance
;
1935 *align
= attr
->cbAlignment
;
1937 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1938 ITypeInfo_Release(other
);
1943 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1944 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1946 ULONG i
, sub
, ptr_size
;
1949 ptr_size
= get_ptr_size(sys
);
1988 *size
= sizeof(DATE
);
1991 *size
= sizeof(VARIANT
);
1993 if(sys
== SYS_WIN32
)
1994 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1998 *size
= sizeof(DECIMAL
);
2005 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2006 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2007 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2012 case VT_USERDEFINED
:
2013 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2015 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2029 /**********************************************************************
2031 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2033 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
2038 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2040 if (where
!= DO_NOT_SEEK
)
2042 where
+= pcx
->oStart
;
2043 if (where
> pcx
->length
)
2046 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2054 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2056 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2057 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2059 MSFT_Seek(pcx
, where
);
2060 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2061 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2066 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2071 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2072 FromLEDWords(buffer
, ret
);
2077 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2082 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2083 FromLEWords(buffer
, ret
);
2088 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2091 MSFT_GuidEntry entry
;
2094 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2096 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2099 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2101 guid
= heap_alloc(sizeof(TLBGuid
));
2103 guid
->offset
= offs
;
2104 guid
->guid
= entry
.guid
;
2105 guid
->hreftype
= entry
.hreftype
;
2107 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2109 offs
+= sizeof(MSFT_GuidEntry
);
2113 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2117 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2118 if(ret
->offset
== offset
){
2119 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2127 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2129 MSFT_NameIntro niName
;
2133 ERR_(typelib
)("bad offset %d\n", offset
);
2137 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2138 pcx
->pTblDir
->pNametab
.offset
+offset
);
2140 return niName
.hreftype
;
2143 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2146 MSFT_NameIntro intro
;
2148 int offs
= 0, lengthInChars
;
2150 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2154 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2157 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2158 intro
.namelen
&= 0xFF;
2159 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2161 len_piece
= (len_piece
+ 4) & ~0x3;
2165 string
= heap_alloc(len_piece
+ 1);
2166 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2167 string
[intro
.namelen
] = '\0';
2169 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2170 string
, -1, NULL
, 0);
2171 if (!lengthInChars
) {
2173 return E_UNEXPECTED
;
2176 tlbstr
= heap_alloc(sizeof(TLBString
));
2178 tlbstr
->offset
= offs
;
2179 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2180 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2184 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2190 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2194 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2195 if (tlbstr
->offset
== offset
) {
2196 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2204 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2208 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2209 if (tlbstr
->offset
== offset
) {
2210 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2219 * read a value and fill a VARIANT structure
2221 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2225 TRACE_(typelib
)("\n");
2227 if(offset
<0) { /* data are packed in here */
2228 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2229 V_I4(pVar
) = offset
& 0x3ffffff;
2232 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2233 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2234 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2235 switch (V_VT(pVar
)){
2236 case VT_EMPTY
: /* FIXME: is this right? */
2237 case VT_NULL
: /* FIXME: is this right? */
2238 case VT_I2
: /* this should not happen */
2249 case VT_VOID
: /* FIXME: is this right? */
2257 case VT_DECIMAL
: /* FIXME: is this right? */
2260 /* pointer types with known behaviour */
2263 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2265 V_BSTR(pVar
) = NULL
;
2267 ptr
= heap_alloc_zero(size
);
2268 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2269 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2270 /* FIXME: do we need a AtoW conversion here? */
2271 V_UNION(pVar
, bstrVal
[size
])='\0';
2272 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2277 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2284 case VT_USERDEFINED
:
2290 case VT_STREAMED_OBJECT
:
2291 case VT_STORED_OBJECT
:
2292 case VT_BLOB_OBJECT
:
2297 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2301 if(size
>0) /* (big|small) endian correct? */
2302 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2306 * create a linked list with custom data
2308 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2314 TRACE_(typelib
)("\n");
2316 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2320 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2321 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2322 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2323 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2324 list_add_head(custdata_list
, &pNew
->entry
);
2325 offset
= entry
.next
;
2330 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2333 pTd
->vt
=type
& VT_TYPEMASK
;
2335 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2337 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2340 static int TLB_is_propgetput(INVOKEKIND invkind
)
2342 return (invkind
== INVOKE_PROPERTYGET
||
2343 invkind
== INVOKE_PROPERTYPUT
||
2344 invkind
== INVOKE_PROPERTYPUTREF
);
2348 MSFT_DoFuncs(TLBContext
* pcx
,
2353 TLBFuncDesc
** pptfd
)
2356 * member information is stored in a data structure at offset
2357 * indicated by the memoffset field of the typeinfo structure
2358 * There are several distinctive parts.
2359 * The first part starts with a field that holds the total length
2360 * of this (first) part excluding this field. Then follow the records,
2361 * for each member there is one record.
2363 * The first entry is always the length of the record (including this
2365 * The rest of the record depends on the type of the member. If there is
2366 * a field indicating the member type (function, variable, interface, etc)
2367 * I have not found it yet. At this time we depend on the information
2368 * in the type info and the usual order how things are stored.
2370 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2373 * Third is an equal sized array with file offsets to the name entry
2376 * The fourth and last (?) part is an array with offsets to the records
2377 * in the first part of this file segment.
2380 int infolen
, nameoffset
, reclength
, i
;
2381 int recoffset
= offset
+ sizeof(INT
);
2383 char *recbuf
= heap_alloc(0xffff);
2384 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2385 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2387 TRACE_(typelib
)("\n");
2389 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2391 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2393 for ( i
= 0; i
< cFuncs
; i
++ )
2397 /* name, eventually add to a hash table */
2398 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2399 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2401 /* read the function information record */
2402 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2404 reclength
&= 0xffff;
2406 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2408 /* size without argument data */
2409 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2410 if (pFuncRec
->FKCCIC
& 0x1000)
2411 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2413 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2414 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2416 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2417 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2419 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2421 if (pFuncRec
->FKCCIC
& 0x2000 )
2423 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2424 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2425 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2428 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2431 ptfd
->Entry
= (TLBString
*)-1;
2433 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2434 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2436 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2437 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2439 /* fill the FuncDesc Structure */
2440 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2441 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2443 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2444 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2445 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2446 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2447 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2448 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2449 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2451 /* nameoffset is sometimes -1 on the second half of a propget/propput
2452 * pair of functions */
2453 if ((nameoffset
== -1) && (i
> 0) &&
2454 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2455 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2456 ptfd
->Name
= ptfd_prev
->Name
;
2458 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2462 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2464 /* do the parameters/arguments */
2465 if(pFuncRec
->nrargs
)
2468 MSFT_ParameterInfo paraminfo
;
2470 ptfd
->funcdesc
.lprgelemdescParam
=
2471 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2473 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2475 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2476 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2478 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2480 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2486 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2489 if (paraminfo
.oName
!= -1)
2490 ptfd
->pParamDesc
[j
].Name
=
2491 MSFT_ReadName( pcx
, paraminfo
.oName
);
2492 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2495 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2496 (pFuncRec
->FKCCIC
& 0x1000) )
2498 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2500 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2502 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2504 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2505 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2507 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2511 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2514 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2515 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2516 pFuncRec
->FKCCIC
& 0x80 )
2519 pFuncRec
->oArgCustData
[j
],
2520 &ptfd
->pParamDesc
[j
].custdata_list
);
2523 /* SEEK value = jump to offset,
2524 * from there jump to the end of record,
2525 * go back by (j-1) arguments
2527 MSFT_ReadLEDWords( ¶minfo
,
2528 sizeof(MSFT_ParameterInfo
), pcx
,
2529 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2530 * sizeof(MSFT_ParameterInfo
)));
2534 /* scode is not used: archaic win16 stuff FIXME: right? */
2535 ptfd
->funcdesc
.cScodes
= 0 ;
2536 ptfd
->funcdesc
.lprgscode
= NULL
;
2540 recoffset
+= reclength
;
2545 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2546 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2548 int infolen
, nameoffset
, reclength
;
2550 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2555 TRACE_(typelib
)("\n");
2557 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2558 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2559 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2560 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2561 recoffset
+= offset
+sizeof(INT
);
2562 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2563 /* name, eventually add to a hash table */
2564 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2565 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2566 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2567 /* read the variable information record */
2568 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2570 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2573 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2574 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2576 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2577 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2579 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2580 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2582 /* fill the VarDesc Structure */
2583 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2584 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2585 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2586 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2587 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2588 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2589 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2590 if(pVarRec
->VarKind
== VAR_CONST
){
2591 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2592 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2593 pVarRec
->OffsValue
, pcx
);
2595 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2596 recoffset
+= reclength
;
2600 /* process Implemented Interfaces of a com class */
2601 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2605 MSFT_RefRecord refrec
;
2608 TRACE_(typelib
)("\n");
2610 pTI
->impltypes
= TLBImplType_Alloc(count
);
2611 pImpl
= pTI
->impltypes
;
2612 for(i
=0;i
<count
;i
++){
2613 if(offset
<0) break; /* paranoia */
2614 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2615 pImpl
->hRef
= refrec
.reftype
;
2616 pImpl
->implflags
=refrec
.flags
;
2617 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2618 offset
=refrec
.onext
;
2624 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2625 * and some structures, and fix the alignment */
2626 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2628 if(info
->typekind
== TKIND_ALIAS
){
2629 switch(info
->tdescAlias
->vt
){
2637 info
->cbSizeInstance
= sizeof(void*);
2638 info
->cbAlignment
= sizeof(void*);
2641 case VT_USERDEFINED
:
2642 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2645 info
->cbSizeInstance
= sizeof(VARIANT
);
2646 info
->cbAlignment
= 8;
2648 if(info
->cbSizeInstance
< sizeof(void*))
2649 info
->cbAlignment
= info
->cbSizeInstance
;
2651 info
->cbAlignment
= sizeof(void*);
2654 }else if(info
->typekind
== TKIND_INTERFACE
||
2655 info
->typekind
== TKIND_DISPATCH
||
2656 info
->typekind
== TKIND_COCLASS
){
2657 info
->cbSizeInstance
= sizeof(void*);
2658 info
->cbAlignment
= sizeof(void*);
2664 * process a typeinfo record
2666 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2669 ITypeLibImpl
* pLibInfo
)
2671 MSFT_TypeInfoBase tiBase
;
2672 ITypeInfoImpl
*ptiRet
;
2674 TRACE_(typelib
)("count=%u\n", count
);
2676 ptiRet
= ITypeInfoImpl_Constructor();
2677 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2678 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2680 /* this is where we are coming from */
2681 ptiRet
->pTypeLib
= pLibInfo
;
2682 ptiRet
->index
=count
;
2684 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2685 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2686 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2687 ptiRet
->cbSizeInstance
=tiBase
.size
;
2688 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2689 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2690 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2691 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2692 ptiRet
->wTypeFlags
=tiBase
.flags
;
2693 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2694 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2695 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2696 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2697 if(ptiRet
->typekind
== TKIND_ALIAS
){
2699 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2700 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2701 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2705 /* IDLDESC idldescType; *//* never saw this one != zero */
2707 /* name, eventually add to a hash table */
2708 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2709 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2710 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2712 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2713 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2714 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2716 if (ptiRet
->typekind
== TKIND_MODULE
)
2717 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2719 /* note: InfoType's Help file and HelpStringDll come from the containing
2720 * library. Further HelpString and Docstring appear to be the same thing :(
2723 if(ptiRet
->cFuncs
>0 )
2724 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2726 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2728 if(ptiRet
->cVars
>0 )
2729 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2731 tiBase
.memoffset
, &ptiRet
->vardescs
);
2732 if(ptiRet
->cImplTypes
>0 ) {
2733 switch(ptiRet
->typekind
)
2736 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2739 case TKIND_DISPATCH
:
2740 /* This is not -1 when the interface is a non-base dual interface or
2741 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2742 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2746 if (tiBase
.datatype1
!= -1)
2748 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2749 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2753 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2754 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2758 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2760 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2761 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2762 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2763 typekind_desc
[ptiRet
->typekind
]);
2764 if (TRACE_ON(typelib
))
2765 dump_TypeInfo(ptiRet
);
2770 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2773 INT16 len_str
, len_piece
;
2774 int offs
= 0, lengthInChars
;
2776 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2780 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2783 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2784 len_piece
= len_str
+ sizeof(INT16
);
2786 len_piece
= (len_piece
+ 4) & ~0x3;
2790 string
= heap_alloc(len_piece
+ 1);
2791 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2792 string
[len_str
] = '\0';
2794 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2795 string
, -1, NULL
, 0);
2796 if (!lengthInChars
) {
2798 return E_UNEXPECTED
;
2801 tlbstr
= heap_alloc(sizeof(TLBString
));
2803 tlbstr
->offset
= offs
;
2804 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2805 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2809 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2815 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2820 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2821 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2822 MSFT_ImpInfo impinfo
;
2825 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2827 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2828 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2830 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2831 if(pImpLib
->offset
==impinfo
.oImpFile
)
2834 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2835 ref
->reference
= offs
;
2836 ref
->pImpTLInfo
= pImpLib
;
2837 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2838 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2839 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2840 ref
->index
= TLB_REF_USE_GUID
;
2842 ref
->index
= impinfo
.oGuid
;
2844 ERR("Cannot find a reference\n");
2845 ref
->reference
= -1;
2846 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2849 offs
+= sizeof(impinfo
);
2855 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2856 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2857 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2860 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2861 static CRITICAL_SECTION cache_section
;
2862 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2864 0, 0, &cache_section
,
2865 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2866 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2868 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2871 typedef struct TLB_PEFile
2873 IUnknown IUnknown_iface
;
2876 HRSRC typelib_resource
;
2877 HGLOBAL typelib_global
;
2878 LPVOID typelib_base
;
2881 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2883 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2886 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2888 if (IsEqualIID(riid
, &IID_IUnknown
))
2891 IUnknown_AddRef(iface
);
2895 return E_NOINTERFACE
;
2898 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2900 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2901 return InterlockedIncrement(&This
->refs
);
2904 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2906 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2907 ULONG refs
= InterlockedDecrement(&This
->refs
);
2910 if (This
->typelib_global
)
2911 FreeResource(This
->typelib_global
);
2913 FreeLibrary(This
->dll
);
2919 static const IUnknownVtbl TLB_PEFile_Vtable
=
2921 TLB_PEFile_QueryInterface
,
2926 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2929 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2931 This
= heap_alloc(sizeof(TLB_PEFile
));
2933 return E_OUTOFMEMORY
;
2935 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2938 This
->typelib_resource
= NULL
;
2939 This
->typelib_global
= NULL
;
2940 This
->typelib_base
= NULL
;
2942 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2943 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2947 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2948 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2949 if (This
->typelib_resource
)
2951 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2952 if (This
->typelib_global
)
2954 This
->typelib_base
= LockResource(This
->typelib_global
);
2956 if (This
->typelib_base
)
2958 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2959 *ppBase
= This
->typelib_base
;
2960 *ppFile
= &This
->IUnknown_iface
;
2966 TRACE("No TYPELIB resource found\n");
2970 TLB_PEFile_Release(&This
->IUnknown_iface
);
2974 typedef struct TLB_NEFile
2976 IUnknown IUnknown_iface
;
2978 LPVOID typelib_base
;
2981 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2983 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2986 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2988 if (IsEqualIID(riid
, &IID_IUnknown
))
2991 IUnknown_AddRef(iface
);
2995 return E_NOINTERFACE
;
2998 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3000 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3001 return InterlockedIncrement(&This
->refs
);
3004 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3006 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3007 ULONG refs
= InterlockedDecrement(&This
->refs
);
3010 heap_free(This
->typelib_base
);
3016 static const IUnknownVtbl TLB_NEFile_Vtable
=
3018 TLB_NEFile_QueryInterface
,
3023 /***********************************************************************
3024 * read_xx_header [internal]
3026 static int read_xx_header( HFILE lzfd
)
3028 IMAGE_DOS_HEADER mzh
;
3031 LZSeek( lzfd
, 0, SEEK_SET
);
3032 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3034 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3037 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3038 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3041 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3043 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3044 return IMAGE_OS2_SIGNATURE
;
3045 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3046 return IMAGE_NT_SIGNATURE
;
3049 WARN("Can't handle %s files.\n", magic
);
3054 /***********************************************************************
3055 * find_ne_resource [internal]
3057 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3058 DWORD
*resLen
, DWORD
*resOff
)
3060 IMAGE_OS2_HEADER nehd
;
3061 NE_TYPEINFO
*typeInfo
;
3062 NE_NAMEINFO
*nameInfo
;
3068 /* Read in NE header */
3069 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3070 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
3072 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3075 TRACE("No resources in NE dll\n" );
3079 /* Read in resource table */
3080 resTab
= heap_alloc( resTabSize
);
3081 if ( !resTab
) return FALSE
;
3083 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3084 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3086 heap_free( resTab
);
3091 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3093 if (!IS_INTRESOURCE(typeid)) /* named type */
3095 BYTE len
= strlen( typeid );
3096 while (typeInfo
->type_id
)
3098 if (!(typeInfo
->type_id
& 0x8000))
3100 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3101 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3103 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3104 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3107 else /* numeric type id */
3109 WORD id
= LOWORD(typeid) | 0x8000;
3110 while (typeInfo
->type_id
)
3112 if (typeInfo
->type_id
== id
) goto found_type
;
3113 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3114 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3117 TRACE("No typeid entry found for %p\n", typeid );
3118 heap_free( resTab
);
3122 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3124 if (!IS_INTRESOURCE(resid
)) /* named resource */
3126 BYTE len
= strlen( resid
);
3127 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3129 BYTE
*p
= resTab
+ nameInfo
->id
;
3130 if (nameInfo
->id
& 0x8000) continue;
3131 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3134 else /* numeric resource id */
3136 WORD id
= LOWORD(resid
) | 0x8000;
3137 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3138 if (nameInfo
->id
== id
) goto found_name
;
3140 TRACE("No resid entry found for %p\n", typeid );
3141 heap_free( resTab
);
3145 /* Return resource data */
3146 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3147 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3149 heap_free( resTab
);
3153 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3157 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3160 This
= heap_alloc(sizeof(TLB_NEFile
));
3161 if (!This
) return E_OUTOFMEMORY
;
3163 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3165 This
->typelib_base
= NULL
;
3167 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3168 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3170 DWORD reslen
, offset
;
3171 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3173 This
->typelib_base
= heap_alloc(reslen
);
3174 if( !This
->typelib_base
)
3178 LZSeek( lzfd
, offset
, SEEK_SET
);
3179 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3181 *ppBase
= This
->typelib_base
;
3182 *pdwTLBLength
= reslen
;
3183 *ppFile
= &This
->IUnknown_iface
;
3189 if( lzfd
>= 0) LZClose( lzfd
);
3190 TLB_NEFile_Release(&This
->IUnknown_iface
);
3194 typedef struct TLB_Mapping
3196 IUnknown IUnknown_iface
;
3200 LPVOID typelib_base
;
3203 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3205 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3208 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3210 if (IsEqualIID(riid
, &IID_IUnknown
))
3213 IUnknown_AddRef(iface
);
3217 return E_NOINTERFACE
;
3220 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3222 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3223 return InterlockedIncrement(&This
->refs
);
3226 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3228 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3229 ULONG refs
= InterlockedDecrement(&This
->refs
);
3232 if (This
->typelib_base
)
3233 UnmapViewOfFile(This
->typelib_base
);
3235 CloseHandle(This
->mapping
);
3236 if (This
->file
!= INVALID_HANDLE_VALUE
)
3237 CloseHandle(This
->file
);
3243 static const IUnknownVtbl TLB_Mapping_Vtable
=
3245 TLB_Mapping_QueryInterface
,
3250 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3254 This
= heap_alloc(sizeof(TLB_Mapping
));
3256 return E_OUTOFMEMORY
;
3258 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3260 This
->file
= INVALID_HANDLE_VALUE
;
3261 This
->mapping
= NULL
;
3262 This
->typelib_base
= NULL
;
3264 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3265 if (INVALID_HANDLE_VALUE
!= This
->file
)
3267 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3270 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3271 if(This
->typelib_base
)
3273 /* retrieve file size */
3274 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3275 *ppBase
= This
->typelib_base
;
3276 *ppFile
= &This
->IUnknown_iface
;
3282 IUnknown_Release(&This
->IUnknown_iface
);
3283 return TYPE_E_CANTLOADLIBRARY
;
3286 /****************************************************************************
3289 * find the type of the typelib file and map the typelib resource into
3293 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3294 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3296 ITypeLibImpl
*entry
;
3299 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3300 LPVOID pBase
= NULL
;
3301 DWORD dwTLBLength
= 0;
3302 IUnknown
*pFile
= NULL
;
3307 index_str
= strrchrW(pszFileName
, '\\');
3308 if(index_str
&& *++index_str
!= '\0')
3311 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3312 if(*end_ptr
== '\0')
3314 int str_len
= index_str
- pszFileName
- 1;
3316 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3317 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3322 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3324 if(strchrW(file
, '\\'))
3326 lstrcpyW(pszPath
, file
);
3330 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3331 pszPath
[len
] = '\\';
3332 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3336 if(file
!= pszFileName
) heap_free(file
);
3338 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_ALWAYS
,
3339 FILE_ATTRIBUTE_NORMAL
, NULL
);
3340 if(h
!= INVALID_HANDLE_VALUE
){
3341 FILE_NAME_INFORMATION
*info
;
3342 char data
[MAX_PATH
* sizeof(WCHAR
) + sizeof(info
->FileNameLength
)];
3345 info
= (FILE_NAME_INFORMATION
*)data
;
3346 /* GetFileInformationByHandleEx returns the path of the file without
3347 * WOW64 redirection */
3348 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, data
, sizeof(data
));
3350 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3351 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3356 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3358 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3359 EnterCriticalSection(&cache_section
);
3360 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3362 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3364 TRACE("cache hit\n");
3365 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3366 ITypeLib2_AddRef(*ppTypeLib
);
3367 LeaveCriticalSection(&cache_section
);
3371 LeaveCriticalSection(&cache_section
);
3373 /* now actually load and parse the typelib */
3375 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3376 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3377 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3378 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3379 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3382 if (dwTLBLength
>= 4)
3384 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3385 if (dwSignature
== MSFT_SIGNATURE
)
3386 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3387 else if (dwSignature
== SLTG_SIGNATURE
)
3388 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3391 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3392 ret
= TYPE_E_CANTLOADLIBRARY
;
3396 ret
= TYPE_E_CANTLOADLIBRARY
;
3397 IUnknown_Release(pFile
);
3401 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3403 TRACE("adding to cache\n");
3404 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3405 lstrcpyW(impl
->path
, pszPath
);
3406 /* We should really canonicalise the path here. */
3407 impl
->index
= index
;
3409 /* FIXME: check if it has added already in the meantime */
3410 EnterCriticalSection(&cache_section
);
3411 list_add_head(&tlb_cache
, &impl
->entry
);
3412 LeaveCriticalSection(&cache_section
);
3418 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3420 ret
= TYPE_E_CANTLOADLIBRARY
;
3427 /*================== ITypeLib(2) Methods ===================================*/
3429 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3431 ITypeLibImpl
* pTypeLibImpl
;
3433 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3434 if (!pTypeLibImpl
) return NULL
;
3436 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3437 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3438 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3439 pTypeLibImpl
->ref
= 1;
3441 list_init(&pTypeLibImpl
->implib_list
);
3442 list_init(&pTypeLibImpl
->custdata_list
);
3443 list_init(&pTypeLibImpl
->name_list
);
3444 list_init(&pTypeLibImpl
->string_list
);
3445 list_init(&pTypeLibImpl
->guid_list
);
3446 list_init(&pTypeLibImpl
->ref_list
);
3447 pTypeLibImpl
->dispatch_href
= -1;
3449 return pTypeLibImpl
;
3452 /****************************************************************************
3453 * ITypeLib2_Constructor_MSFT
3455 * loading an MSFT typelib from an in-memory image
3457 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3461 MSFT_Header tlbHeader
;
3462 MSFT_SegDir tlbSegDir
;
3463 ITypeLibImpl
* pTypeLibImpl
;
3466 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3468 pTypeLibImpl
= TypeLibImpl_Constructor();
3469 if (!pTypeLibImpl
) return NULL
;
3471 /* get pointer to beginning of typelib data */
3475 cx
.pLibInfo
= pTypeLibImpl
;
3476 cx
.length
= dwTLBLength
;
3479 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3480 TRACE_(typelib
)("header:\n");
3481 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3482 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3483 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3486 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3488 /* there is a small amount of information here until the next important
3490 * the segment directory . Try to calculate the amount of data */
3491 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3493 /* now read the segment directory */
3494 TRACE("read segment directory (at %d)\n",lPSegDir
);
3495 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3496 cx
.pTblDir
= &tlbSegDir
;
3498 /* just check two entries */
3499 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3501 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3502 heap_free(pTypeLibImpl
);
3506 MSFT_ReadAllNames(&cx
);
3507 MSFT_ReadAllStrings(&cx
);
3508 MSFT_ReadAllGuids(&cx
);
3510 /* now fill our internal data */
3511 /* TLIBATTR fields */
3512 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3514 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3515 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3516 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3517 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3518 pTypeLibImpl
->libflags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3520 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3521 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3523 /* name, eventually add to a hash table */
3524 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3527 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3528 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3530 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3533 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3534 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3537 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3540 if(tlbHeader
.CustomDataOffset
>= 0)
3542 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3545 /* fill in type descriptions */
3546 if(tlbSegDir
.pTypdescTab
.length
> 0)
3548 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3550 pTypeLibImpl
->ctTypeDesc
= cTD
;
3551 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3552 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3555 /* FIXME: add several sanity checks here */
3556 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3557 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3559 /* FIXME: check safearray */
3561 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3563 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3565 else if(td
[0] == VT_CARRAY
)
3567 /* array descr table here */
3568 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3570 else if(td
[0] == VT_USERDEFINED
)
3572 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3574 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3577 /* second time around to fill the array subscript info */
3580 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3581 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3583 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3584 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3587 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3589 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3591 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3593 for(j
= 0; j
<td
[2]; j
++)
3595 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3596 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3597 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3598 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3603 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3604 ERR("didn't find array description data\n");
3609 /* imported type libs */
3610 if(tlbSegDir
.pImpFiles
.offset
>0)
3613 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3616 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3620 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3621 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3622 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3624 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3625 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3626 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3627 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3630 name
= heap_alloc_zero(size
+1);
3631 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3632 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3635 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3636 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3638 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3642 MSFT_ReadAllRefs(&cx
);
3644 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3647 if(tlbHeader
.nrtypeinfos
>= 0 )
3649 ITypeInfoImpl
**ppTI
;
3651 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3653 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3655 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3658 (pTypeLibImpl
->TypeInfoCount
)++;
3663 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3664 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3665 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3669 TRACE("(%p)\n", pTypeLibImpl
);
3670 return &pTypeLibImpl
->ITypeLib2_iface
;
3674 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3680 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3681 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3685 guid
->Data4
[0] = s
>> 8;
3686 guid
->Data4
[1] = s
& 0xff;
3689 for(i
= 0; i
< 6; i
++) {
3690 memcpy(b
, str
+ 24 + 2 * i
, 2);
3691 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3696 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3703 bytelen
= *(const WORD
*)ptr
;
3704 if(bytelen
== 0xffff) return 2;
3706 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3707 tmp_str
= SysAllocStringLen(NULL
, len
);
3709 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3710 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3711 SysFreeString(tmp_str
);
3716 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3721 bytelen
= *(const WORD
*)ptr
;
3722 if(bytelen
== 0xffff) return 2;
3723 *str
= heap_alloc(bytelen
+ 1);
3724 memcpy(*str
, ptr
+ 2, bytelen
);
3725 (*str
)[bytelen
] = '\0';
3729 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3734 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3735 if (tlbstr
->offset
== offset
)
3739 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3740 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3741 SysFreeString(tmp_str
);
3746 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3748 char *ptr
= pLibBlk
;
3751 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3752 FIXME("libblk magic = %04x\n", w
);
3757 if((w
= *(WORD
*)ptr
) != 0xffff) {
3758 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3763 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3765 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3767 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3770 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3771 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3774 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3775 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3777 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3780 ptr
+= 4; /* skip res12 */
3782 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3785 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3788 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3791 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3792 ptr
+= sizeof(GUID
);
3794 return ptr
- (char*)pLibBlk
;
3797 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3802 } sltg_ref_lookup_t
;
3804 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3805 HREFTYPE
*typelib_ref
)
3807 if(table
&& typeinfo_ref
< table
->num
)
3809 *typelib_ref
= table
->refs
[typeinfo_ref
];
3813 ERR_(typelib
)("Unable to find reference\n");
3818 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3823 if((*pType
& 0xe00) == 0xe00) {
3825 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3826 pTD
= pTD
->u
.lptdesc
;
3828 switch(*pType
& 0x3f) {
3831 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3832 pTD
= pTD
->u
.lptdesc
;
3835 case VT_USERDEFINED
:
3836 pTD
->vt
= VT_USERDEFINED
;
3837 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3843 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3846 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3848 pTD
->vt
= VT_CARRAY
;
3849 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3850 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3851 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3852 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3854 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3860 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3864 pTD
->vt
= VT_SAFEARRAY
;
3865 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3866 pTD
= pTD
->u
.lptdesc
;
3870 pTD
->vt
= *pType
& 0x3f;
3879 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3880 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3882 /* Handle [in/out] first */
3883 if((*pType
& 0xc000) == 0xc000)
3884 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3885 else if(*pType
& 0x8000)
3886 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3887 else if(*pType
& 0x4000)
3888 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3890 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3893 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3896 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3898 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3902 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3907 TLBRefType
*ref_type
;
3908 sltg_ref_lookup_t
*table
;
3909 HREFTYPE typelib_ref
;
3911 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3912 FIXME("Ref magic = %x\n", pRef
->magic
);
3915 name
= ( (char*)pRef
->names
+ pRef
->number
);
3917 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3918 table
->num
= pRef
->number
>> 3;
3920 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3922 /* We don't want the first href to be 0 */
3923 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3925 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3927 unsigned int lib_offs
, type_num
;
3929 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3931 name
+= SLTG_ReadStringA(name
, &refname
);
3932 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3933 FIXME_(typelib
)("Can't sscanf ref\n");
3934 if(lib_offs
!= 0xffff) {
3937 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3938 if(import
->offset
== lib_offs
)
3941 if(&import
->entry
== &pTL
->implib_list
) {
3942 char fname
[MAX_PATH
+1];
3946 import
= heap_alloc_zero(sizeof(*import
));
3947 import
->offset
= lib_offs
;
3948 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3949 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3950 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3951 &import
->wVersionMajor
,
3952 &import
->wVersionMinor
,
3953 &import
->lcid
, fname
) != 4) {
3954 FIXME_(typelib
)("can't sscanf ref %s\n",
3955 pNameTable
+ lib_offs
+ 40);
3957 len
= strlen(fname
);
3958 if(fname
[len
-1] != '#')
3959 FIXME("fname = %s\n", fname
);
3960 fname
[len
-1] = '\0';
3961 import
->name
= TLB_MultiByteToBSTR(fname
);
3962 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3964 ref_type
->pImpTLInfo
= import
;
3966 /* Store a reference to IDispatch */
3967 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3968 pTL
->dispatch_href
= typelib_ref
;
3970 } else { /* internal ref */
3971 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3973 ref_type
->reference
= typelib_ref
;
3974 ref_type
->index
= type_num
;
3977 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3979 table
->refs
[ref
] = typelib_ref
;
3982 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3983 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3984 dump_TLBRefType(pTL
);
3988 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3989 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3991 SLTG_ImplInfo
*info
;
3992 TLBImplType
*pImplType
;
3993 /* I don't really get this structure, usually it's 0x16 bytes
3994 long, but iuser.tlb contains some that are 0x18 bytes long.
3995 That's ok because we can use the next ptr to jump to the next
3996 one. But how do we know the length of the last one? The WORD
3997 at offs 0x8 might be the clue. For now I'm just assuming that
3998 the last one is the regular 0x16 bytes. */
4000 info
= (SLTG_ImplInfo
*)pBlk
;
4003 if(info
->next
== 0xffff)
4005 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4008 info
= (SLTG_ImplInfo
*)pBlk
;
4009 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4010 pImplType
= pTI
->impltypes
;
4012 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4013 pImplType
->implflags
= info
->impltypeflags
;
4016 if(info
->next
== 0xffff)
4019 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4020 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4022 info
++; /* see comment at top of function */
4026 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4027 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4029 TLBVarDesc
*pVarDesc
;
4030 const TLBString
*prevName
= NULL
;
4031 SLTG_Variable
*pItem
;
4035 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4037 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4038 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4040 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4042 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4043 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4044 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4048 if (pItem
->name
== 0xfffe)
4049 pVarDesc
->Name
= prevName
;
4051 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4053 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4054 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4055 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4057 if(pItem
->flags
& 0x02)
4058 pType
= &pItem
->type
;
4060 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4062 if (pItem
->flags
& ~0xda)
4063 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4065 SLTG_DoElem(pType
, pBlk
,
4066 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4068 if (TRACE_ON(typelib
)) {
4070 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4071 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4074 if (pItem
->flags
& 0x40) {
4075 TRACE_(typelib
)("VAR_DISPATCH\n");
4076 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4078 else if (pItem
->flags
& 0x10) {
4079 TRACE_(typelib
)("VAR_CONST\n");
4080 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4081 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4082 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4083 if (pItem
->flags
& 0x08)
4084 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4086 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4092 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4094 TRACE_(typelib
)("len = %u\n", len
);
4095 if (len
== 0xffff) {
4098 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4099 str
= SysAllocStringLen(NULL
, alloc_len
);
4100 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4102 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4103 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4112 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4113 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4116 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4121 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4122 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4123 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4126 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4127 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4129 if (pItem
->flags
& 0x80)
4130 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4132 prevName
= pVarDesc
->Name
;
4137 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4138 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4140 SLTG_Function
*pFunc
;
4142 TLBFuncDesc
*pFuncDesc
;
4144 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4146 pFuncDesc
= pTI
->funcdescs
;
4147 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4148 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4153 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4154 case SLTG_FUNCTION_MAGIC
:
4155 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4157 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4158 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4160 case SLTG_STATIC_FUNCTION_MAGIC
:
4161 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4164 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4167 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4169 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4170 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4171 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4172 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4173 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4174 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4176 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4177 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4179 if(pFunc
->retnextopt
& 0x80)
4180 pType
= &pFunc
->rettype
;
4182 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4184 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4186 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4187 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4188 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4190 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4192 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4193 char *paramName
= pNameTable
+ *pArg
;
4195 /* If arg type follows then paramName points to the 2nd
4196 letter of the name, else the next WORD is an offset to
4197 the arg type and paramName points to the first letter.
4198 So let's take one char off paramName and see if we're
4199 pointing at an alpha-numeric char. However if *pArg is
4200 0xffff or 0xfffe then the param has no name, the former
4201 meaning that the next WORD is the type, the latter
4202 meaning that the next WORD is an offset to the type. */
4207 else if(*pArg
== 0xfffe) {
4211 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4216 if(HaveOffs
) { /* the next word is an offset to type */
4217 pType
= (WORD
*)(pBlk
+ *pArg
);
4218 SLTG_DoElem(pType
, pBlk
,
4219 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4224 pArg
= SLTG_DoElem(pArg
, pBlk
,
4225 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4228 /* Are we an optional param ? */
4229 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4230 pFuncDesc
->funcdesc
.cParamsOpt
)
4231 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4234 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4235 paramName
- pNameTable
, pTI
->pTypeLib
);
4237 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4241 pTI
->cFuncs
= cFuncs
;
4244 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4245 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4246 SLTG_TypeInfoTail
*pTITail
)
4249 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4251 if(pTIHeader
->href_table
!= 0xffffffff) {
4252 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4258 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4259 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4261 heap_free(ref_lookup
);
4265 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4266 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4267 const SLTG_TypeInfoTail
*pTITail
)
4270 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4272 if(pTIHeader
->href_table
!= 0xffffffff) {
4273 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4279 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4280 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4283 if (pTITail
->funcs_off
!= 0xffff)
4284 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4286 heap_free(ref_lookup
);
4288 if (TRACE_ON(typelib
))
4289 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4292 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4293 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4294 const SLTG_TypeInfoTail
*pTITail
)
4296 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4299 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4300 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4301 const SLTG_TypeInfoTail
*pTITail
)
4304 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4306 if (pTITail
->simple_alias
) {
4307 /* if simple alias, no more processing required */
4308 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4309 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4313 if(pTIHeader
->href_table
!= 0xffffffff) {
4314 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4318 /* otherwise it is an offset to a type */
4319 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4321 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4322 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4324 heap_free(ref_lookup
);
4327 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4328 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4329 const SLTG_TypeInfoTail
*pTITail
)
4331 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4332 if (pTIHeader
->href_table
!= 0xffffffff)
4333 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4336 if (pTITail
->vars_off
!= 0xffff)
4337 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4339 if (pTITail
->funcs_off
!= 0xffff)
4340 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4342 if (pTITail
->impls_off
!= 0xffff)
4343 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4345 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4346 * of dispinterface functions including the IDispatch ones, so
4347 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4348 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4350 heap_free(ref_lookup
);
4351 if (TRACE_ON(typelib
))
4352 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4355 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4356 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4357 const SLTG_TypeInfoTail
*pTITail
)
4359 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4362 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4363 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4364 const SLTG_TypeInfoTail
*pTITail
)
4366 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4367 if (pTIHeader
->href_table
!= 0xffffffff)
4368 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4371 if (pTITail
->vars_off
!= 0xffff)
4372 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4374 if (pTITail
->funcs_off
!= 0xffff)
4375 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4376 heap_free(ref_lookup
);
4377 if (TRACE_ON(typelib
))
4381 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4382 manageable copy of it into this */
4395 } SLTG_InternalOtherTypeInfo
;
4397 /****************************************************************************
4398 * ITypeLib2_Constructor_SLTG
4400 * loading a SLTG typelib from an in-memory image
4402 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4404 ITypeLibImpl
*pTypeLibImpl
;
4405 SLTG_Header
*pHeader
;
4406 SLTG_BlkEntry
*pBlkEntry
;
4410 LPVOID pBlk
, pFirstBlk
;
4411 SLTG_LibBlk
*pLibBlk
;
4412 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4413 char *pAfterOTIBlks
= NULL
;
4414 char *pNameTable
, *ptr
;
4417 ITypeInfoImpl
**ppTypeInfoImpl
;
4419 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4422 pTypeLibImpl
= TypeLibImpl_Constructor();
4423 if (!pTypeLibImpl
) return NULL
;
4427 TRACE_(typelib
)("header:\n");
4428 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4429 pHeader
->nrOfFileBlks
);
4430 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4431 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4432 pHeader
->SLTG_magic
);
4436 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4437 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4439 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4440 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4442 /* Next we have a magic block */
4443 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4445 /* Let's see if we're still in sync */
4446 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4447 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4448 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4451 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4452 sizeof(SLTG_DIR_MAGIC
))) {
4453 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4457 pIndex
= (SLTG_Index
*)(pMagic
+1);
4459 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4461 pFirstBlk
= pPad9
+ 1;
4463 /* We'll set up a ptr to the main library block, which is the last one. */
4465 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4466 pBlkEntry
[order
].next
!= 0;
4467 order
= pBlkEntry
[order
].next
- 1, i
++) {
4468 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4472 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4474 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4479 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4481 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4484 ptr
= (char*)pLibBlk
+ len
;
4486 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4490 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4492 w
= *(WORD
*)(ptr
+ 2);
4495 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4496 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4497 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4499 w
= *(WORD
*)(ptr
+ 4 + len
);
4501 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4503 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4504 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4505 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4507 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4508 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4509 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4511 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4512 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4515 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4516 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4517 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4518 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4519 len
+= sizeof(SLTG_OtherTypeInfo
);
4523 pAfterOTIBlks
= ptr
;
4525 /* Skip this WORD and get the next DWORD */
4526 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4528 /* Now add this to pLibBLk look at what we're pointing at and
4529 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4530 dust and we should be pointing at the beginning of the name
4533 pNameTable
= (char*)pLibBlk
+ len
;
4535 switch(*(WORD
*)pNameTable
) {
4542 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4546 pNameTable
+= 0x216;
4550 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4552 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4555 /* Hopefully we now have enough ptrs set up to actually read in
4556 some TypeInfos. It's not clear which order to do them in, so
4557 I'll just follow the links along the BlkEntry chain and read
4558 them in the order in which they are in the file */
4560 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4561 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4563 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4564 pBlkEntry
[order
].next
!= 0;
4565 order
= pBlkEntry
[order
].next
- 1, i
++) {
4567 SLTG_TypeInfoHeader
*pTIHeader
;
4568 SLTG_TypeInfoTail
*pTITail
;
4569 SLTG_MemberHeader
*pMemHeader
;
4571 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4572 FIXME_(typelib
)("Index strings don't match\n");
4573 heap_free(pOtherTypeInfoBlks
);
4578 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4579 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4580 heap_free(pOtherTypeInfoBlks
);
4583 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4584 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4585 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4587 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4588 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4589 (*ppTypeInfoImpl
)->index
= i
;
4590 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4591 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4592 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4593 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4594 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4595 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4596 (*ppTypeInfoImpl
)->wTypeFlags
=
4597 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4599 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4600 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4602 if((pTIHeader
->typeflags1
& 7) != 2)
4603 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4604 if(pTIHeader
->typeflags3
!= 2)
4605 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4607 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4608 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4609 typekind_desc
[pTIHeader
->typekind
],
4610 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4611 (*ppTypeInfoImpl
)->wTypeFlags
);
4613 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4615 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4617 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4618 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4619 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4621 switch(pTIHeader
->typekind
) {
4623 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4624 pTIHeader
, pTITail
);
4628 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4629 pTIHeader
, pTITail
);
4632 case TKIND_INTERFACE
:
4633 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4634 pTIHeader
, pTITail
);
4638 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4639 pTIHeader
, pTITail
);
4643 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4644 pTIHeader
, pTITail
);
4647 case TKIND_DISPATCH
:
4648 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4649 pTIHeader
, pTITail
);
4653 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4654 pTIHeader
, pTITail
);
4658 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4663 /* could get cFuncs, cVars and cImplTypes from here
4664 but we've already set those */
4665 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4681 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4684 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4685 FIXME("Somehow processed %d TypeInfos\n", i
);
4686 heap_free(pOtherTypeInfoBlks
);
4690 heap_free(pOtherTypeInfoBlks
);
4691 return &pTypeLibImpl
->ITypeLib2_iface
;
4694 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4696 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4698 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4700 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4701 IsEqualIID(riid
,&IID_ITypeLib
)||
4702 IsEqualIID(riid
,&IID_ITypeLib2
))
4704 *ppv
= &This
->ITypeLib2_iface
;
4706 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4707 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4709 *ppv
= &This
->ICreateTypeLib2_iface
;
4714 TRACE("-- Interface: E_NOINTERFACE\n");
4715 return E_NOINTERFACE
;
4718 IUnknown_AddRef((IUnknown
*)*ppv
);
4722 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4724 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4725 ULONG ref
= InterlockedIncrement(&This
->ref
);
4727 TRACE("(%p) ref=%u\n", This
, ref
);
4732 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4734 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4735 ULONG ref
= InterlockedDecrement(&This
->ref
);
4737 TRACE("(%p) ref=%u\n",This
, ref
);
4741 TLBImpLib
*pImpLib
, *pImpLibNext
;
4742 TLBRefType
*ref_type
;
4743 TLBString
*tlbstr
, *tlbstr_next
;
4744 TLBGuid
*tlbguid
, *tlbguid_next
;
4748 /* remove cache entry */
4751 TRACE("removing from cache list\n");
4752 EnterCriticalSection(&cache_section
);
4753 if(This
->entry
.next
)
4754 list_remove(&This
->entry
);
4755 LeaveCriticalSection(&cache_section
);
4756 heap_free(This
->path
);
4758 TRACE(" destroying ITypeLib(%p)\n",This
);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4761 list_remove(&tlbstr
->entry
);
4762 SysFreeString(tlbstr
->str
);
4766 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4767 list_remove(&tlbstr
->entry
);
4768 SysFreeString(tlbstr
->str
);
4772 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4773 list_remove(&tlbguid
->entry
);
4777 TLB_FreeCustData(&This
->custdata_list
);
4779 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4780 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4781 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4783 heap_free(This
->pTypeDesc
);
4785 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4787 if (pImpLib
->pImpTypeLib
)
4788 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4789 SysFreeString(pImpLib
->name
);
4791 list_remove(&pImpLib
->entry
);
4795 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4797 list_remove(&ref_type
->entry
);
4798 heap_free(ref_type
);
4801 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4802 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4803 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4805 heap_free(This
->typeinfos
);
4813 /* ITypeLib::GetTypeInfoCount
4815 * Returns the number of type descriptions in the type library
4817 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4819 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4820 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4821 return This
->TypeInfoCount
;
4824 /* ITypeLib::GetTypeInfo
4826 * retrieves the specified type description in the library.
4828 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4831 ITypeInfo
**ppTInfo
)
4833 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4835 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4838 return E_INVALIDARG
;
4840 if(index
>= This
->TypeInfoCount
)
4841 return TYPE_E_ELEMENTNOTFOUND
;
4843 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4844 ITypeInfo_AddRef(*ppTInfo
);
4850 /* ITypeLibs::GetTypeInfoType
4852 * Retrieves the type of a type description.
4854 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4859 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4861 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4864 return E_INVALIDARG
;
4866 if(index
>= This
->TypeInfoCount
)
4867 return TYPE_E_ELEMENTNOTFOUND
;
4869 *pTKind
= This
->typeinfos
[index
]->typekind
;
4874 /* ITypeLib::GetTypeInfoOfGuid
4876 * Retrieves the type description that corresponds to the specified GUID.
4879 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4882 ITypeInfo
**ppTInfo
)
4884 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4887 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4889 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4890 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4891 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4892 ITypeInfo_AddRef(*ppTInfo
);
4897 return TYPE_E_ELEMENTNOTFOUND
;
4900 /* ITypeLib::GetLibAttr
4902 * Retrieves the structure that contains the library's attributes.
4905 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4909 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4911 TRACE("(%p, %p)\n", This
, attr
);
4913 if (!attr
) return E_INVALIDARG
;
4915 *attr
= heap_alloc(sizeof(**attr
));
4916 if (!*attr
) return E_OUTOFMEMORY
;
4918 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4919 (*attr
)->lcid
= This
->set_lcid
;
4920 (*attr
)->syskind
= This
->syskind
;
4921 (*attr
)->wMajorVerNum
= This
->ver_major
;
4922 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4923 (*attr
)->wLibFlags
= This
->libflags
;
4928 /* ITypeLib::GetTypeComp
4930 * Enables a client compiler to bind to a library's types, variables,
4931 * constants, and global functions.
4934 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4936 ITypeComp
**ppTComp
)
4938 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4940 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4941 *ppTComp
= &This
->ITypeComp_iface
;
4942 ITypeComp_AddRef(*ppTComp
);
4947 /* ITypeLib::GetDocumentation
4949 * Retrieves the library's documentation string, the complete Help file name
4950 * and path, and the context identifier for the library Help topic in the Help
4953 * On a successful return all non-null BSTR pointers will have been set,
4956 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4960 BSTR
*pBstrDocString
,
4961 DWORD
*pdwHelpContext
,
4962 BSTR
*pBstrHelpFile
)
4964 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4965 HRESULT result
= E_INVALIDARG
;
4968 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4970 pBstrName
, pBstrDocString
,
4971 pdwHelpContext
, pBstrHelpFile
);
4975 /* documentation for the typelib */
4980 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4988 if (This
->DocString
)
4990 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4994 *pBstrDocString
= NULL
;
4998 *pdwHelpContext
= This
->dwHelpContext
;
5004 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5008 *pBstrHelpFile
= NULL
;
5015 /* for a typeinfo */
5016 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5018 if(SUCCEEDED(result
))
5020 result
= ITypeInfo_GetDocumentation(pTInfo
,
5024 pdwHelpContext
, pBstrHelpFile
);
5026 ITypeInfo_Release(pTInfo
);
5031 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5033 if (pBstrName
) SysFreeString (*pBstrName
);
5035 return STG_E_INSUFFICIENTMEMORY
;
5040 * Indicates whether a passed-in string contains the name of a type or member
5041 * described in the library.
5044 static HRESULT WINAPI
ITypeLib2_fnIsName(
5050 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5052 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5054 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5058 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5059 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5060 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5061 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5062 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5064 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5065 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5066 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5067 goto ITypeLib2_fnIsName_exit
;
5070 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5071 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5072 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5078 ITypeLib2_fnIsName_exit
:
5079 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5080 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5085 /* ITypeLib::FindName
5087 * Finds occurrences of a type description in a type library. This may be used
5088 * to quickly verify that a name exists in a type library.
5091 static HRESULT WINAPI
ITypeLib2_fnFindName(
5095 ITypeInfo
**ppTInfo
,
5099 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5104 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5106 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5107 return E_INVALIDARG
;
5109 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5110 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
5111 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5115 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
5116 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5117 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5120 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
5121 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
5122 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
5123 goto ITypeLib2_fnFindName_exit
;
5127 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5129 goto ITypeLib2_fnFindName_exit
;
5132 ITypeLib2_fnFindName_exit
:
5133 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5134 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5137 TRACE("found %d typeinfos\n", count
);
5144 /* ITypeLib::ReleaseTLibAttr
5146 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5149 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5151 TLIBATTR
*pTLibAttr
)
5153 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5154 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5155 heap_free(pTLibAttr
);
5158 /* ITypeLib2::GetCustData
5160 * gets the custom data
5162 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5167 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5168 TLBCustData
*pCData
;
5170 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5172 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5174 return TYPE_E_ELEMENTNOTFOUND
;
5176 VariantInit(pVarVal
);
5177 VariantCopy(pVarVal
, &pCData
->data
);
5182 /* ITypeLib2::GetLibStatistics
5184 * Returns statistics about a type library that are required for efficient
5185 * sizing of hash tables.
5188 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5190 ULONG
*pcUniqueNames
,
5191 ULONG
*pcchUniqueNames
)
5193 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5195 FIXME("(%p): stub!\n", This
);
5197 if(pcUniqueNames
) *pcUniqueNames
=1;
5198 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5202 /* ITypeLib2::GetDocumentation2
5204 * Retrieves the library's documentation string, the complete Help file name
5205 * and path, the localization context to use, and the context ID for the
5206 * library Help topic in the Help file.
5209 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5213 BSTR
*pbstrHelpString
,
5214 DWORD
*pdwHelpStringContext
,
5215 BSTR
*pbstrHelpStringDll
)
5217 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5221 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5223 /* the help string should be obtained from the helpstringdll,
5224 * using the _DLLGetDocumentation function, based on the supplied
5225 * lcid. Nice to do sometime...
5229 /* documentation for the typelib */
5231 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5232 if(pdwHelpStringContext
)
5233 *pdwHelpStringContext
=This
->dwHelpContext
;
5234 if(pbstrHelpStringDll
)
5235 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5241 /* for a typeinfo */
5242 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5244 if(SUCCEEDED(result
))
5246 ITypeInfo2
* pTInfo2
;
5247 result
= ITypeInfo_QueryInterface(pTInfo
,
5249 (LPVOID
*) &pTInfo2
);
5251 if(SUCCEEDED(result
))
5253 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5257 pdwHelpStringContext
,
5258 pbstrHelpStringDll
);
5260 ITypeInfo2_Release(pTInfo2
);
5263 ITypeInfo_Release(pTInfo
);
5269 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5271 TLBCustData
*pCData
;
5275 ct
= list_count(custdata_list
);
5277 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5278 if(!pCustData
->prgCustData
)
5279 return E_OUTOFMEMORY
;
5281 pCustData
->cCustData
= ct
;
5283 cdi
= pCustData
->prgCustData
;
5284 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5285 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5286 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5294 /* ITypeLib2::GetAllCustData
5296 * Gets all custom data items for the library.
5299 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5301 CUSTDATA
*pCustData
)
5303 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5304 TRACE("(%p)->(%p)\n", This
, pCustData
);
5305 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5308 static const ITypeLib2Vtbl tlbvt
= {
5309 ITypeLib2_fnQueryInterface
,
5311 ITypeLib2_fnRelease
,
5312 ITypeLib2_fnGetTypeInfoCount
,
5313 ITypeLib2_fnGetTypeInfo
,
5314 ITypeLib2_fnGetTypeInfoType
,
5315 ITypeLib2_fnGetTypeInfoOfGuid
,
5316 ITypeLib2_fnGetLibAttr
,
5317 ITypeLib2_fnGetTypeComp
,
5318 ITypeLib2_fnGetDocumentation
,
5320 ITypeLib2_fnFindName
,
5321 ITypeLib2_fnReleaseTLibAttr
,
5323 ITypeLib2_fnGetCustData
,
5324 ITypeLib2_fnGetLibStatistics
,
5325 ITypeLib2_fnGetDocumentation2
,
5326 ITypeLib2_fnGetAllCustData
5330 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5332 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5334 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5337 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5339 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5341 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5344 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5346 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5348 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5351 static HRESULT WINAPI
ITypeLibComp_fnBind(
5356 ITypeInfo
** ppTInfo
,
5357 DESCKIND
* pDescKind
,
5360 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5361 int typemismatch
=0, i
;
5363 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5365 *pDescKind
= DESCKIND_NONE
;
5366 pBindPtr
->lptcomp
= NULL
;
5369 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5370 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5371 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5373 /* FIXME: check wFlags here? */
5374 /* FIXME: we should use a hash table to look this info up using lHash
5375 * instead of an O(n) search */
5376 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5377 (pTypeInfo
->typekind
== TKIND_MODULE
))
5379 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5381 *pDescKind
= DESCKIND_TYPECOMP
;
5382 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5383 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5384 TRACE("module or enum: %s\n", debugstr_w(szName
));
5389 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5390 (pTypeInfo
->typekind
== TKIND_ENUM
))
5392 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5395 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5396 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5398 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5401 else if (hr
== TYPE_E_TYPEMISMATCH
)
5405 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5406 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5408 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5410 ITypeInfo
*subtypeinfo
;
5412 DESCKIND subdesckind
;
5414 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5415 &subtypeinfo
, &subdesckind
, &subbindptr
);
5416 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5418 TYPEDESC tdesc_appobject
;
5419 const VARDESC vardesc_appobject
=
5422 NULL
, /* lpstrSchema */
5437 VAR_STATIC
/* varkind */
5440 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5441 tdesc_appobject
.vt
= VT_USERDEFINED
;
5443 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5445 /* cleanup things filled in by Bind call so we can put our
5446 * application object data in there instead */
5447 switch (subdesckind
)
5449 case DESCKIND_FUNCDESC
:
5450 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5452 case DESCKIND_VARDESC
:
5453 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5458 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5460 if (pTypeInfo
->hreftype
== -1)
5461 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5463 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5467 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5468 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5469 ITypeInfo_AddRef(*ppTInfo
);
5472 else if (hr
== TYPE_E_TYPEMISMATCH
)
5479 TRACE("type mismatch %s\n", debugstr_w(szName
));
5480 return TYPE_E_TYPEMISMATCH
;
5484 TRACE("name not found %s\n", debugstr_w(szName
));
5489 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5493 ITypeInfo
** ppTInfo
,
5494 ITypeComp
** ppTComp
)
5496 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5497 ITypeInfoImpl
*info
;
5499 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5501 if(!szName
|| !ppTInfo
|| !ppTComp
)
5502 return E_INVALIDARG
;
5504 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5511 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5512 ITypeInfo_AddRef(*ppTInfo
);
5513 *ppTComp
= &info
->ITypeComp_iface
;
5514 ITypeComp_AddRef(*ppTComp
);
5519 static const ITypeCompVtbl tlbtcvt
=
5522 ITypeLibComp_fnQueryInterface
,
5523 ITypeLibComp_fnAddRef
,
5524 ITypeLibComp_fnRelease
,
5526 ITypeLibComp_fnBind
,
5527 ITypeLibComp_fnBindType
5530 /*================== ITypeInfo(2) Methods ===================================*/
5531 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5533 ITypeInfoImpl
*pTypeInfoImpl
;
5535 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5538 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5539 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5540 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5541 pTypeInfoImpl
->ref
= 0;
5542 pTypeInfoImpl
->hreftype
= -1;
5543 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5544 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5545 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5546 list_init(pTypeInfoImpl
->pcustdata_list
);
5548 TRACE("(%p)\n", pTypeInfoImpl
);
5549 return pTypeInfoImpl
;
5552 /* ITypeInfo::QueryInterface
5554 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5559 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5561 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5564 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5565 IsEqualIID(riid
,&IID_ITypeInfo
)||
5566 IsEqualIID(riid
,&IID_ITypeInfo2
))
5568 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5569 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5570 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5573 ITypeInfo2_AddRef(iface
);
5574 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5577 TRACE("-- Interface: E_NOINTERFACE\n");
5578 return E_NOINTERFACE
;
5581 /* ITypeInfo::AddRef
5583 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5585 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5586 ULONG ref
= InterlockedIncrement(&This
->ref
);
5588 TRACE("(%p)->ref is %u\n",This
, ref
);
5590 if (ref
== 1 /* incremented from 0 */)
5591 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5596 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5600 TRACE("destroying ITypeInfo(%p)\n",This
);
5602 for (i
= 0; i
< This
->cFuncs
; ++i
)
5605 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5606 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5608 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5609 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5610 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5611 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5613 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5614 heap_free(pFInfo
->pParamDesc
);
5615 TLB_FreeCustData(&pFInfo
->custdata_list
);
5617 heap_free(This
->funcdescs
);
5619 for(i
= 0; i
< This
->cVars
; ++i
)
5621 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5622 if (pVInfo
->vardesc_create
) {
5623 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5624 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5625 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5626 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5628 TLB_FreeCustData(&pVInfo
->custdata_list
);
5630 heap_free(This
->vardescs
);
5632 if(This
->impltypes
){
5633 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5634 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5635 TLB_FreeCustData(&pImpl
->custdata_list
);
5637 heap_free(This
->impltypes
);
5640 TLB_FreeCustData(&This
->custdata_list
);
5645 /* ITypeInfo::Release
5647 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5649 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5650 ULONG ref
= InterlockedDecrement(&This
->ref
);
5652 TRACE("(%p)->(%u)\n",This
, ref
);
5656 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5657 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5658 if (not_attached_to_typelib
)
5660 /* otherwise This will be freed when typelib is freed */
5666 /* ITypeInfo::GetTypeAttr
5668 * Retrieves a TYPEATTR structure that contains the attributes of the type
5672 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5673 LPTYPEATTR
*ppTypeAttr
)
5675 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5678 TRACE("(%p)\n",This
);
5680 size
= sizeof(**ppTypeAttr
);
5681 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5682 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5684 *ppTypeAttr
= heap_alloc(size
);
5686 return E_OUTOFMEMORY
;
5688 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5689 (*ppTypeAttr
)->lcid
= This
->lcid
;
5690 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5691 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5692 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5693 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5694 (*ppTypeAttr
)->typekind
= This
->typekind
;
5695 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5696 (*ppTypeAttr
)->cVars
= This
->cVars
;
5697 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5698 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5699 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5700 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5701 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5702 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5703 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5705 if (This
->tdescAlias
)
5706 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5707 This
->tdescAlias
, *ppTypeAttr
+ 1);
5709 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5710 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5713 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5714 /* This should include all the inherited funcs */
5715 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5716 /* This is always the size of IDispatch's vtbl */
5717 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5718 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5723 /* ITypeInfo::GetTypeComp
5725 * Retrieves the ITypeComp interface for the type description, which enables a
5726 * client compiler to bind to the type description's members.
5729 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5730 ITypeComp
* *ppTComp
)
5732 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5734 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5736 *ppTComp
= &This
->ITypeComp_iface
;
5737 ITypeComp_AddRef(*ppTComp
);
5741 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5743 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5744 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5745 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5749 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5752 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5753 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5755 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5756 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5757 *buffer
+= sizeof(PARAMDESCEX
);
5758 *pparamdescex_dest
= *pparamdescex_src
;
5759 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5760 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5761 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5762 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5765 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5769 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5771 UINT len
= SysStringLen(str
), i
;
5772 for (i
= 0; i
< len
; ++i
)
5778 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5780 if (V_VT(var
) == VT_INT
)
5781 return VariantChangeType(var
, var
, 0, VT_I4
);
5782 else if (V_VT(var
) == VT_UINT
)
5783 return VariantChangeType(var
, var
, 0, VT_UI4
);
5784 else if (V_VT(var
) == VT_BSTR
)
5785 return TLB_SanitizeBSTR(V_BSTR(var
));
5790 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5792 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5793 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5796 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5800 SIZE_T size
= sizeof(*src
);
5804 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5805 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5806 for (i
= 0; i
< src
->cParams
; i
++)
5808 size
+= sizeof(ELEMDESC
);
5809 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5812 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5813 if (!dest
) return E_OUTOFMEMORY
;
5816 if (dispinterface
) /* overwrite funckind */
5817 dest
->funckind
= FUNC_DISPATCH
;
5818 buffer
= (char *)(dest
+ 1);
5820 dest
->oVft
= dest
->oVft
& 0xFFFC;
5822 if (dest
->cScodes
) {
5823 dest
->lprgscode
= (SCODE
*)buffer
;
5824 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5825 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5827 dest
->lprgscode
= NULL
;
5829 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5832 SysFreeString((BSTR
)dest
);
5836 if (dest
->cParams
) {
5837 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5838 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5839 for (i
= 0; i
< src
->cParams
; i
++)
5841 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5847 /* undo the above actions */
5848 for (i
= i
- 1; i
>= 0; i
--)
5849 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5850 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5851 SysFreeString((BSTR
)dest
);
5855 dest
->lprgelemdescParam
= NULL
;
5857 /* special treatment for dispinterfaces: this makes functions appear
5858 * to return their [retval] value when it is really returning an
5860 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5862 if (dest
->cParams
&&
5863 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5865 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5866 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5868 ERR("elemdesc should have started with VT_PTR instead of:\n");
5870 dump_ELEMDESC(elemdesc
);
5871 return E_UNEXPECTED
;
5874 /* copy last parameter to the return value. we are using a flat
5875 * buffer so there is no danger of leaking memory in
5877 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5879 /* remove the last parameter */
5883 /* otherwise this function is made to appear to have no return
5885 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5893 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5895 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5896 if (var_desc
->varkind
== VAR_CONST
)
5897 VariantClear(var_desc
->u
.lpvarValue
);
5898 SysFreeString((BSTR
)var_desc
);
5901 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5903 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5905 if (index
>= This
->cFuncs
)
5906 return TYPE_E_ELEMENTNOTFOUND
;
5908 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5912 /* internal function to make the inherited interfaces' methods appear
5913 * part of the interface */
5914 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5915 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5917 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5919 UINT implemented_funcs
= 0;
5924 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5928 ITypeInfo
*pSubTypeInfo
;
5931 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5935 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5938 &sub_funcs
, hrefoffset
);
5939 implemented_funcs
+= sub_funcs
;
5940 ITypeInfo_Release(pSubTypeInfo
);
5943 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5947 *funcs
= implemented_funcs
+ This
->cFuncs
;
5951 if (index
< implemented_funcs
)
5952 return E_INVALIDARG
;
5953 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5957 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5959 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5962 switch (pTypeDesc
->vt
)
5964 case VT_USERDEFINED
:
5965 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5969 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5972 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5980 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5983 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5984 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5985 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5988 /* ITypeInfo::GetFuncDesc
5990 * Retrieves the FUNCDESC structure that contains information about a
5991 * specified function.
5994 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5995 LPFUNCDESC
*ppFuncDesc
)
5997 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5998 const FUNCDESC
*internal_funcdesc
;
6000 UINT hrefoffset
= 0;
6002 TRACE("(%p) index %d\n", This
, index
);
6005 return E_INVALIDARG
;
6007 if (This
->needs_layout
)
6008 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6010 if (This
->typekind
== TKIND_DISPATCH
)
6011 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6012 &internal_funcdesc
, NULL
,
6015 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6016 &internal_funcdesc
);
6019 WARN("description for function %d not found\n", index
);
6023 hr
= TLB_AllocAndInitFuncDesc(
6026 This
->typekind
== TKIND_DISPATCH
);
6028 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6029 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6031 TRACE("-- 0x%08x\n", hr
);
6035 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6039 SIZE_T size
= sizeof(*src
);
6042 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6043 if (src
->varkind
== VAR_CONST
)
6044 size
+= sizeof(VARIANT
);
6045 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6047 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6048 if (!dest
) return E_OUTOFMEMORY
;
6051 buffer
= (char *)(dest
+ 1);
6052 if (src
->lpstrSchema
)
6055 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6056 len
= strlenW(src
->lpstrSchema
);
6057 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6058 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6061 if (src
->varkind
== VAR_CONST
)
6065 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6066 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6067 buffer
+= sizeof(VARIANT
);
6068 VariantInit(dest
->u
.lpvarValue
);
6069 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6072 SysFreeString((BSTR
)dest
);
6076 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6079 if (src
->varkind
== VAR_CONST
)
6080 VariantClear(dest
->u
.lpvarValue
);
6081 SysFreeString((BSTR
)dest
);
6088 /* ITypeInfo::GetVarDesc
6090 * Retrieves a VARDESC structure that describes the specified variable.
6093 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6094 LPVARDESC
*ppVarDesc
)
6096 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6097 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6099 TRACE("(%p) index %d\n", This
, index
);
6101 if(index
>= This
->cVars
)
6102 return TYPE_E_ELEMENTNOTFOUND
;
6104 if (This
->needs_layout
)
6105 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6107 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6110 /* ITypeInfo_GetNames
6112 * Retrieves the variable with the specified member ID (or the name of the
6113 * property or method and its parameters) that correspond to the specified
6116 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6117 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6119 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6120 const TLBFuncDesc
*pFDesc
;
6121 const TLBVarDesc
*pVDesc
;
6123 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6126 return E_INVALIDARG
;
6130 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6133 if(!cMaxNames
|| !pFDesc
->Name
)
6136 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6139 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6140 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6142 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6148 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6151 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6156 if(This
->impltypes
&&
6157 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6158 /* recursive search */
6161 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6162 if(SUCCEEDED(result
))
6164 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6165 ITypeInfo_Release(pTInfo
);
6168 WARN("Could not search inherited interface!\n");
6172 WARN("no names found\n");
6175 return TYPE_E_ELEMENTNOTFOUND
;
6181 /* ITypeInfo::GetRefTypeOfImplType
6183 * If a type description describes a COM class, it retrieves the type
6184 * description of the implemented interface types. For an interface,
6185 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6189 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6194 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6197 TRACE("(%p) index %d\n", This
, index
);
6198 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6202 /* only valid on dual interfaces;
6203 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6206 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6212 hr
= TYPE_E_ELEMENTNOTFOUND
;
6215 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6217 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6218 *pRefType
= This
->pTypeLib
->dispatch_href
;
6222 if(index
>= This
->cImplTypes
)
6223 hr
= TYPE_E_ELEMENTNOTFOUND
;
6225 *pRefType
= This
->impltypes
[index
].hRef
;
6226 if(This
->typekind
== TKIND_INTERFACE
)
6234 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6236 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6242 /* ITypeInfo::GetImplTypeFlags
6244 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6245 * or base interface in a type description.
6247 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6248 UINT index
, INT
*pImplTypeFlags
)
6250 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6252 TRACE("(%p) index %d\n", This
, index
);
6255 return E_INVALIDARG
;
6257 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6258 *pImplTypeFlags
= 0;
6262 if(index
>= This
->cImplTypes
)
6263 return TYPE_E_ELEMENTNOTFOUND
;
6265 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6271 * Maps between member names and member IDs, and parameter names and
6274 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6275 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6277 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6278 const TLBVarDesc
*pVDesc
;
6282 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6285 /* init out parameters in case of failure */
6286 for (i
= 0; i
< cNames
; i
++)
6287 pMemId
[i
] = MEMBERID_NIL
;
6289 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6291 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6292 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6293 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6294 for(i
=1; i
< cNames
; i
++){
6295 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6296 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6298 if( j
<pFDesc
->funcdesc
.cParams
)
6301 ret
=DISP_E_UNKNOWNNAME
;
6303 TRACE("-- 0x%08x\n", ret
);
6307 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6310 *pMemId
= pVDesc
->vardesc
.memid
;
6313 /* not found, see if it can be found in an inherited interface */
6314 if(This
->impltypes
) {
6315 /* recursive search */
6317 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6319 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6320 ITypeInfo_Release(pTInfo
);
6323 WARN("Could not search inherited interface!\n");
6325 WARN("no names found\n");
6326 return DISP_E_UNKNOWNNAME
;
6332 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6333 __ASM_GLOBAL_FUNC( call_method
,
6335 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6336 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6337 "movl %esp,%ebp\n\t"
6338 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6340 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6342 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6343 "movl 12(%ebp),%edx\n\t"
6344 "movl %esp,%edi\n\t"
6347 "subl %edx,%edi\n\t"
6348 "andl $~15,%edi\n\t"
6349 "movl %edi,%esp\n\t"
6350 "movl 12(%ebp),%ecx\n\t"
6351 "movl 16(%ebp),%esi\n\t"
6354 "1:\tcall *8(%ebp)\n\t"
6355 "subl %esp,%edi\n\t"
6356 "movl 20(%ebp),%ecx\n\t"
6357 "movl %edi,(%ecx)\n\t"
6358 "leal -8(%ebp),%esp\n\t"
6360 __ASM_CFI(".cfi_same_value %edi\n\t")
6362 __ASM_CFI(".cfi_same_value %esi\n\t")
6364 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6365 __ASM_CFI(".cfi_same_value %ebp\n\t")
6368 /* same function but returning floating point */
6369 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6371 /* ITypeInfo::Invoke
6373 * Invokes a method, or accesses a property of an object, that implements the
6374 * interface described by the type description.
6377 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6381 if (TRACE_ON(ole
)) {
6383 TRACE("Calling %p(",func
);
6384 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6385 if (nrargs
> 30) TRACE("...");
6392 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6395 FIXME("unsupported calling convention %d\n",callconv
);
6399 TRACE("returns %08x\n",res
);
6403 #elif defined(__x86_64__)
6405 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6406 __ASM_GLOBAL_FUNC( call_method
,
6408 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6409 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6410 "movq %rsp,%rbp\n\t"
6411 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6413 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6415 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6416 "movq %rcx,%rax\n\t"
6419 "cmovgq %rdx,%rcx\n\t"
6420 "leaq 0(,%rcx,8),%rdx\n\t"
6421 "subq %rdx,%rsp\n\t"
6422 "andq $~15,%rsp\n\t"
6423 "movq %rsp,%rdi\n\t"
6426 "movq 0(%rsp),%rcx\n\t"
6427 "movq 8(%rsp),%rdx\n\t"
6428 "movq 16(%rsp),%r8\n\t"
6429 "movq 24(%rsp),%r9\n\t"
6430 "movq %rcx,%xmm0\n\t"
6431 "movq %rdx,%xmm1\n\t"
6432 "movq %r8,%xmm2\n\t"
6433 "movq %r9,%xmm3\n\t"
6435 "leaq -16(%rbp),%rsp\n\t"
6437 __ASM_CFI(".cfi_same_value %rdi\n\t")
6439 __ASM_CFI(".cfi_same_value %rsi\n\t")
6440 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6442 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6443 __ASM_CFI(".cfi_same_value %rbp\n\t")
6446 /* same function but returning floating point */
6447 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6449 #endif /* __x86_64__ */
6451 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6454 ITypeInfo
*tinfo2
= NULL
;
6455 TYPEATTR
*tattr
= NULL
;
6457 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6460 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6462 tdesc
->u
.hreftype
, hr
);
6465 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6468 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6469 ITypeInfo_Release(tinfo2
);
6473 switch (tattr
->typekind
)
6480 tdesc
= &tattr
->tdescAlias
;
6481 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6484 case TKIND_INTERFACE
:
6485 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6491 case TKIND_DISPATCH
:
6500 FIXME("TKIND_RECORD unhandled.\n");
6505 FIXME("TKIND_UNION unhandled.\n");
6510 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6514 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6515 ITypeInfo_Release(tinfo2
);
6519 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6523 /* enforce only one level of pointer indirection */
6524 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6526 tdesc
= tdesc
->u
.lptdesc
;
6528 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6529 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6530 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6531 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6532 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6534 VARTYPE vt_userdefined
= 0;
6535 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6536 if (tdesc
->vt
== VT_PTR
)
6538 vt_userdefined
= VT_BYREF
;
6539 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6541 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6543 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6544 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6546 *vt
|= vt_userdefined
;
6558 case VT_USERDEFINED
:
6559 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6566 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6567 hr
= DISP_E_BADVARTYPE
;
6571 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6586 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6592 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6596 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6598 ITypeInfo_Release(tinfo2
);
6602 switch(tattr
->typekind
) {
6604 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6607 case TKIND_INTERFACE
:
6608 case TKIND_DISPATCH
:
6609 *guid
= tattr
->guid
;
6613 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6614 hres
= E_UNEXPECTED
;
6617 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6618 ITypeInfo_Release(tinfo2
);
6622 /***********************************************************************
6623 * DispCallFunc (OLEAUT32.@)
6625 * Invokes a function of the specified calling convention, passing the
6626 * specified arguments and returns the result.
6629 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6630 * oVft [I] The offset in the vtable. See notes.
6631 * cc [I] Calling convention of the function to call.
6632 * vtReturn [I] The return type of the function.
6633 * cActuals [I] Number of parameters.
6634 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6635 * prgpvarg [I] The arguments to pass.
6636 * pvargResult [O] The return value of the function. Can be NULL.
6640 * Failure: HRESULT code.
6643 * The HRESULT return value of this function is not affected by the return
6644 * value of the user supplied function, which is returned in pvargResult.
6646 * If pvInstance is NULL then a non-object function is to be called and oVft
6647 * is the address of the function to call.
6649 * The cc parameter can be one of the following values:
6662 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6663 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6666 int argspos
, stack_offset
;
6671 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6672 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6673 pvargResult
, V_VT(pvargResult
));
6675 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6677 FIXME("unsupported calling convention %d\n",cc
);
6678 return E_INVALIDARG
;
6681 /* maximum size for an argument is sizeof(VARIANT) */
6682 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6684 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6688 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6689 func
= vtable
[oVft
/sizeof(void *)];
6690 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6692 else func
= (void *)oVft
;
6694 for (i
= 0; i
< cActuals
; i
++)
6696 VARIANT
*arg
= prgpvarg
[i
];
6707 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6708 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6712 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6713 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6715 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6716 args
[argspos
++] = V_BOOL(arg
);
6719 args
[argspos
++] = V_UI4(arg
);
6722 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6729 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6732 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6736 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6740 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6741 call_method( func
, argspos
, args
, &stack_offset
);
6746 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6749 WARN("invalid return type %u\n", vtReturn
);
6751 return E_INVALIDARG
;
6753 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6757 if (stack_offset
&& cc
== CC_STDCALL
)
6759 WARN( "stack pointer off by %d\n", stack_offset
);
6760 return DISP_E_BADCALLEE
;
6762 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6763 TRACE("retval: "); dump_Variant(pvargResult
);
6766 #elif defined(__x86_64__)
6772 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6773 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6774 pvargResult
, V_VT(pvargResult
));
6776 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6778 FIXME("unsupported calling convention %d\n",cc
);
6779 return E_INVALIDARG
;
6782 /* maximum size for an argument is sizeof(DWORD_PTR) */
6783 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6785 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6789 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6790 func
= vtable
[oVft
/sizeof(void *)];
6791 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6793 else func
= (void *)oVft
;
6795 for (i
= 0; i
< cActuals
; i
++)
6797 VARIANT
*arg
= prgpvarg
[i
];
6803 args
[argspos
++] = (ULONG_PTR
)arg
;
6805 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6806 args
[argspos
++] = V_BOOL(arg
);
6809 args
[argspos
++] = V_UI8(arg
);
6812 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6819 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6823 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6827 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6828 call_method( func
, argspos
, args
);
6831 WARN("invalid return type %u\n", vtReturn
);
6833 return E_INVALIDARG
;
6835 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6839 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6840 TRACE("retval: "); dump_Variant(pvargResult
);
6844 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6845 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6850 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6852 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6855 #define INVBUF_ELEMENT_SIZE \
6856 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6857 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6858 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6859 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6860 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6861 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6862 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6863 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6865 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6870 DISPPARAMS
*pDispParams
,
6871 VARIANT
*pVarResult
,
6872 EXCEPINFO
*pExcepInfo
,
6875 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6877 unsigned int var_index
;
6880 const TLBFuncDesc
*pFuncInfo
;
6883 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6884 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6887 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6888 return DISP_E_MEMBERNOTFOUND
;
6892 ERR("NULL pDispParams not allowed\n");
6893 return E_INVALIDARG
;
6896 dump_DispParms(pDispParams
);
6898 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6900 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6901 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6902 return E_INVALIDARG
;
6905 /* we do this instead of using GetFuncDesc since it will return a fake
6906 * FUNCDESC for dispinterfaces and we want the real function description */
6907 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6908 pFuncInfo
= &This
->funcdescs
[fdc
];
6909 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6910 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6911 !func_restricted( &pFuncInfo
->funcdesc
))
6915 if (fdc
< This
->cFuncs
) {
6916 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6920 TRACE("invoking:\n");
6921 dump_TLBFuncDescOne(pFuncInfo
);
6924 switch (func_desc
->funckind
) {
6925 case FUNC_PUREVIRTUAL
:
6926 case FUNC_VIRTUAL
: {
6927 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6929 VARIANT retval
; /* pointer for storing byref retvals in */
6930 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6931 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6932 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6933 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6934 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6935 UINT vargs_converted
=0;
6939 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6941 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6943 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6944 hres
= DISP_E_PARAMNOTFOUND
;
6949 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6951 ERR("functions with the vararg attribute do not support named arguments\n");
6952 hres
= DISP_E_NONAMEDARGS
;
6956 for (i
= 0; i
< func_desc
->cParams
; i
++)
6958 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6959 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6964 TRACE("changing args\n");
6965 for (i
= 0; i
< func_desc
->cParams
; i
++)
6967 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6968 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6969 VARIANTARG
*src_arg
;
6971 if (wParamFlags
& PARAMFLAG_FLCID
)
6974 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6976 V_I4(arg
) = This
->pTypeLib
->lcid
;
6985 for (j
= 0; j
< cNamedArgs
; j
++)
6986 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6988 src_arg
= &pDispParams
->rgvarg
[j
];
6993 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6995 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6999 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7001 /* under most conditions the caller is not allowed to
7002 * pass in a dispparam arg in the index of what would be
7003 * the retval parameter. however, there is an exception
7004 * where the extra parameter is used in an extra
7005 * IDispatch::Invoke below */
7006 if ((i
< pDispParams
->cArgs
) &&
7007 ((func_desc
->cParams
!= 1) || !pVarResult
||
7008 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7010 hres
= DISP_E_BADPARAMCOUNT
;
7014 /* note: this check is placed so that if the caller passes
7015 * in a VARIANTARG for the retval we just ignore it, like
7017 if (i
== func_desc
->cParams
- 1)
7020 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7021 memset(arg
, 0, sizeof(*arg
));
7022 V_VT(arg
) = rgvt
[i
];
7023 memset(&retval
, 0, sizeof(retval
));
7024 V_BYREF(arg
) = &retval
;
7028 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7029 hres
= E_UNEXPECTED
;
7035 dump_Variant(src_arg
);
7037 if(rgvt
[i
]!=V_VT(src_arg
))
7039 if (rgvt
[i
] == VT_VARIANT
)
7040 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7041 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7043 if (rgvt
[i
] == V_VT(src_arg
))
7044 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7047 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7048 if (wParamFlags
& PARAMFLAG_FIN
)
7049 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7050 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7052 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7054 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7057 SAFEARRAYBOUND bound
;
7061 bound
.cElements
= pDispParams
->cArgs
-i
;
7062 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7064 ERR("SafeArrayCreate failed\n");
7067 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7070 ERR("SafeArrayAccessData failed with %x\n", hres
);
7071 SafeArrayDestroy(a
);
7074 for (j
= 0; j
< bound
.cElements
; j
++)
7075 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7076 hres
= SafeArrayUnaccessData(a
);
7079 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7080 SafeArrayDestroy(a
);
7083 V_ARRAY(&rgvarg
[i
]) = a
;
7084 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7086 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7088 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7089 if (wParamFlags
& PARAMFLAG_FIN
)
7090 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7092 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7093 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7094 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7096 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7098 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7099 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7103 /* FIXME: this doesn't work for VT_BYREF arguments if
7104 * they are not the same type as in the paramdesc */
7105 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7106 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7107 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7112 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
7113 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
7114 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
7117 prgpvarg
[i
] = &rgvarg
[i
];
7121 prgpvarg
[i
] = src_arg
;
7124 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7125 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7126 && V_UNKNOWN(prgpvarg
[i
])) {
7127 IUnknown
*userdefined_iface
;
7130 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7134 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7136 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7140 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7141 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7144 else if (wParamFlags
& PARAMFLAG_FOPT
)
7147 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7148 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7150 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7156 VARIANTARG
*missing_arg
;
7157 /* if the function wants a pointer to a variant then
7158 * set that up, otherwise just pass the VT_ERROR in
7159 * the argument by value */
7160 if (rgvt
[i
] & VT_BYREF
)
7162 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7163 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7164 V_VARIANTREF(arg
) = missing_arg
;
7168 V_VT(missing_arg
) = VT_ERROR
;
7169 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7174 hres
= DISP_E_BADPARAMCOUNT
;
7178 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7180 /* VT_VOID is a special case for return types, so it is not
7181 * handled in the general function */
7182 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7183 V_VT(&varresult
) = VT_EMPTY
;
7186 V_VT(&varresult
) = 0;
7187 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7188 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7191 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7192 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7193 prgpvarg
, &varresult
);
7195 vargs_converted
= 0;
7197 for (i
= 0; i
< func_desc
->cParams
; i
++)
7199 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7200 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7202 if (wParamFlags
& PARAMFLAG_FLCID
)
7204 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7208 TRACE("[retval] value: ");
7209 dump_Variant(prgpvarg
[i
]);
7214 VariantInit(pVarResult
);
7215 /* deref return value */
7216 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7219 VARIANT_ClearInd(prgpvarg
[i
]);
7221 else if (vargs_converted
< pDispParams
->cArgs
)
7223 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7224 if (wParamFlags
& PARAMFLAG_FOUT
)
7226 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7228 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7232 ERR("failed to convert param %d to vt %d\n", i
,
7233 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7238 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7239 func_desc
->cParamsOpt
< 0 &&
7240 i
== func_desc
->cParams
-1)
7242 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7245 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7248 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7251 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7254 ERR("SafeArrayAccessData failed with %x\n", hres
);
7257 for (j
= 0; j
<= ubound
; j
++)
7258 VariantClear(&v
[j
]);
7259 hres
= SafeArrayUnaccessData(a
);
7262 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7266 VariantClear(&rgvarg
[i
]);
7269 else if (wParamFlags
& PARAMFLAG_FOPT
)
7271 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7272 VariantClear(&rgvarg
[i
]);
7275 VariantClear(&missing_arg
[i
]);
7278 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7280 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7281 hres
= DISP_E_EXCEPTION
;
7284 IErrorInfo
*pErrorInfo
;
7285 pExcepInfo
->scode
= V_ERROR(&varresult
);
7286 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7288 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7289 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7290 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7291 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7293 IErrorInfo_Release(pErrorInfo
);
7297 if (V_VT(&varresult
) != VT_ERROR
)
7299 TRACE("varresult value: ");
7300 dump_Variant(&varresult
);
7304 VariantClear(pVarResult
);
7305 *pVarResult
= varresult
;
7308 VariantClear(&varresult
);
7311 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7312 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7313 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7314 (pDispParams
->cArgs
!= 0))
7316 if (V_VT(pVarResult
) == VT_DISPATCH
)
7318 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7319 /* Note: not VariantClear; we still need the dispatch
7320 * pointer to be valid */
7321 VariantInit(pVarResult
);
7322 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7323 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7324 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7325 IDispatch_Release(pDispatch
);
7329 VariantClear(pVarResult
);
7330 hres
= DISP_E_NOTACOLLECTION
;
7338 case FUNC_DISPATCH
: {
7341 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7342 if (SUCCEEDED(hres
)) {
7343 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7344 hres
= IDispatch_Invoke(
7345 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7346 pVarResult
,pExcepInfo
,pArgErr
7349 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7350 IDispatch_Release(disp
);
7352 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7356 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7361 TRACE("-- 0x%08x\n", hres
);
7364 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7367 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7368 if(FAILED(hres
)) return hres
;
7370 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7371 dump_VARDESC(var_desc
);
7372 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7376 /* not found, look for it in inherited interfaces */
7377 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7378 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7379 if(This
->impltypes
) {
7380 /* recursive search */
7382 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7383 if(SUCCEEDED(hres
)){
7384 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7385 ITypeInfo_Release(pTInfo
);
7388 WARN("Could not search inherited interface!\n");
7391 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7392 return DISP_E_MEMBERNOTFOUND
;
7395 /* ITypeInfo::GetDocumentation
7397 * Retrieves the documentation string, the complete Help file name and path,
7398 * and the context ID for the Help topic for a specified type description.
7400 * (Can be tested by the Visual Basic Editor in Word for instance.)
7402 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7403 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7404 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7406 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7407 const TLBFuncDesc
*pFDesc
;
7408 const TLBVarDesc
*pVDesc
;
7409 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7410 " HelpContext(%p) HelpFile(%p)\n",
7411 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7412 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7414 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7416 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7418 *pdwHelpContext
=This
->dwHelpContext
;
7420 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7422 }else {/* for a member */
7423 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7426 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7428 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7430 *pdwHelpContext
=pFDesc
->helpcontext
;
7432 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7435 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7438 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7440 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7442 *pdwHelpContext
=pVDesc
->HelpContext
;
7444 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7449 if(This
->impltypes
&&
7450 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7451 /* recursive search */
7454 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7455 if(SUCCEEDED(result
)) {
7456 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7457 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7458 ITypeInfo_Release(pTInfo
);
7461 WARN("Could not search inherited interface!\n");
7464 WARN("member %d not found\n", memid
);
7465 return TYPE_E_ELEMENTNOTFOUND
;
7468 /* ITypeInfo::GetDllEntry
7470 * Retrieves a description or specification of an entry point for a function
7473 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7474 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7477 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7478 const TLBFuncDesc
*pFDesc
;
7480 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7482 if (pBstrDllName
) *pBstrDllName
= NULL
;
7483 if (pBstrName
) *pBstrName
= NULL
;
7484 if (pwOrdinal
) *pwOrdinal
= 0;
7486 if (This
->typekind
!= TKIND_MODULE
)
7487 return TYPE_E_BADMODULEKIND
;
7489 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7491 dump_TypeInfo(This
);
7493 dump_TLBFuncDescOne(pFDesc
);
7496 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7498 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7500 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7508 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7511 return TYPE_E_ELEMENTNOTFOUND
;
7514 /* internal function to make the inherited interfaces' methods appear
7515 * part of the interface */
7516 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7517 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7519 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7522 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7524 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7526 ITypeInfo
*pSubTypeInfo
;
7528 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7532 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7534 ITypeInfo_Release(pSubTypeInfo
);
7538 *hRefType
-= DISPATCH_HREF_OFFSET
;
7540 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7541 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7546 /* ITypeInfo::GetRefTypeInfo
7548 * If a type description references other type descriptions, it retrieves
7549 * the referenced type descriptions.
7551 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7554 ITypeInfo
**ppTInfo
)
7556 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7557 HRESULT result
= E_FAIL
;
7560 return E_INVALIDARG
;
7562 if ((INT
)hRefType
< 0) {
7563 ITypeInfoImpl
*pTypeInfoImpl
;
7565 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7566 !(This
->typekind
== TKIND_INTERFACE
||
7567 This
->typekind
== TKIND_DISPATCH
))
7568 return TYPE_E_ELEMENTNOTFOUND
;
7570 /* when we meet a DUAL typeinfo, we must create the alternate
7573 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7575 *pTypeInfoImpl
= *This
;
7576 pTypeInfoImpl
->ref
= 0;
7577 list_init(&pTypeInfoImpl
->custdata_list
);
7579 if (This
->typekind
== TKIND_INTERFACE
)
7580 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7582 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7584 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7585 /* the AddRef implicitly adds a reference to the parent typelib, which
7586 * stops the copied data from being destroyed until the new typeinfo's
7587 * refcount goes to zero, but we need to signal to the new instance to
7588 * not free its data structures when it is destroyed */
7589 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7591 ITypeInfo_AddRef(*ppTInfo
);
7594 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7595 (This
->typekind
== TKIND_DISPATCH
))
7597 HREFTYPE href_dispatch
= hRefType
;
7598 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7600 TLBRefType
*ref_type
;
7601 ITypeLib
*pTLib
= NULL
;
7604 if(!(hRefType
& 0x1)){
7605 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7607 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7610 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7611 ITypeInfo_AddRef(*ppTInfo
);
7617 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7619 if(ref_type
->reference
== (hRefType
& (~0x3)))
7622 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7624 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7628 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7630 TRACE("internal reference\n");
7631 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7633 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7634 TRACE("typeinfo in imported typelib that is already loaded\n");
7635 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7636 ITypeLib_AddRef(pTLib
);
7641 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7643 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7644 ref_type
->pImpTLInfo
->wVersionMajor
,
7645 ref_type
->pImpTLInfo
->wVersionMinor
,
7646 This
->pTypeLib
->syskind
,
7647 ref_type
->pImpTLInfo
->lcid
, &libnam
);
7649 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7651 result
= LoadTypeLib(libnam
, &pTLib
);
7652 SysFreeString(libnam
);
7654 if(SUCCEEDED(result
)) {
7655 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7656 ITypeLib_AddRef(pTLib
);
7660 if(SUCCEEDED(result
)) {
7661 if(ref_type
->index
== TLB_REF_USE_GUID
)
7662 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7664 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7667 ITypeLib_Release(pTLib
);
7671 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7672 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7676 /* ITypeInfo::AddressOfMember
7678 * Retrieves the addresses of static functions or variables, such as those
7681 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7682 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7684 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7690 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7692 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7696 module
= LoadLibraryW(dll
);
7699 ERR("couldn't load %s\n", debugstr_w(dll
));
7701 SysFreeString(entry
);
7702 return STG_E_FILENOTFOUND
;
7704 /* FIXME: store library somewhere where we can free it */
7709 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7710 entryA
= heap_alloc(len
);
7711 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7713 *ppv
= GetProcAddress(module
, entryA
);
7715 ERR("function not found %s\n", debugstr_a(entryA
));
7721 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7723 ERR("function not found %d\n", ordinal
);
7727 SysFreeString(entry
);
7730 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7735 /* ITypeInfo::CreateInstance
7737 * Creates a new instance of a type that describes a component object class
7740 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7741 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7743 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7747 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7753 WARN("Not able to aggregate\n");
7754 return CLASS_E_NOAGGREGATION
;
7757 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7758 if(FAILED(hr
)) return hr
;
7760 if(pTA
->typekind
!= TKIND_COCLASS
)
7762 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7768 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7771 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7772 TRACE("GetActiveObject rets %08x\n", hr
);
7775 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7776 IUnknown_Release(pUnk
);
7781 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7782 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7786 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7790 /* ITypeInfo::GetMops
7792 * Retrieves marshalling information.
7794 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7797 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7798 FIXME("(%p %d) stub!\n", This
, memid
);
7803 /* ITypeInfo::GetContainingTypeLib
7805 * Retrieves the containing type library and the index of the type description
7806 * within that type library.
7808 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7809 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7811 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7813 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7815 *pIndex
=This
->index
;
7816 TRACE("returning pIndex=%d\n", *pIndex
);
7820 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7821 ITypeLib_AddRef(*ppTLib
);
7822 TRACE("returning ppTLib=%p\n", *ppTLib
);
7828 /* ITypeInfo::ReleaseTypeAttr
7830 * Releases a TYPEATTR previously returned by Get
7833 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7834 TYPEATTR
* pTypeAttr
)
7836 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7837 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7838 heap_free(pTypeAttr
);
7841 /* ITypeInfo::ReleaseFuncDesc
7843 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7845 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7847 FUNCDESC
*pFuncDesc
)
7849 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7852 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7854 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7855 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7856 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7858 SysFreeString((BSTR
)pFuncDesc
);
7861 /* ITypeInfo::ReleaseVarDesc
7863 * Releases a VARDESC previously returned by GetVarDesc.
7865 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7868 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7869 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7871 TLB_FreeVarDesc(pVarDesc
);
7874 /* ITypeInfo2::GetTypeKind
7876 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7879 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7880 TYPEKIND
*pTypeKind
)
7882 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7883 *pTypeKind
=This
->typekind
;
7884 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7888 /* ITypeInfo2::GetTypeFlags
7890 * Returns the type flags without any allocations. This returns a DWORD type
7891 * flag, which expands the type flags without growing the TYPEATTR (type
7895 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7897 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7898 *pTypeFlags
=This
->wTypeFlags
;
7899 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7903 /* ITypeInfo2::GetFuncIndexOfMemId
7904 * Binds to a specific member based on a known DISPID, where the member name
7905 * is not known (for example, when binding to a default member).
7908 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7909 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7911 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7915 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7916 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7917 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7920 if(fdc
< This
->cFuncs
) {
7924 result
= TYPE_E_ELEMENTNOTFOUND
;
7926 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7927 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7931 /* TypeInfo2::GetVarIndexOfMemId
7933 * Binds to a specific member based on a known DISPID, where the member name
7934 * is not known (for example, when binding to a default member).
7937 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7938 MEMBERID memid
, UINT
*pVarIndex
)
7940 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7941 TLBVarDesc
*pVarInfo
;
7943 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7945 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7947 return TYPE_E_ELEMENTNOTFOUND
;
7949 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7954 /* ITypeInfo2::GetCustData
7956 * Gets the custom data
7958 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7963 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7964 TLBCustData
*pCData
;
7966 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7968 if(!guid
|| !pVarVal
)
7969 return E_INVALIDARG
;
7971 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
7973 VariantInit( pVarVal
);
7975 VariantCopy( pVarVal
, &pCData
->data
);
7977 VariantClear( pVarVal
);
7981 /* ITypeInfo2::GetFuncCustData
7983 * Gets the custom data
7985 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7991 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7992 TLBCustData
*pCData
;
7993 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7995 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7997 if(index
>= This
->cFuncs
)
7998 return TYPE_E_ELEMENTNOTFOUND
;
8000 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8002 return TYPE_E_ELEMENTNOTFOUND
;
8004 VariantInit(pVarVal
);
8005 VariantCopy(pVarVal
, &pCData
->data
);
8010 /* ITypeInfo2::GetParamCustData
8012 * Gets the custom data
8014 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8021 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8022 TLBCustData
*pCData
;
8023 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8025 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8026 debugstr_guid(guid
), pVarVal
);
8028 if(indexFunc
>= This
->cFuncs
)
8029 return TYPE_E_ELEMENTNOTFOUND
;
8031 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8032 return TYPE_E_ELEMENTNOTFOUND
;
8034 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8036 return TYPE_E_ELEMENTNOTFOUND
;
8038 VariantInit(pVarVal
);
8039 VariantCopy(pVarVal
, &pCData
->data
);
8044 /* ITypeInfo2::GetVarCustData
8046 * Gets the custom data
8048 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8054 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8055 TLBCustData
*pCData
;
8056 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8058 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8060 if(index
>= This
->cVars
)
8061 return TYPE_E_ELEMENTNOTFOUND
;
8063 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8065 return TYPE_E_ELEMENTNOTFOUND
;
8067 VariantInit(pVarVal
);
8068 VariantCopy(pVarVal
, &pCData
->data
);
8073 /* ITypeInfo2::GetImplCustData
8075 * Gets the custom data
8077 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8083 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8084 TLBCustData
*pCData
;
8085 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8087 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8089 if(index
>= This
->cImplTypes
)
8090 return TYPE_E_ELEMENTNOTFOUND
;
8092 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8094 return TYPE_E_ELEMENTNOTFOUND
;
8096 VariantInit(pVarVal
);
8097 VariantCopy(pVarVal
, &pCData
->data
);
8102 /* ITypeInfo2::GetDocumentation2
8104 * Retrieves the documentation string, the complete Help file name and path,
8105 * the localization context to use, and the context ID for the library Help
8106 * topic in the Help file.
8109 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8113 BSTR
*pbstrHelpString
,
8114 DWORD
*pdwHelpStringContext
,
8115 BSTR
*pbstrHelpStringDll
)
8117 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8118 const TLBFuncDesc
*pFDesc
;
8119 const TLBVarDesc
*pVDesc
;
8120 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8121 "HelpStringContext(%p) HelpStringDll(%p)\n",
8122 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8123 pbstrHelpStringDll
);
8124 /* the help string should be obtained from the helpstringdll,
8125 * using the _DLLGetDocumentation function, based on the supplied
8126 * lcid. Nice to do sometime...
8128 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8130 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8131 if(pdwHelpStringContext
)
8132 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8133 if(pbstrHelpStringDll
)
8134 *pbstrHelpStringDll
=
8135 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8137 }else {/* for a member */
8138 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8141 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8142 if(pdwHelpStringContext
)
8143 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8144 if(pbstrHelpStringDll
)
8145 *pbstrHelpStringDll
=
8146 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8149 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8152 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8153 if(pdwHelpStringContext
)
8154 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8155 if(pbstrHelpStringDll
)
8156 *pbstrHelpStringDll
=
8157 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8161 return TYPE_E_ELEMENTNOTFOUND
;
8164 /* ITypeInfo2::GetAllCustData
8166 * Gets all custom data items for the Type info.
8169 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8171 CUSTDATA
*pCustData
)
8173 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8175 TRACE("%p %p\n", This
, pCustData
);
8177 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8180 /* ITypeInfo2::GetAllFuncCustData
8182 * Gets all custom data items for the specified Function
8185 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8188 CUSTDATA
*pCustData
)
8190 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8191 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8193 TRACE("%p %u %p\n", This
, index
, pCustData
);
8195 if(index
>= This
->cFuncs
)
8196 return TYPE_E_ELEMENTNOTFOUND
;
8198 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8201 /* ITypeInfo2::GetAllParamCustData
8203 * Gets all custom data items for the Functions
8206 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8207 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8209 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8210 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8212 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8214 if(indexFunc
>= This
->cFuncs
)
8215 return TYPE_E_ELEMENTNOTFOUND
;
8217 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8218 return TYPE_E_ELEMENTNOTFOUND
;
8220 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8223 /* ITypeInfo2::GetAllVarCustData
8225 * Gets all custom data items for the specified Variable
8228 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8229 UINT index
, CUSTDATA
*pCustData
)
8231 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8232 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8234 TRACE("%p %u %p\n", This
, index
, pCustData
);
8236 if(index
>= This
->cVars
)
8237 return TYPE_E_ELEMENTNOTFOUND
;
8239 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8242 /* ITypeInfo2::GetAllImplCustData
8244 * Gets all custom data items for the specified implementation type
8247 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8250 CUSTDATA
*pCustData
)
8252 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8253 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8255 TRACE("%p %u %p\n", This
, index
, pCustData
);
8257 if(index
>= This
->cImplTypes
)
8258 return TYPE_E_ELEMENTNOTFOUND
;
8260 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8263 static const ITypeInfo2Vtbl tinfvt
=
8266 ITypeInfo_fnQueryInterface
,
8268 ITypeInfo_fnRelease
,
8270 ITypeInfo_fnGetTypeAttr
,
8271 ITypeInfo_fnGetTypeComp
,
8272 ITypeInfo_fnGetFuncDesc
,
8273 ITypeInfo_fnGetVarDesc
,
8274 ITypeInfo_fnGetNames
,
8275 ITypeInfo_fnGetRefTypeOfImplType
,
8276 ITypeInfo_fnGetImplTypeFlags
,
8277 ITypeInfo_fnGetIDsOfNames
,
8279 ITypeInfo_fnGetDocumentation
,
8280 ITypeInfo_fnGetDllEntry
,
8281 ITypeInfo_fnGetRefTypeInfo
,
8282 ITypeInfo_fnAddressOfMember
,
8283 ITypeInfo_fnCreateInstance
,
8284 ITypeInfo_fnGetMops
,
8285 ITypeInfo_fnGetContainingTypeLib
,
8286 ITypeInfo_fnReleaseTypeAttr
,
8287 ITypeInfo_fnReleaseFuncDesc
,
8288 ITypeInfo_fnReleaseVarDesc
,
8290 ITypeInfo2_fnGetTypeKind
,
8291 ITypeInfo2_fnGetTypeFlags
,
8292 ITypeInfo2_fnGetFuncIndexOfMemId
,
8293 ITypeInfo2_fnGetVarIndexOfMemId
,
8294 ITypeInfo2_fnGetCustData
,
8295 ITypeInfo2_fnGetFuncCustData
,
8296 ITypeInfo2_fnGetParamCustData
,
8297 ITypeInfo2_fnGetVarCustData
,
8298 ITypeInfo2_fnGetImplTypeCustData
,
8299 ITypeInfo2_fnGetDocumentation2
,
8300 ITypeInfo2_fnGetAllCustData
,
8301 ITypeInfo2_fnGetAllFuncCustData
,
8302 ITypeInfo2_fnGetAllParamCustData
,
8303 ITypeInfo2_fnGetAllVarCustData
,
8304 ITypeInfo2_fnGetAllImplTypeCustData
,
8307 /******************************************************************************
8308 * CreateDispTypeInfo [OLEAUT32.31]
8310 * Build type information for an object so it can be called through an
8311 * IDispatch interface.
8314 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8315 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8318 * This call allows an objects methods to be accessed through IDispatch, by
8319 * building an ITypeInfo object that IDispatch can use to call through.
8321 HRESULT WINAPI
CreateDispTypeInfo(
8322 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8323 LCID lcid
, /* [I] Locale Id */
8324 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8326 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8327 ITypeLibImpl
*pTypeLibImpl
;
8328 unsigned int param
, func
;
8329 TLBFuncDesc
*pFuncDesc
;
8333 pTypeLibImpl
= TypeLibImpl_Constructor();
8334 if (!pTypeLibImpl
) return E_FAIL
;
8336 pTypeLibImpl
->TypeInfoCount
= 2;
8337 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8339 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8340 pTIIface
->pTypeLib
= pTypeLibImpl
;
8341 pTIIface
->index
= 0;
8342 pTIIface
->Name
= NULL
;
8343 pTIIface
->dwHelpContext
= -1;
8344 pTIIface
->guid
= NULL
;
8345 pTIIface
->lcid
= lcid
;
8346 pTIIface
->typekind
= TKIND_INTERFACE
;
8347 pTIIface
->wMajorVerNum
= 0;
8348 pTIIface
->wMinorVerNum
= 0;
8349 pTIIface
->cbAlignment
= 2;
8350 pTIIface
->cbSizeInstance
= -1;
8351 pTIIface
->cbSizeVft
= -1;
8352 pTIIface
->cFuncs
= 0;
8353 pTIIface
->cImplTypes
= 0;
8354 pTIIface
->cVars
= 0;
8355 pTIIface
->wTypeFlags
= 0;
8356 pTIIface
->hreftype
= 0;
8358 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8359 pFuncDesc
= pTIIface
->funcdescs
;
8360 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8361 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8362 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8363 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8364 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8365 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8366 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8367 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8368 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8369 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8370 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8371 pFuncDesc
->funcdesc
.cScodes
= 0;
8372 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8373 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8374 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8375 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8376 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8377 md
->cArgs
* sizeof(ELEMDESC
));
8378 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8379 for(param
= 0; param
< md
->cArgs
; param
++) {
8380 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8381 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8383 pFuncDesc
->helpcontext
= 0;
8384 pFuncDesc
->HelpStringContext
= 0;
8385 pFuncDesc
->HelpString
= NULL
;
8386 pFuncDesc
->Entry
= NULL
;
8387 list_init(&pFuncDesc
->custdata_list
);
8392 dump_TypeInfo(pTIIface
);
8394 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8395 pTIClass
->pTypeLib
= pTypeLibImpl
;
8396 pTIClass
->index
= 1;
8397 pTIClass
->Name
= NULL
;
8398 pTIClass
->dwHelpContext
= -1;
8399 pTIClass
->guid
= NULL
;
8400 pTIClass
->lcid
= lcid
;
8401 pTIClass
->typekind
= TKIND_COCLASS
;
8402 pTIClass
->wMajorVerNum
= 0;
8403 pTIClass
->wMinorVerNum
= 0;
8404 pTIClass
->cbAlignment
= 2;
8405 pTIClass
->cbSizeInstance
= -1;
8406 pTIClass
->cbSizeVft
= -1;
8407 pTIClass
->cFuncs
= 0;
8408 pTIClass
->cImplTypes
= 1;
8409 pTIClass
->cVars
= 0;
8410 pTIClass
->wTypeFlags
= 0;
8411 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8413 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8415 ref
= heap_alloc_zero(sizeof(*ref
));
8416 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8417 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8419 dump_TypeInfo(pTIClass
);
8421 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8423 ITypeInfo_AddRef(*pptinfo
);
8424 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8430 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8432 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8434 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8437 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8439 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8441 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8444 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8446 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8448 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8451 static HRESULT WINAPI
ITypeComp_fnBind(
8456 ITypeInfo
** ppTInfo
,
8457 DESCKIND
* pDescKind
,
8460 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8461 const TLBFuncDesc
*pFDesc
;
8462 const TLBVarDesc
*pVDesc
;
8463 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8466 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8468 *pDescKind
= DESCKIND_NONE
;
8469 pBindPtr
->lpfuncdesc
= NULL
;
8472 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8473 pFDesc
= &This
->funcdescs
[fdc
];
8474 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8475 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8478 /* name found, but wrong flags */
8479 hr
= TYPE_E_TYPEMISMATCH
;
8483 if (fdc
< This
->cFuncs
)
8485 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8487 &pBindPtr
->lpfuncdesc
,
8488 This
->typekind
== TKIND_DISPATCH
);
8491 *pDescKind
= DESCKIND_FUNCDESC
;
8492 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8493 ITypeInfo_AddRef(*ppTInfo
);
8496 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8498 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8501 *pDescKind
= DESCKIND_VARDESC
;
8502 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8503 ITypeInfo_AddRef(*ppTInfo
);
8508 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8509 /* recursive search */
8513 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8516 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8517 ITypeInfo_Release(pTInfo
);
8521 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8522 ITypeComp_Release(pTComp
);
8523 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8524 This
->typekind
== TKIND_DISPATCH
)
8526 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8527 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8528 SysFreeString((BSTR
)tmp
);
8532 WARN("Could not search inherited interface!\n");
8534 if (hr
== DISP_E_MEMBERNOTFOUND
)
8536 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8540 static HRESULT WINAPI
ITypeComp_fnBindType(
8544 ITypeInfo
** ppTInfo
,
8545 ITypeComp
** ppTComp
)
8547 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8549 /* strange behaviour (does nothing) but like the
8552 if (!ppTInfo
|| !ppTComp
)
8561 static const ITypeCompVtbl tcompvt
=
8564 ITypeComp_fnQueryInterface
,
8566 ITypeComp_fnRelease
,
8569 ITypeComp_fnBindType
8572 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8573 ICreateTypeLib2
** ppctlib
)
8578 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8580 if (!szFile
) return E_INVALIDARG
;
8582 This
= TypeLibImpl_Constructor();
8584 return E_OUTOFMEMORY
;
8586 This
->lcid
= GetSystemDefaultLCID();
8587 This
->syskind
= syskind
;
8588 This
->ptr_size
= get_ptr_size(syskind
);
8590 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8592 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8593 return E_OUTOFMEMORY
;
8595 lstrcpyW(This
->path
, szFile
);
8597 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8598 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8602 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8603 REFIID riid
, void **object
)
8605 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8607 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8610 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8612 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8614 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8617 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8619 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8621 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8624 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8625 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8627 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8628 ITypeInfoImpl
*info
;
8631 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8633 if (!ctinfo
|| !name
)
8634 return E_INVALIDARG
;
8636 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8638 return TYPE_E_NAMECONFLICT
;
8640 if (This
->typeinfos
)
8641 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8642 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8644 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8646 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8648 info
->pTypeLib
= This
;
8649 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8650 info
->index
= This
->TypeInfoCount
;
8651 info
->typekind
= kind
;
8652 info
->cbAlignment
= 4;
8654 switch(info
->typekind
) {
8656 case TKIND_INTERFACE
:
8657 case TKIND_DISPATCH
:
8659 info
->cbSizeInstance
= This
->ptr_size
;
8663 info
->cbSizeInstance
= 0;
8666 info
->cbSizeInstance
= 2;
8669 info
->cbSizeInstance
= -0x75;
8672 FIXME("unrecognized typekind %d\n", info
->typekind
);
8673 info
->cbSizeInstance
= 0xdeadbeef;
8677 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8678 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8680 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8684 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8686 ++This
->TypeInfoCount
;
8691 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8694 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8696 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8699 return E_INVALIDARG
;
8701 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8706 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8707 WORD majorVerNum
, WORD minorVerNum
)
8709 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8711 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8713 This
->ver_major
= majorVerNum
;
8714 This
->ver_minor
= minorVerNum
;
8719 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8722 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8724 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8726 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8731 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8734 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8736 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8739 return E_INVALIDARG
;
8741 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8746 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8747 LPOLESTR helpFileName
)
8749 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8751 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8754 return E_INVALIDARG
;
8756 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8761 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8764 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8766 TRACE("%p %d\n", This
, helpContext
);
8768 This
->dwHelpContext
= helpContext
;
8773 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8776 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8778 TRACE("%p %x\n", This
, lcid
);
8780 This
->set_lcid
= lcid
;
8785 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8788 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8790 TRACE("%p %x\n", This
, libFlags
);
8792 This
->libflags
= libFlags
;
8797 typedef struct tagWMSFT_SegContents
{
8800 } WMSFT_SegContents
;
8802 typedef struct tagWMSFT_TLBFile
{
8804 WMSFT_SegContents typeinfo_seg
;
8805 WMSFT_SegContents impfile_seg
;
8806 WMSFT_SegContents impinfo_seg
;
8807 WMSFT_SegContents ref_seg
;
8808 WMSFT_SegContents guidhash_seg
;
8809 WMSFT_SegContents guid_seg
;
8810 WMSFT_SegContents namehash_seg
;
8811 WMSFT_SegContents name_seg
;
8812 WMSFT_SegContents string_seg
;
8813 WMSFT_SegContents typdesc_seg
;
8814 WMSFT_SegContents arraydesc_seg
;
8815 WMSFT_SegContents custdata_seg
;
8816 WMSFT_SegContents cdguids_seg
;
8818 WMSFT_SegContents aux_seg
;
8821 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8822 WMSFT_TLBFile
*file
)
8828 file
->string_seg
.len
= 0;
8829 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8832 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8834 return E_UNEXPECTED
;
8836 size
+= sizeof(INT16
);
8838 size
= (size
+ 4) & ~0x3;
8842 file
->string_seg
.len
+= size
;
8844 /* temporarily use str->offset to store the length of the aligned,
8845 * converted string */
8849 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8852 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8855 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8856 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8858 heap_free(file
->string_seg
.data
);
8859 return E_UNEXPECTED
;
8862 *((INT16
*)data
) = size
;
8864 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8868 str
->offset
= last_offs
;
8875 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8876 WMSFT_TLBFile
*file
)
8881 MSFT_NameIntro
*last_intro
= NULL
;
8883 file
->header
.nametablecount
= 0;
8884 file
->header
.nametablechars
= 0;
8886 file
->name_seg
.len
= 0;
8887 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8890 size
= strlenW(str
->str
);
8891 file
->header
.nametablechars
+= size
;
8892 file
->header
.nametablecount
++;
8894 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8896 return E_UNEXPECTED
;
8898 size
+= sizeof(MSFT_NameIntro
);
8900 size
= (size
+ 4) & ~0x3;
8904 file
->name_seg
.len
+= size
;
8906 /* temporarily use str->offset to store the length of the aligned,
8907 * converted string */
8911 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8912 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8915 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8917 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8919 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8920 data
+ sizeof(MSFT_NameIntro
),
8921 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8923 heap_free(file
->name_seg
.data
);
8924 return E_UNEXPECTED
;
8926 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8928 intro
->hreftype
= -1; /* TODO? */
8929 intro
->namelen
= size
& 0xFF;
8930 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8931 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8932 intro
->namelen
|= hash
<< 16;
8933 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8934 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
8936 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8937 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8939 /* update str->offset to actual value to use in other
8940 * compilation functions that require positions within
8941 * the string table */
8945 str
->offset
= last_offs
;
8950 last_intro
->hreftype
= 0; /* last one is 0? */
8955 static inline int hash_guid(GUID
*guid
)
8959 for (i
= 0; i
< 8; i
++)
8960 hash
^= ((const short *)guid
)[i
];
8965 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8968 MSFT_GuidEntry
*entry
;
8970 int hash_key
, *guidhashtab
;
8972 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8973 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8975 entry
= file
->guid_seg
.data
;
8977 guidhashtab
= file
->guidhash_seg
.data
;
8978 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
8979 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
8980 entry
->hreftype
= guid
->hreftype
;
8982 hash_key
= hash_guid(&guid
->guid
);
8983 entry
->next_hash
= guidhashtab
[hash_key
];
8984 guidhashtab
[hash_key
] = offs
;
8986 guid
->offset
= offs
;
8987 offs
+= sizeof(MSFT_GuidEntry
);
8994 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
8997 VARTYPE arg_type
= V_VT(value
);
9000 DWORD ret
= file
->custdata_seg
.len
;
9002 if(arg_type
== VT_INT
)
9004 if(arg_type
== VT_UINT
)
9008 if(V_VT(value
) != arg_type
) {
9009 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9011 ERR("VariantChangeType failed: %08x\n", hres
);
9016 /* Check if default value can be stored in-place */
9021 if(V_UI4(&v
) > 0x3ffffff)
9034 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9037 /* have to allocate space in custdata_seg */
9046 /* Construct the data to be allocated */
9049 if(file
->custdata_seg
.data
){
9050 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9051 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9052 file
->custdata_seg
.len
+= sizeof(int) * 2;
9054 file
->custdata_seg
.len
= sizeof(int) * 2;
9055 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9058 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9059 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9061 /* TODO: Check if the encoded data is already present in custdata_seg */
9067 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9070 if(file
->custdata_seg
.data
){
9071 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9072 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9073 file
->custdata_seg
.len
+= len
;
9075 file
->custdata_seg
.len
= len
;
9076 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9079 *((unsigned short *)data
) = V_VT(value
);
9080 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9081 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9082 if(V_BSTR(&v
)[i
] <= 0x7f)
9083 data
[i
+6] = V_BSTR(&v
)[i
];
9087 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9088 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9091 /* TODO: Check if the encoded data is already present in custdata_seg */
9096 FIXME("Argument type not yet handled\n");
9101 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9103 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9105 DWORD offs
= file
->arraydesc_seg
.len
;
9109 /* TODO: we should check for duplicates, but that's harder because each
9110 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9111 * at the library-level) */
9113 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9114 if(!file
->arraydesc_seg
.data
)
9115 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9117 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9118 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
9120 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9121 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9122 for(i
= 0; i
< desc
->cDims
; ++i
){
9123 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9124 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9130 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9136 VARTYPE vt
, subtype
;
9147 vt
= desc
->vt
& VT_TYPEMASK
;
9149 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9151 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9152 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9154 *out_size
+= 2 * sizeof(DWORD
);
9155 }else if(vt
== VT_CARRAY
){
9156 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9157 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9159 }else if(vt
== VT_USERDEFINED
){
9160 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9161 encoded
[1] = desc
->u
.hreftype
;
9162 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9164 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9182 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9185 data
= file
->typdesc_seg
.data
;
9186 while(offs
< file
->typdesc_seg
.len
){
9187 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9189 offs
+= sizeof(encoded
);
9192 file
->typdesc_seg
.len
+= sizeof(encoded
);
9193 if(!file
->typdesc_seg
.data
)
9194 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9196 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9198 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9203 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9205 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9206 DWORD ret
= cdguids_seg
->len
, offs
;
9207 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9210 if(list_empty(custdata_list
))
9213 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9214 if(!cdguids_seg
->data
){
9215 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9217 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9219 offs
= ret
+ sizeof(MSFT_CDGuid
);
9220 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9221 cdguid
->GuidOffset
= cd
->guid
->offset
;
9222 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9223 cdguid
->next
= offs
;
9224 offs
+= sizeof(MSFT_CDGuid
);
9234 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9235 WMSFT_TLBFile
*file
)
9237 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9238 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9239 MSFT_VarRecord
*varrecord
;
9240 MSFT_FuncRecord
*funcrecord
;
9242 DWORD
*name
, *offsets
, offs
;
9244 for(i
= 0; i
< info
->cFuncs
; ++i
){
9245 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9247 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9249 /* optional fields */
9250 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9251 if(!list_empty(&desc
->custdata_list
))
9252 recorded_size
+= 7 * sizeof(INT
);
9253 else if(desc
->HelpStringContext
!= 0)
9254 recorded_size
+= 6 * sizeof(INT
);
9256 else if(desc
->Entry
)
9257 recorded_size
+= 3 * sizeof(INT
);
9258 else if(desc
->HelpString
)
9259 recorded_size
+= 2 * sizeof(INT
);
9260 else if(desc
->helpcontext
)
9261 recorded_size
+= sizeof(INT
);
9263 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9265 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9266 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9267 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9272 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9275 for(i
= 0; i
< info
->cVars
; ++i
){
9276 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9278 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9280 /* optional fields */
9281 if(desc
->HelpStringContext
!= 0)
9282 recorded_size
+= 5 * sizeof(INT
);
9283 else if(!list_empty(&desc
->custdata_list
))
9284 recorded_size
+= 4 * sizeof(INT
);
9286 else if(desc
->HelpString
)
9287 recorded_size
+= 2 * sizeof(INT
);
9288 else if(desc
->HelpContext
!= 0)
9289 recorded_size
+= sizeof(INT
);
9291 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9294 if(!recorded_size
&& !extra_size
)
9297 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9299 aux_seg
->len
+= recorded_size
+ extra_size
;
9301 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9304 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9306 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9308 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9310 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9313 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9314 for(i
= 0; i
< info
->cFuncs
; ++i
){
9315 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9316 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9318 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9319 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9320 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9321 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9324 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9329 * ^has_param_defaults
9330 * ^oEntry_is_intresource
9332 funcrecord
->FKCCIC
=
9333 desc
->funcdesc
.funckind
|
9334 (desc
->funcdesc
.invkind
<< 3) |
9335 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9336 (desc
->funcdesc
.callconv
<< 8);
9338 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9339 funcrecord
->FKCCIC
|= 0x2000;
9341 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9342 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9343 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9344 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9347 if(paramdefault_size
> 0)
9348 funcrecord
->FKCCIC
|= 0x1000;
9350 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9351 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9353 /* optional fields */
9355 if(!list_empty(&desc
->custdata_list
)){
9356 size
+= 7 * sizeof(INT
);
9357 funcrecord
->HelpContext
= desc
->helpcontext
;
9358 if(desc
->HelpString
)
9359 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9361 funcrecord
->oHelpString
= -1;
9363 funcrecord
->oEntry
= -1;
9364 else if(IS_INTRESOURCE(desc
->Entry
))
9365 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9367 funcrecord
->oEntry
= desc
->Entry
->offset
;
9368 funcrecord
->res9
= -1;
9369 funcrecord
->resA
= -1;
9370 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9371 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9372 }else if(desc
->HelpStringContext
!= 0){
9373 size
+= 6 * sizeof(INT
);
9374 funcrecord
->HelpContext
= desc
->helpcontext
;
9375 if(desc
->HelpString
)
9376 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9378 funcrecord
->oHelpString
= -1;
9380 funcrecord
->oEntry
= -1;
9381 else if(IS_INTRESOURCE(desc
->Entry
))
9382 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9384 funcrecord
->oEntry
= desc
->Entry
->offset
;
9385 funcrecord
->res9
= -1;
9386 funcrecord
->resA
= -1;
9387 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9388 }else if(desc
->Entry
){
9389 size
+= 3 * sizeof(INT
);
9390 funcrecord
->HelpContext
= desc
->helpcontext
;
9391 if(desc
->HelpString
)
9392 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9394 funcrecord
->oHelpString
= -1;
9396 funcrecord
->oEntry
= -1;
9397 else if(IS_INTRESOURCE(desc
->Entry
))
9398 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9400 funcrecord
->oEntry
= desc
->Entry
->offset
;
9401 }else if(desc
->HelpString
){
9402 size
+= 2 * sizeof(INT
);
9403 funcrecord
->HelpContext
= desc
->helpcontext
;
9404 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9405 }else if(desc
->helpcontext
){
9406 size
+= sizeof(INT
);
9407 funcrecord
->HelpContext
= desc
->helpcontext
;
9410 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9411 size
+= paramdefault_size
;
9413 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9414 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9416 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9417 if(desc
->pParamDesc
[j
].Name
)
9418 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9421 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9423 if(paramdefault_size
){
9424 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9425 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9426 else if(paramdefault_size
)
9431 size
+= sizeof(MSFT_ParameterInfo
);
9434 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9440 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9443 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9444 for(i
= 0; i
< info
->cVars
; ++i
){
9445 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9446 DWORD size
= 5 * sizeof(INT
);
9448 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9449 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9450 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9451 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9453 if(desc
->vardesc
.varkind
== VAR_CONST
){
9454 varrecord
->vardescsize
+= sizeof(VARIANT
);
9455 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9457 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9460 if(desc
->HelpStringContext
!= 0){
9461 size
+= 5 * sizeof(INT
);
9462 varrecord
->HelpContext
= desc
->HelpContext
;
9463 if(desc
->HelpString
)
9464 varrecord
->HelpString
= desc
->HelpString
->offset
;
9466 varrecord
->HelpString
= -1;
9467 varrecord
->res9
= -1;
9468 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9469 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9470 }else if(!list_empty(&desc
->custdata_list
)){
9471 size
+= 4 * sizeof(INT
);
9472 varrecord
->HelpContext
= desc
->HelpContext
;
9473 if(desc
->HelpString
)
9474 varrecord
->HelpString
= desc
->HelpString
->offset
;
9476 varrecord
->HelpString
= -1;
9477 varrecord
->res9
= -1;
9478 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9479 }else if(desc
->HelpString
){
9480 size
+= 2 * sizeof(INT
);
9481 varrecord
->HelpContext
= desc
->HelpContext
;
9482 if(desc
->HelpString
)
9483 varrecord
->HelpString
= desc
->HelpString
->offset
;
9485 varrecord
->HelpString
= -1;
9486 }else if(desc
->HelpContext
!= 0){
9487 size
+= sizeof(INT
);
9488 varrecord
->HelpContext
= desc
->HelpContext
;
9491 varrecord
->Info
= size
| (i
<< 16);
9497 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9500 memid
= (MEMBERID
*)varrecord
;
9501 for(i
= 0; i
< info
->cFuncs
; ++i
){
9502 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9503 *memid
= desc
->funcdesc
.memid
;
9506 for(i
= 0; i
< info
->cVars
; ++i
){
9507 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9508 *memid
= desc
->vardesc
.memid
;
9512 name
= (UINT
*)memid
;
9513 for(i
= 0; i
< info
->cFuncs
; ++i
){
9514 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9516 *name
= desc
->Name
->offset
;
9521 for(i
= 0; i
< info
->cVars
; ++i
){
9522 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9524 *name
= desc
->Name
->offset
;
9533 typedef struct tagWMSFT_RefChunk
{
9540 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9542 DWORD offs
= file
->ref_seg
.len
, i
;
9543 WMSFT_RefChunk
*chunk
;
9545 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9546 if(!file
->ref_seg
.data
)
9547 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9549 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9551 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9553 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9554 chunk
->href
= info
->impltypes
[i
].hRef
;
9555 chunk
->res04
= info
->impltypes
[i
].implflags
;
9557 if(i
< info
->cImplTypes
- 1)
9558 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9567 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9571 size
= sizeof(MSFT_TypeInfoBase
);
9574 MSFT_TypeInfoBase
*base
= (void*)data
;
9575 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9576 base
->typekind
= TKIND_DISPATCH
;
9578 base
->typekind
= info
->typekind
;
9579 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9580 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9581 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9586 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9592 base
->posguid
= info
->guid
->offset
;
9595 base
->flags
= info
->wTypeFlags
;
9597 base
->NameOffset
= info
->Name
->offset
;
9599 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9600 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9602 base
->NameOffset
= -1;
9604 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9606 base
->docstringoffs
= info
->DocString
->offset
;
9608 base
->docstringoffs
= -1;
9609 base
->helpstringcontext
= info
->dwHelpStringContext
;
9610 base
->helpcontext
= info
->dwHelpContext
;
9611 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9612 base
->cImplTypes
= info
->cImplTypes
;
9613 base
->cbSizeVft
= info
->cbSizeVft
;
9614 base
->size
= info
->cbSizeInstance
;
9615 if(info
->typekind
== TKIND_COCLASS
){
9616 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9617 }else if(info
->typekind
== TKIND_ALIAS
){
9618 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9619 }else if(info
->typekind
== TKIND_MODULE
){
9621 base
->datatype1
= info
->DllName
->offset
;
9623 base
->datatype1
= -1;
9625 if(info
->cImplTypes
> 0)
9626 base
->datatype1
= info
->impltypes
[0].hRef
;
9628 base
->datatype1
= -1;
9630 base
->datatype2
= index
; /* FIXME: i think there's more here */
9638 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9642 file
->typeinfo_seg
.len
= 0;
9643 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9644 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9645 *junk
= file
->typeinfo_seg
.len
;
9647 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9650 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9651 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9653 file
->aux_seg
.len
= 0;
9654 file
->aux_seg
.data
= NULL
;
9656 file
->typeinfo_seg
.len
= 0;
9657 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9658 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9659 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9660 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9664 typedef struct tagWMSFT_ImpFile
{
9670 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9673 WMSFT_ImpFile
*impfile
;
9675 DWORD last_offs
= 0;
9677 file
->impfile_seg
.len
= 0;
9678 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9682 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9686 path
= implib
->name
;
9687 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9689 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9692 size
+= sizeof(INT16
);
9694 size
= (size
+ 4) & ~0x3;
9698 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9701 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9703 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9704 int strlen
= 0, size
;
9706 impfile
= (WMSFT_ImpFile
*)data
;
9707 impfile
->guid_offs
= implib
->guid
->offset
;
9708 impfile
->lcid
= implib
->lcid
;
9709 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9711 data
+= sizeof(WMSFT_ImpFile
);
9714 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9718 path
= implib
->name
;
9719 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9720 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9722 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9725 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9727 size
= strlen
+ sizeof(INT16
);
9729 size
= (size
+ 4) & ~0x3;
9732 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9735 implib
->offset
= last_offs
;
9736 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9740 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9743 TLBRefType
*ref_type
;
9746 WMSFT_compile_impfile(This
, file
);
9748 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9749 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9751 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9752 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9753 if(ref_type
->index
== TLB_REF_USE_GUID
){
9754 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9755 info
->oGuid
= ref_type
->guid
->offset
;
9757 info
->oGuid
= ref_type
->index
;
9758 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9764 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9766 file
->guidhash_seg
.len
= 0x80;
9767 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9768 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9771 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9773 file
->namehash_seg
.len
= 0x200;
9774 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9775 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9778 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9780 if(contents
&& contents
->len
){
9781 segdir
->offset
= *running_offset
;
9782 segdir
->length
= contents
->len
;
9783 *running_offset
+= segdir
->length
;
9785 segdir
->offset
= -1;
9789 /* TODO: do these ever change? */
9791 segdir
->res0c
= 0xf;
9794 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9798 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9801 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9805 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9807 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9808 base
->memoffset
+= file_len
;
9815 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9817 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9818 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9819 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9820 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9821 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9822 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9823 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9824 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9825 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9826 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9827 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9828 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9829 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9830 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9833 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9835 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9837 DWORD written
, junk_size
, junk_offs
, running_offset
;
9844 TRACE("%p\n", This
);
9846 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9847 if(This
->typeinfos
[i
]->needs_layout
)
9848 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9850 memset(&file
, 0, sizeof(file
));
9852 file
.header
.magic1
= 0x5446534D;
9853 file
.header
.magic2
= 0x00010002;
9854 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9855 file
.header
.lcid2
= This
->set_lcid
;
9856 file
.header
.varflags
= 0x40 | This
->syskind
;
9858 file
.header
.varflags
|= 0x10;
9859 if (This
->HelpStringDll
)
9860 file
.header
.varflags
|= HELPDLLFLAG
;
9861 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9862 file
.header
.flags
= This
->libflags
;
9863 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9864 file
.header
.helpcontext
= This
->dwHelpContext
;
9865 file
.header
.res44
= 0x20;
9866 file
.header
.res48
= 0x80;
9867 file
.header
.dispatchpos
= This
->dispatch_href
;
9869 WMSFT_compile_namehash(This
, &file
);
9870 /* do name and string compilation to get offsets for other compilations */
9871 hres
= WMSFT_compile_names(This
, &file
);
9873 WMSFT_free_file(&file
);
9877 hres
= WMSFT_compile_strings(This
, &file
);
9879 WMSFT_free_file(&file
);
9883 WMSFT_compile_guidhash(This
, &file
);
9884 hres
= WMSFT_compile_guids(This
, &file
);
9886 WMSFT_free_file(&file
);
9891 file
.header
.helpfile
= This
->HelpFile
->offset
;
9893 file
.header
.helpfile
= -1;
9896 file
.header
.helpstring
= This
->DocString
->offset
;
9898 file
.header
.helpstring
= -1;
9900 /* do some more segment compilation */
9901 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9902 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9905 file
.header
.NameOffset
= This
->Name
->offset
;
9907 file
.header
.NameOffset
= -1;
9909 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9912 file
.header
.posguid
= This
->guid
->offset
;
9914 file
.header
.posguid
= -1;
9916 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9917 if(file
.header
.varflags
& HELPDLLFLAG
)
9918 junk_size
+= sizeof(DWORD
);
9920 junk
= heap_alloc_zero(junk_size
);
9921 if(file
.header
.varflags
& HELPDLLFLAG
){
9922 *junk
= This
->HelpStringDll
->offset
;
9931 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9932 WMSFT_compile_impinfo(This
, &file
);
9936 TRACE("header at: 0x%x\n", running_offset
);
9937 running_offset
+= sizeof(file
.header
);
9939 TRACE("junk at: 0x%x\n", running_offset
);
9940 running_offset
+= junk_size
;
9942 TRACE("segdir at: 0x%x\n", running_offset
);
9943 running_offset
+= sizeof(file
.segdir
);
9945 TRACE("typeinfo at: 0x%x\n", running_offset
);
9946 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9948 TRACE("guidhashtab at: 0x%x\n", running_offset
);
9949 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
9951 TRACE("guidtab at: 0x%x\n", running_offset
);
9952 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9954 TRACE("reftab at: 0x%x\n", running_offset
);
9955 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9957 TRACE("impinfo at: 0x%x\n", running_offset
);
9958 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9960 TRACE("impfiles at: 0x%x\n", running_offset
);
9961 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9963 TRACE("namehashtab at: 0x%x\n", running_offset
);
9964 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
9966 TRACE("nametab at: 0x%x\n", running_offset
);
9967 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9969 TRACE("stringtab at: 0x%x\n", running_offset
);
9970 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9972 TRACE("typdesc at: 0x%x\n", running_offset
);
9973 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
9975 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
9976 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
9978 TRACE("custdata at: 0x%x\n", running_offset
);
9979 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
9981 TRACE("cdguids at: 0x%x\n", running_offset
);
9982 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
9984 TRACE("res0e at: 0x%x\n", running_offset
);
9985 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
9987 TRACE("res0f at: 0x%x\n", running_offset
);
9988 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
9990 TRACE("aux_seg at: 0x%x\n", running_offset
);
9992 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
9994 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
9995 FILE_ATTRIBUTE_NORMAL
, 0);
9996 if (outfile
== INVALID_HANDLE_VALUE
){
9997 WMSFT_free_file(&file
);
9999 return TYPE_E_IOERROR
;
10002 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10004 WMSFT_free_file(&file
);
10005 CloseHandle(outfile
);
10007 return TYPE_E_IOERROR
;
10010 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10013 WMSFT_free_file(&file
);
10014 CloseHandle(outfile
);
10015 return TYPE_E_IOERROR
;
10018 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10020 WMSFT_free_file(&file
);
10021 CloseHandle(outfile
);
10022 return TYPE_E_IOERROR
;
10025 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10026 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10027 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10028 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10029 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10030 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10031 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10032 WMSFT_write_segment(outfile
, &file
.name_seg
);
10033 WMSFT_write_segment(outfile
, &file
.string_seg
);
10034 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10035 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10036 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10037 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10038 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10040 WMSFT_free_file(&file
);
10042 CloseHandle(outfile
);
10047 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10050 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10051 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10055 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10056 REFGUID guid
, VARIANT
*varVal
)
10058 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10059 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10063 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10064 ULONG helpStringContext
)
10066 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10067 FIXME("%p %u - stub\n", This
, helpStringContext
);
10071 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10074 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10075 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10078 return E_INVALIDARG
;
10080 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10085 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10086 ICreateTypeLib2_fnQueryInterface
,
10087 ICreateTypeLib2_fnAddRef
,
10088 ICreateTypeLib2_fnRelease
,
10089 ICreateTypeLib2_fnCreateTypeInfo
,
10090 ICreateTypeLib2_fnSetName
,
10091 ICreateTypeLib2_fnSetVersion
,
10092 ICreateTypeLib2_fnSetGuid
,
10093 ICreateTypeLib2_fnSetDocString
,
10094 ICreateTypeLib2_fnSetHelpFileName
,
10095 ICreateTypeLib2_fnSetHelpContext
,
10096 ICreateTypeLib2_fnSetLcid
,
10097 ICreateTypeLib2_fnSetLibFlags
,
10098 ICreateTypeLib2_fnSaveAllChanges
,
10099 ICreateTypeLib2_fnDeleteTypeInfo
,
10100 ICreateTypeLib2_fnSetCustData
,
10101 ICreateTypeLib2_fnSetHelpStringContext
,
10102 ICreateTypeLib2_fnSetHelpStringDll
10105 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10106 REFIID riid
, void **object
)
10108 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10110 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10113 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10115 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10117 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10120 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10122 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10124 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10127 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10130 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10132 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10134 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10139 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10142 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10146 TRACE("%p %x\n", This
, typeFlags
);
10148 if (typeFlags
& TYPEFLAG_FDUAL
) {
10149 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10151 ITypeInfo
*dispatch
;
10155 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10159 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10160 ITypeLib_Release(stdole
);
10164 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10165 ITypeInfo_Release(dispatch
);
10170 old_flags
= This
->wTypeFlags
;
10171 This
->wTypeFlags
= typeFlags
;
10173 hres
= ICreateTypeInfo2_LayOut(iface
);
10174 if (FAILED(hres
)) {
10175 This
->wTypeFlags
= old_flags
;
10182 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10185 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10187 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10190 return E_INVALIDARG
;
10192 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10197 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10200 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10202 TRACE("%p %d\n", This
, helpContext
);
10204 This
->dwHelpContext
= helpContext
;
10209 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10210 WORD majorVerNum
, WORD minorVerNum
)
10212 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10214 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10216 This
->wMajorVerNum
= majorVerNum
;
10217 This
->wMinorVerNum
= minorVerNum
;
10222 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10223 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10225 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10227 ITypeLib
*container
;
10228 TLBRefType
*ref_type
;
10230 TYPEATTR
*typeattr
;
10234 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10236 if (!typeInfo
|| !refType
)
10237 return E_INVALIDARG
;
10239 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10243 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10244 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10246 ITypeLib_Release(container
);
10248 *refType
= target
->hreftype
;
10253 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10254 if (FAILED(hres
)) {
10255 ITypeLib_Release(container
);
10259 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10260 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10261 implib
->lcid
== libattr
->lcid
&&
10262 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10263 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10267 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10268 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10270 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10271 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10272 implib
->name
= SysAllocString(our_container
->path
);
10274 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10275 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10277 implib
->name
= NULL
;
10278 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10282 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10283 implib
->lcid
= libattr
->lcid
;
10284 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10285 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10287 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10290 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10291 ITypeLib_Release(container
);
10293 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10298 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10299 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10300 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10301 ref_type
->tkind
== typeattr
->typekind
)
10306 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10307 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10309 ref_type
->tkind
= typeattr
->typekind
;
10310 ref_type
->pImpTLInfo
= implib
;
10311 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10313 ref_type
->index
= TLB_REF_USE_GUID
;
10315 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10317 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10320 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10322 *refType
= ref_type
->reference
| 0x1;
10324 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10325 This
->pTypeLib
->dispatch_href
= *refType
;
10330 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10331 UINT index
, FUNCDESC
*funcDesc
)
10333 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10334 TLBFuncDesc tmp_func_desc
, *func_desc
;
10339 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10341 if (!funcDesc
|| funcDesc
->oVft
& 3)
10342 return E_INVALIDARG
;
10344 switch (This
->typekind
) {
10346 if (funcDesc
->funckind
!= FUNC_STATIC
)
10347 return TYPE_E_BADMODULEKIND
;
10349 case TKIND_DISPATCH
:
10350 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10351 return TYPE_E_BADMODULEKIND
;
10354 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10355 return TYPE_E_BADMODULEKIND
;
10358 if (index
> This
->cFuncs
)
10359 return TYPE_E_ELEMENTNOTFOUND
;
10361 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10362 !funcDesc
->cParams
)
10363 return TYPE_E_INCONSISTENTPROPFUNCS
;
10366 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10367 funcDesc
->oVft
% 8 != 0)
10368 return E_INVALIDARG
;
10371 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10372 TLBFuncDesc_Constructor(&tmp_func_desc
);
10374 tmp_func_desc
.funcdesc
= *funcDesc
;
10376 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10377 tmp_func_desc
.funcdesc
.oVft
|= 1;
10379 if (funcDesc
->cScodes
) {
10380 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10381 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10383 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10385 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10386 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10387 buf_size
+= sizeof(ELEMDESC
);
10388 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10390 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10391 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10393 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10394 if (FAILED(hres
)) {
10395 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10396 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10400 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10401 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10402 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10403 if (FAILED(hres
)) {
10404 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10405 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10408 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10409 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10410 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10411 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10412 if (FAILED(hres
)) {
10413 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10414 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10420 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10422 if (This
->funcdescs
) {
10423 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10424 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10426 if (index
< This
->cFuncs
) {
10427 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10428 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10429 func_desc
= This
->funcdescs
+ index
;
10431 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10433 /* move custdata lists to the new memory location */
10434 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10436 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10437 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10438 list_init(&fd
->custdata_list
);
10440 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10441 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10446 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10448 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10449 list_init(&func_desc
->custdata_list
);
10453 This
->needs_layout
= TRUE
;
10458 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10459 UINT index
, HREFTYPE refType
)
10461 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10462 TLBImplType
*impl_type
;
10465 TRACE("%p %u %d\n", This
, index
, refType
);
10467 switch(This
->typekind
){
10468 case TKIND_COCLASS
: {
10470 FIXME("Unhandled index: -1\n");
10474 if(index
!= This
->cImplTypes
)
10475 return TYPE_E_ELEMENTNOTFOUND
;
10479 case TKIND_INTERFACE
:
10480 case TKIND_DISPATCH
:
10481 if (index
!= 0 || This
->cImplTypes
)
10482 return TYPE_E_ELEMENTNOTFOUND
;
10485 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10489 if (This
->impltypes
){
10492 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10493 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10495 if (index
< This
->cImplTypes
) {
10496 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10497 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10498 impl_type
= This
->impltypes
+ index
;
10500 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10502 /* move custdata lists to the new memory location */
10503 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10505 TLBImplType
*it
= &This
->impltypes
[i
];
10506 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10507 list_init(&it
->custdata_list
);
10509 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10510 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10515 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10517 memset(impl_type
, 0, sizeof(TLBImplType
));
10518 TLBImplType_Constructor(impl_type
);
10519 impl_type
->hRef
= refType
;
10521 ++This
->cImplTypes
;
10523 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10524 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10526 hres
= ICreateTypeInfo2_LayOut(iface
);
10533 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10534 UINT index
, INT implTypeFlags
)
10536 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10537 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10539 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10541 if (This
->typekind
!= TKIND_COCLASS
)
10542 return TYPE_E_BADMODULEKIND
;
10544 if (index
>= This
->cImplTypes
)
10545 return TYPE_E_ELEMENTNOTFOUND
;
10547 impl_type
->implflags
= implTypeFlags
;
10552 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10555 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10557 TRACE("%p %d\n", This
, alignment
);
10559 This
->cbAlignment
= alignment
;
10564 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10567 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10569 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10572 return E_INVALIDARG
;
10574 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10576 This
->lpstrSchema
= This
->Schema
->str
;
10581 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10582 UINT index
, VARDESC
*varDesc
)
10584 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10585 TLBVarDesc
*var_desc
;
10587 TRACE("%p %u %p\n", This
, index
, varDesc
);
10589 if (This
->vardescs
){
10592 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10593 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10595 if (index
< This
->cVars
) {
10596 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10597 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10598 var_desc
= This
->vardescs
+ index
;
10600 var_desc
= This
->vardescs
+ This
->cVars
;
10602 /* move custdata lists to the new memory location */
10603 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10605 TLBVarDesc
*var
= &This
->vardescs
[i
];
10606 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10607 list_init(&var
->custdata_list
);
10609 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10610 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10615 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10617 TLBVarDesc_Constructor(var_desc
);
10618 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10619 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10623 This
->needs_layout
= TRUE
;
10628 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10629 UINT index
, LPOLESTR
*names
, UINT numNames
)
10631 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10632 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10635 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10638 return E_INVALIDARG
;
10640 if (index
>= This
->cFuncs
|| numNames
== 0)
10641 return TYPE_E_ELEMENTNOTFOUND
;
10643 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10644 if(numNames
> func_desc
->funcdesc
.cParams
)
10645 return TYPE_E_ELEMENTNOTFOUND
;
10647 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10648 return TYPE_E_ELEMENTNOTFOUND
;
10650 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10651 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10652 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10653 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10654 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10655 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10657 return TYPE_E_AMBIGUOUSNAME
;
10661 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10663 for (i
= 1; i
< numNames
; ++i
) {
10664 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10665 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10671 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10672 UINT index
, LPOLESTR name
)
10674 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10676 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10679 return E_INVALIDARG
;
10681 if(index
>= This
->cVars
)
10682 return TYPE_E_ELEMENTNOTFOUND
;
10684 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10688 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10689 TYPEDESC
*tdescAlias
)
10691 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10694 TRACE("%p %p\n", This
, tdescAlias
);
10697 return E_INVALIDARG
;
10699 if(This
->typekind
!= TKIND_ALIAS
)
10700 return TYPE_E_BADMODULEKIND
;
10702 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10706 heap_free(This
->tdescAlias
);
10707 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10708 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10713 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10714 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10716 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10717 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10721 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10722 UINT index
, LPOLESTR docString
)
10724 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10725 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
10729 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10730 UINT index
, LPOLESTR docString
)
10732 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10733 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10735 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10738 return E_INVALIDARG
;
10740 if(index
>= This
->cVars
)
10741 return TYPE_E_ELEMENTNOTFOUND
;
10743 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10748 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10749 UINT index
, DWORD helpContext
)
10751 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10752 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10754 TRACE("%p %u %d\n", This
, index
, helpContext
);
10756 if(index
>= This
->cFuncs
)
10757 return TYPE_E_ELEMENTNOTFOUND
;
10759 func_desc
->helpcontext
= helpContext
;
10764 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10765 UINT index
, DWORD helpContext
)
10767 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10768 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10770 TRACE("%p %u %d\n", This
, index
, helpContext
);
10772 if(index
>= This
->cVars
)
10773 return TYPE_E_ELEMENTNOTFOUND
;
10775 var_desc
->HelpContext
= helpContext
;
10780 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10781 UINT index
, BSTR bstrMops
)
10783 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10784 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10788 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10791 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10793 TRACE("%p %p\n", This
, idlDesc
);
10796 return E_INVALIDARG
;
10798 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10799 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10804 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10806 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10808 TLBFuncDesc
*func_desc
;
10809 UINT user_vft
= 0, i
, depth
= 0;
10810 HRESULT hres
= S_OK
;
10812 TRACE("%p\n", This
);
10814 This
->needs_layout
= FALSE
;
10816 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10820 if (This
->typekind
== TKIND_INTERFACE
) {
10825 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10827 if (SUCCEEDED(hres
)) {
10828 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10830 if (SUCCEEDED(hres
)) {
10831 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10832 if (FAILED(hres
)) {
10833 ITypeInfo_Release(inh
);
10834 ITypeInfo_Release(tinfo
);
10837 This
->cbSizeVft
= attr
->cbSizeVft
;
10838 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10842 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10843 if(SUCCEEDED(hres
)){
10845 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10846 if(SUCCEEDED(hres
)){
10847 ITypeInfo_Release(inh
);
10851 }while(SUCCEEDED(hres
));
10854 ITypeInfo_Release(inh
);
10855 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10856 This
->cbSizeVft
= 0;
10859 ITypeInfo_Release(tinfo
);
10862 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10863 This
->cbSizeVft
= 0;
10866 ITypeInfo_Release(tinfo
);
10869 } else if (This
->typekind
== TKIND_DISPATCH
)
10870 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10872 This
->cbSizeVft
= 0;
10874 func_desc
= This
->funcdescs
;
10876 while (i
< This
->cFuncs
) {
10877 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10878 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10880 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10881 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10883 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10885 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10888 BOOL reset
= FALSE
;
10890 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10892 iter
= This
->funcdescs
;
10893 while (j
< This
->cFuncs
) {
10894 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10896 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10899 ++func_desc
->funcdesc
.memid
;
10900 iter
= This
->funcdescs
;
10913 if (user_vft
> This
->cbSizeVft
)
10914 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10916 for(i
= 0; i
< This
->cVars
; ++i
){
10917 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10918 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
10920 BOOL reset
= FALSE
;
10923 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
10925 iter
= This
->vardescs
;
10926 while (j
< This
->cVars
) {
10927 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
10929 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
10932 ++var_desc
->vardesc
.memid
;
10933 iter
= This
->vardescs
;
10943 ITypeInfo_Release(tinfo
);
10947 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10950 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10951 FIXME("%p %u - stub\n", This
, index
);
10955 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
10956 MEMBERID memid
, INVOKEKIND invKind
)
10958 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10959 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
10963 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
10966 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10967 FIXME("%p %u - stub\n", This
, index
);
10971 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
10974 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10975 FIXME("%p %x - stub\n", This
, memid
);
10979 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
10982 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10983 FIXME("%p %u - stub\n", This
, index
);
10987 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
10988 REFGUID guid
, VARIANT
*varVal
)
10992 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10994 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10996 if (!guid
|| !varVal
)
10997 return E_INVALIDARG
;
10999 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11001 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11004 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11005 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11007 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11008 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11012 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11013 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11015 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11016 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11020 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11021 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11023 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11024 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11028 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11029 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11031 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11032 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11036 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11037 ULONG helpStringContext
)
11039 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11041 TRACE("%p %u\n", This
, helpStringContext
);
11043 This
->dwHelpStringContext
= helpStringContext
;
11048 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11049 UINT index
, ULONG helpStringContext
)
11051 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11052 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11056 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11057 UINT index
, ULONG helpStringContext
)
11059 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11060 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11064 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11066 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11067 FIXME("%p - stub\n", This
);
11071 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11074 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11076 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11079 return E_INVALIDARG
;
11081 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11086 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11087 ICreateTypeInfo2_fnQueryInterface
,
11088 ICreateTypeInfo2_fnAddRef
,
11089 ICreateTypeInfo2_fnRelease
,
11090 ICreateTypeInfo2_fnSetGuid
,
11091 ICreateTypeInfo2_fnSetTypeFlags
,
11092 ICreateTypeInfo2_fnSetDocString
,
11093 ICreateTypeInfo2_fnSetHelpContext
,
11094 ICreateTypeInfo2_fnSetVersion
,
11095 ICreateTypeInfo2_fnAddRefTypeInfo
,
11096 ICreateTypeInfo2_fnAddFuncDesc
,
11097 ICreateTypeInfo2_fnAddImplType
,
11098 ICreateTypeInfo2_fnSetImplTypeFlags
,
11099 ICreateTypeInfo2_fnSetAlignment
,
11100 ICreateTypeInfo2_fnSetSchema
,
11101 ICreateTypeInfo2_fnAddVarDesc
,
11102 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11103 ICreateTypeInfo2_fnSetVarName
,
11104 ICreateTypeInfo2_fnSetTypeDescAlias
,
11105 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11106 ICreateTypeInfo2_fnSetFuncDocString
,
11107 ICreateTypeInfo2_fnSetVarDocString
,
11108 ICreateTypeInfo2_fnSetFuncHelpContext
,
11109 ICreateTypeInfo2_fnSetVarHelpContext
,
11110 ICreateTypeInfo2_fnSetMops
,
11111 ICreateTypeInfo2_fnSetTypeIdldesc
,
11112 ICreateTypeInfo2_fnLayOut
,
11113 ICreateTypeInfo2_fnDeleteFuncDesc
,
11114 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11115 ICreateTypeInfo2_fnDeleteVarDesc
,
11116 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11117 ICreateTypeInfo2_fnDeleteImplType
,
11118 ICreateTypeInfo2_fnSetCustData
,
11119 ICreateTypeInfo2_fnSetFuncCustData
,
11120 ICreateTypeInfo2_fnSetParamCustData
,
11121 ICreateTypeInfo2_fnSetVarCustData
,
11122 ICreateTypeInfo2_fnSetImplTypeCustData
,
11123 ICreateTypeInfo2_fnSetHelpStringContext
,
11124 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11125 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11126 ICreateTypeInfo2_fnInvalidate
,
11127 ICreateTypeInfo2_fnSetName
11130 /******************************************************************************
11131 * ClearCustData (OLEAUT32.171)
11133 * Clear a custom data type's data.
11136 * lpCust [I] The custom data type instance
11141 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11143 if (lpCust
&& lpCust
->cCustData
)
11145 if (lpCust
->prgCustData
)
11149 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11150 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11152 /* FIXME - Should be using a per-thread IMalloc */
11153 heap_free(lpCust
->prgCustData
);
11154 lpCust
->prgCustData
= NULL
;
11156 lpCust
->cCustData
= 0;