4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
46 * -. lousy fatal error handling
51 #include "wine/port.h"
60 #define NONAMELESSUNION
61 #define NONAMELESSSTRUCT
72 #include "wine/unicode.h"
75 #include "wine/debug.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
94 WORD type_id
; /* Type identifier */
95 WORD count
; /* Number of resources of this type */
96 DWORD resloader
; /* SetResourceHandler() */
102 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
103 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
104 static void TLB_FreeVarDesc(VARDESC
*);
106 /****************************************************************************
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD
FromLEWord(WORD p_iVal
)
115 return (((p_iVal
& 0x00FF) << 8) |
116 ((p_iVal
& 0xFF00) >> 8));
120 static DWORD
FromLEDWord(DWORD p_iVal
)
122 return (((p_iVal
& 0x000000FF) << 24) |
123 ((p_iVal
& 0x0000FF00) << 8) |
124 ((p_iVal
& 0x00FF0000) >> 8) |
125 ((p_iVal
& 0xFF000000) >> 24));
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val
, int p_iSize
)
145 p_iSize
/= sizeof(WORD
);
148 *Val
= FromLEWord(*Val
);
155 static void FromLEDWords(void *p_Val
, int p_iSize
)
159 p_iSize
/= sizeof(DWORD
);
162 *Val
= FromLEDWord(*Val
);
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
177 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
181 INT best_maj
= -1, best_min
= -1;
184 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
185 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
190 len
= sizeof(key_name
);
192 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
196 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
200 if (*wMaj
== 0xffff && *wMin
== 0xffff)
202 if (v_maj
> best_maj
) best_maj
= v_maj
;
203 if (v_min
> best_min
) best_min
= v_min
;
205 else if (*wMaj
== v_maj
)
212 break; /* exact match */
214 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
217 len
= sizeof(key_name
);
221 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
223 if (*wMaj
== 0xffff && *wMin
== 0xffff)
225 if (best_maj
>= 0 && best_min
>= 0)
233 if (*wMaj
== best_maj
&& best_min
>= 0)
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
245 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
249 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
250 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
258 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
261 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
269 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
270 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
274 sprintfW( buffer
, LcidFormatW
, lcid
);
277 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
278 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
279 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
281 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
287 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
290 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
291 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
292 SYSKIND syskind
, LCID lcid
, LPBSTR path
)
294 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
298 WCHAR Path
[MAX_PATH
];
301 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
303 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
304 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
306 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
307 if (res
== ERROR_FILE_NOT_FOUND
)
309 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
310 return TYPE_E_LIBNOTREGISTERED
;
312 else if (res
!= ERROR_SUCCESS
)
314 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
315 return TYPE_E_REGISTRYACCESS
;
320 LONG dwPathLen
= sizeof(Path
);
322 get_lcid_subkey( myLCID
, syskind
, buffer
);
324 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
328 else if (myLCID
== lcid
)
330 /* try with sub-langid */
331 myLCID
= SUBLANGID(lcid
);
333 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
335 /* try with system langid */
345 *path
= SysAllocString( Path
);
350 TRACE_(typelib
)("-- 0x%08x\n", hr
);
354 /****************************************************************************
355 * QueryPathOfRegTypeLib [OLEAUT32.164]
357 * Gets the path to a registered type library.
360 * guid [I] referenced guid
361 * wMaj [I] major version
362 * wMin [I] minor version
364 * path [O] path of typelib
368 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
369 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
372 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
375 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
);
379 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
);
382 /******************************************************************************
383 * CreateTypeLib [OLEAUT32.160] creates a typelib
389 HRESULT WINAPI
CreateTypeLib(
390 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
392 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
396 /******************************************************************************
397 * LoadTypeLib [OLEAUT32.161]
399 * Loads a type library
402 * szFile [I] Name of file to load from.
403 * pptLib [O] Pointer that receives ITypeLib object on success.
410 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
412 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
414 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
415 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
418 /******************************************************************************
419 * LoadTypeLibEx [OLEAUT32.183]
421 * Loads and optionally registers a type library
427 HRESULT WINAPI
LoadTypeLibEx(
428 LPCOLESTR szFile
, /* [in] Name of file to load from */
429 REGKIND regkind
, /* [in] Specify kind of registration */
430 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
432 WCHAR szPath
[MAX_PATH
+1];
435 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
439 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
444 case REGKIND_DEFAULT
:
445 /* don't register typelibs supplied with full path. Experimentation confirms the following */
446 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
447 (szFile
[0] && (szFile
[1] == ':'))) break;
448 /* else fall-through */
450 case REGKIND_REGISTER
:
451 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
453 ITypeLib_Release(*pptLib
);
461 TRACE(" returns %08x\n",res
);
465 /******************************************************************************
466 * LoadRegTypeLib [OLEAUT32.162]
468 * Loads a registered type library.
471 * rguid [I] GUID of the registered type library.
472 * wVerMajor [I] major version.
473 * wVerMinor [I] minor version.
474 * lcid [I] locale ID.
475 * ppTLib [O] pointer that receives an ITypeLib object on success.
479 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
482 HRESULT WINAPI
LoadRegTypeLib(
494 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
498 res
= LoadTypeLib(bstr
, ppTLib
);
502 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
508 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
509 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
510 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
511 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
512 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
513 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
515 /******************************************************************************
516 * RegisterTypeLib [OLEAUT32.163]
517 * Adds information about a type library to the System Registry
519 * Docs: ITypeLib FAR * ptlib
520 * Docs: OLECHAR FAR* szFullPath
521 * Docs: OLECHAR FAR* szHelpDir
527 HRESULT WINAPI
RegisterTypeLib(
528 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
529 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
530 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
533 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
534 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
535 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
545 if (ptlib
== NULL
|| szFullPath
== NULL
)
548 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
552 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
555 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
558 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
559 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
563 /* Set the human-readable name of the typelib */
564 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
568 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
569 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
575 /* Make up the name of the typelib path subkey */
576 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
578 /* Create the typelib path subkey */
579 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
580 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
582 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
583 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
591 /* Create the flags subkey */
592 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
593 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
595 /* FIXME: is %u correct? */
596 static const WCHAR formatW
[] = {'%','u',0};
598 sprintfW(buf
, formatW
, attr
->wLibFlags
);
599 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
600 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
608 /* create the helpdir subkey */
609 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
610 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
612 BOOL freeHelpDir
= FALSE
;
615 /* if we created a new key, and helpDir was null, set the helpdir
616 to the directory which contains the typelib. However,
617 if we just opened an existing key, we leave the helpdir alone */
618 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
619 szHelpDir
= SysAllocString(szFullPath
);
620 pIndexStr
= strrchrW(szHelpDir
, '\\');
627 /* if we have an szHelpDir, set it! */
628 if (szHelpDir
!= NULL
) {
629 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
630 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
636 if (freeHelpDir
) SysFreeString(szHelpDir
);
648 /* register OLE Automation-compatible interfaces for this typelib */
649 types
= ITypeLib_GetTypeInfoCount(ptlib
);
650 for (tidx
=0; tidx
<types
; tidx
++) {
651 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
652 LPOLESTR name
= NULL
;
653 ITypeInfo
*tinfo
= NULL
;
655 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
658 case TKIND_INTERFACE
:
659 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
660 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
664 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
665 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
669 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
674 TYPEATTR
*tattr
= NULL
;
675 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
678 TRACE_(typelib
)("guid=%s, flags=%04x (",
679 debugstr_guid(&tattr
->guid
),
682 if (TRACE_ON(typelib
)) {
683 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
703 /* Register all dispinterfaces (which includes dual interfaces) and
704 oleautomation interfaces */
705 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
706 kind
== TKIND_DISPATCH
)
708 /* register interface<->typelib coupling */
709 get_interface_key( &tattr
->guid
, keyName
);
710 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
711 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
714 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
715 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
717 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
718 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
719 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
720 (const BYTE
*)PSOA
, sizeof PSOA
);
724 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
725 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
726 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
727 (const BYTE
*)PSOA
, sizeof PSOA
);
731 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
732 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
735 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
736 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
738 StringFromGUID2(&attr
->guid
, buffer
, 40);
739 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
740 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
741 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
742 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
743 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
751 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
754 ITypeInfo_Release(tinfo
);
761 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
767 /******************************************************************************
768 * UnRegisterTypeLib [OLEAUT32.186]
769 * Removes information about a type library from the System Registry
776 HRESULT WINAPI
UnRegisterTypeLib(
777 REFGUID libid
, /* [in] Guid of the library */
778 WORD wVerMajor
, /* [in] major version */
779 WORD wVerMinor
, /* [in] minor version */
780 LCID lcid
, /* [in] locale id */
783 BSTR tlibPath
= NULL
;
786 WCHAR subKeyName
[50];
789 BOOL deleteOtherStuff
;
792 TYPEATTR
* typeAttr
= NULL
;
794 ITypeInfo
* typeInfo
= NULL
;
795 ITypeLib
* typeLib
= NULL
;
798 TRACE("(IID: %s)\n",debugstr_guid(libid
));
800 /* Create the path to the key */
801 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
803 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
805 TRACE("Unsupported syskind %i\n", syskind
);
806 result
= E_INVALIDARG
;
810 /* get the path to the typelib on disk */
811 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
) != S_OK
) {
812 result
= E_INVALIDARG
;
816 /* Try and open the key to the type library. */
817 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
818 result
= E_INVALIDARG
;
822 /* Try and load the type library */
823 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
824 result
= TYPE_E_INVALIDSTATE
;
828 /* remove any types registered with this typelib */
829 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
830 for (i
=0; i
<numTypes
; i
++) {
831 /* get the kind of type */
832 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
836 /* skip non-interfaces, and get type info for the type */
837 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
840 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
843 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
847 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
848 kind
== TKIND_DISPATCH
)
850 /* the path to the type */
851 get_interface_key( &typeAttr
->guid
, subKeyName
);
853 /* Delete its bits */
854 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
)
857 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
858 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
859 RegDeleteKeyW(subKey
, TypeLibW
);
862 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
866 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
868 if (typeInfo
) ITypeInfo_Release(typeInfo
);
872 /* Now, delete the type library path subkey */
873 get_lcid_subkey( lcid
, syskind
, subKeyName
);
874 RegDeleteKeyW(key
, subKeyName
);
875 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
876 RegDeleteKeyW(key
, subKeyName
);
878 /* check if there is anything besides the FLAGS/HELPDIR keys.
879 If there is, we don't delete them */
880 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
881 deleteOtherStuff
= TRUE
;
883 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
884 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
886 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
887 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
888 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
889 deleteOtherStuff
= FALSE
;
893 /* only delete the other parts of the key if we're absolutely sure */
894 if (deleteOtherStuff
) {
895 RegDeleteKeyW(key
, FLAGSW
);
896 RegDeleteKeyW(key
, HELPDIRW
);
900 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
901 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
902 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
906 SysFreeString(tlibPath
);
907 if (typeLib
) ITypeLib_Release(typeLib
);
908 if (subKey
) RegCloseKey(subKey
);
909 if (key
) RegCloseKey(key
);
913 /******************************************************************************
914 * RegisterTypeLibForUser [OLEAUT32.442]
915 * Adds information about a type library to the user registry
917 * Docs: ITypeLib FAR * ptlib
918 * Docs: OLECHAR FAR* szFullPath
919 * Docs: OLECHAR FAR* szHelpDir
925 HRESULT WINAPI
RegisterTypeLibForUser(
926 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
927 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
928 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
931 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
932 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
933 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
936 /******************************************************************************
937 * UnRegisterTypeLibForUser [OLEAUT32.443]
938 * Removes information about a type library from the user registry
944 HRESULT WINAPI
UnRegisterTypeLibForUser(
945 REFGUID libid
, /* [in] GUID of the library */
946 WORD wVerMajor
, /* [in] major version */
947 WORD wVerMinor
, /* [in] minor version */
948 LCID lcid
, /* [in] locale id */
951 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
952 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
953 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
956 /*======================= ITypeLib implementation =======================*/
958 typedef struct tagTLBGuid
{
965 typedef struct tagTLBCustData
972 /* data structure for import typelibs */
973 typedef struct tagTLBImpLib
975 int offset
; /* offset in the file (MSFT)
976 offset in nametable (SLTG)
977 just used to identify library while reading
979 TLBGuid
*guid
; /* libid */
980 BSTR name
; /* name */
982 LCID lcid
; /* lcid of imported typelib */
984 WORD wVersionMajor
; /* major version number */
985 WORD wVersionMinor
; /* minor version number */
987 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
988 NULL if not yet loaded */
992 typedef struct tagTLBString
{
998 /* internal ITypeLib data */
999 typedef struct tagITypeLibImpl
1001 ITypeLib2 ITypeLib2_iface
;
1002 ITypeComp ITypeComp_iface
;
1003 ICreateTypeLib2 ICreateTypeLib2_iface
;
1014 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1015 * exported to the application as a UNICODE string.
1017 struct list string_list
;
1018 struct list name_list
;
1019 struct list guid_list
;
1021 const TLBString
*Name
;
1022 const TLBString
*DocString
;
1023 const TLBString
*HelpFile
;
1024 const TLBString
*HelpStringDll
;
1025 DWORD dwHelpContext
;
1026 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1027 struct tagITypeInfoImpl
**typeinfos
;
1028 struct list custdata_list
;
1029 struct list implib_list
;
1030 int ctTypeDesc
; /* number of items in type desc array */
1031 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1032 library. Only used while reading MSFT
1034 struct list ref_list
; /* list of ref types in this typelib */
1035 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1038 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1044 static const ITypeLib2Vtbl tlbvt
;
1045 static const ITypeCompVtbl tlbtcvt
;
1046 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1048 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1050 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1053 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1055 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1058 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1060 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1063 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1065 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1068 /* ITypeLib methods */
1069 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1070 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1072 /*======================= ITypeInfo implementation =======================*/
1074 /* data for referenced types */
1075 typedef struct tagTLBRefType
1077 INT index
; /* Type index for internal ref or for external ref
1078 it the format is SLTG. -2 indicates to
1082 TLBGuid
*guid
; /* guid of the referenced type */
1083 /* if index == TLB_REF_USE_GUID */
1085 HREFTYPE reference
; /* The href of this ref */
1086 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1087 TLB_REF_INTERNAL for internal refs
1088 TLB_REF_NOT_FOUND for broken refs */
1093 #define TLB_REF_USE_GUID -2
1095 #define TLB_REF_INTERNAL (void*)-2
1096 #define TLB_REF_NOT_FOUND (void*)-1
1098 /* internal Parameter data */
1099 typedef struct tagTLBParDesc
1101 const TLBString
*Name
;
1102 struct list custdata_list
;
1105 /* internal Function data */
1106 typedef struct tagTLBFuncDesc
1108 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1109 const TLBString
*Name
; /* the name of this function */
1110 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1112 int HelpStringContext
;
1113 const TLBString
*HelpString
;
1114 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1115 struct list custdata_list
;
1118 /* internal Variable data */
1119 typedef struct tagTLBVarDesc
1121 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1122 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1123 const TLBString
*Name
; /* the name of this variable */
1125 int HelpStringContext
;
1126 const TLBString
*HelpString
;
1127 struct list custdata_list
;
1130 /* internal implemented interface data */
1131 typedef struct tagTLBImplType
1133 HREFTYPE hRef
; /* hRef of interface */
1134 int implflags
; /* IMPLFLAG_*s */
1135 struct list custdata_list
;
1138 /* internal TypeInfo data */
1139 typedef struct tagITypeInfoImpl
1141 ITypeInfo2 ITypeInfo2_iface
;
1142 ITypeComp ITypeComp_iface
;
1143 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1145 BOOL not_attached_to_typelib
;
1150 MEMBERID memidConstructor
;
1151 MEMBERID memidDestructor
;
1152 LPOLESTR lpstrSchema
;
1153 ULONG cbSizeInstance
;
1163 TYPEDESC tdescAlias
;
1164 IDLDESC idldescType
;
1166 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1167 int index
; /* index in this typelib; */
1168 HREFTYPE hreftype
; /* hreftype for app object binding */
1169 /* type libs seem to store the doc strings in ascii
1170 * so why should we do it in unicode?
1172 const TLBString
*Name
;
1173 const TLBString
*DocString
;
1174 const TLBString
*DllName
;
1175 const TLBString
*Schema
;
1176 DWORD dwHelpContext
;
1177 DWORD dwHelpStringContext
;
1180 TLBFuncDesc
*funcdescs
;
1183 TLBVarDesc
*vardescs
;
1185 /* Implemented Interfaces */
1186 TLBImplType
*impltypes
;
1188 struct list
*pcustdata_list
;
1189 struct list custdata_list
;
1192 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1194 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1197 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1199 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1202 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1204 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1207 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1209 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1212 static const ITypeInfo2Vtbl tinfvt
;
1213 static const ITypeCompVtbl tcompvt
;
1214 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1216 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1217 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1219 typedef struct tagTLBContext
1221 unsigned int oStart
; /* start of TLB in file */
1222 unsigned int pos
; /* current pos */
1223 unsigned int length
; /* total length */
1224 void *mapping
; /* memory mapping */
1225 MSFT_SegDir
* pTblDir
;
1226 ITypeLibImpl
* pLibInfo
;
1230 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1232 return str
!= NULL
? str
->str
: NULL
;
1235 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1239 return memcmp(left
, str
->str
, len
);
1242 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1244 return guid
!= NULL
? &guid
->guid
: NULL
;
1247 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1249 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1252 static int get_ptr_size(SYSKIND syskind
)
1262 WARN("Unhandled syskind: 0x%x\n", syskind
);
1269 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1270 if (pTD
->vt
& VT_RESERVED
)
1271 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1272 if (pTD
->vt
& VT_BYREF
)
1273 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1274 if (pTD
->vt
& VT_ARRAY
)
1275 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1276 if (pTD
->vt
& VT_VECTOR
)
1277 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1278 switch(pTD
->vt
& VT_TYPEMASK
) {
1279 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1280 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1281 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1282 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1283 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1284 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1285 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1286 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1287 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1288 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1289 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1290 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1291 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1292 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1293 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1294 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1295 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1296 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1297 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1298 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1299 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1300 pTD
->u
.hreftype
); break;
1301 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1302 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1303 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1304 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1306 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1307 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1309 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1310 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1311 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1314 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1318 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1320 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1321 dump_TypeDesc(&edesc
->tdesc
,buf
);
1322 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1323 MESSAGE("\t\tu.paramdesc.wParamFlags");
1324 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1325 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1326 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1327 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1328 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1329 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1330 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1331 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1332 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1334 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1336 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1337 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1338 MESSAGE("Param %d:\n",i
);
1339 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1341 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1342 switch (funcdesc
->funckind
) {
1343 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1344 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1345 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1346 case FUNC_STATIC
: MESSAGE("static");break;
1347 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1348 default: MESSAGE("unknown");break;
1350 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1351 switch (funcdesc
->invkind
) {
1352 case INVOKE_FUNC
: MESSAGE("func");break;
1353 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1354 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1355 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1357 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1358 switch (funcdesc
->callconv
) {
1359 case CC_CDECL
: MESSAGE("cdecl");break;
1360 case CC_PASCAL
: MESSAGE("pascal");break;
1361 case CC_STDCALL
: MESSAGE("stdcall");break;
1362 case CC_SYSCALL
: MESSAGE("syscall");break;
1365 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1366 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1367 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1369 MESSAGE("\telemdescFunc (return value type):\n");
1370 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1373 static const char * const typekind_desc
[] =
1386 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1389 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1390 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1391 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1394 dump_FUNCDESC(&(pfd
->funcdesc
));
1396 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1397 if(pfd
->Entry
== NULL
)
1398 MESSAGE("\tentry: (null)\n");
1399 else if(pfd
->Entry
== (void*)-1)
1400 MESSAGE("\tentry: invalid\n");
1401 else if(IS_INTRESOURCE(pfd
->Entry
))
1402 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1404 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1406 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1410 dump_TLBFuncDescOne(pfd
);
1415 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1419 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1425 static void dump_TLBImpLib(const TLBImpLib
*import
)
1427 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1428 debugstr_w(import
->name
));
1429 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1430 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1433 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1437 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1439 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1440 if(ref
->index
== -1)
1441 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1443 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1445 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1447 TRACE_(typelib
)("in lib\n");
1448 dump_TLBImpLib(ref
->pImpTLInfo
);
1453 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1458 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1459 impl
->hRef
, impl
->implflags
);
1465 static void dump_Variant(const VARIANT
* pvar
)
1469 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1473 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1474 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1476 TRACE(",%p", V_BYREF(pvar
));
1478 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1480 TRACE(",%p", V_ARRAY(pvar
));
1482 else switch (V_TYPE(pvar
))
1484 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1485 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1486 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1487 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1489 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1491 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1492 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1493 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1494 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1495 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1496 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1497 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1498 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1499 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1500 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1501 V_CY(pvar
).s
.Lo
); break;
1503 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1504 TRACE(",<invalid>");
1506 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1507 st
.wHour
, st
.wMinute
, st
.wSecond
);
1511 case VT_USERDEFINED
:
1513 case VT_NULL
: break;
1514 default: TRACE(",?"); break;
1520 static void dump_DispParms(const DISPPARAMS
* pdp
)
1524 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1526 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1528 TRACE("named args:\n");
1529 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1530 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1533 if (pdp
->cArgs
&& pdp
->rgvarg
)
1536 for (index
= 0; index
< pdp
->cArgs
; index
++)
1537 dump_Variant( &pdp
->rgvarg
[index
] );
1541 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1543 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1544 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1545 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1546 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1547 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1548 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1549 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1550 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1552 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1553 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1554 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1557 static void dump_VARDESC(const VARDESC
*v
)
1559 MESSAGE("memid %d\n",v
->memid
);
1560 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1561 MESSAGE("oInst %d\n",v
->u
.oInst
);
1562 dump_ELEMDESC(&(v
->elemdescVar
));
1563 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1564 MESSAGE("varkind %d\n",v
->varkind
);
1567 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1569 /* VT_LPWSTR is largest type that, may appear in type description */
1570 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1571 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1572 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1573 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1574 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1575 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1576 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1577 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1580 static void TLB_abort(void)
1585 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1587 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1588 if (!ret
) ERR("cannot allocate memory\n");
1592 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1594 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1595 if (!ret
) ERR("cannot allocate memory\n");
1599 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1601 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1604 void heap_free(void *ptr
)
1606 HeapFree(GetProcessHeap(), 0, ptr
);
1609 /* returns the size required for a deep copy of a typedesc into a
1611 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1615 if (alloc_initial_space
)
1616 size
+= sizeof(TYPEDESC
);
1622 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1625 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1626 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1632 /* deep copy a typedesc into a flat buffer */
1633 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1638 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1647 dest
->u
.lptdesc
= buffer
;
1648 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1651 dest
->u
.lpadesc
= buffer
;
1652 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1653 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1654 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1660 /* free custom data allocated by MSFT_CustData */
1661 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1663 TLBCustData
*cd
, *cdn
;
1664 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1666 list_remove(&cd
->entry
);
1667 VariantClear(&cd
->data
);
1672 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1677 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1678 ret
= SysAllocStringLen(NULL
, len
- 1);
1679 if (!ret
) return ret
;
1680 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1684 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1685 UINT n
, MEMBERID memid
)
1688 if(funcdescs
->funcdesc
.memid
== memid
)
1696 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1697 UINT n
, const OLECHAR
*name
)
1700 if(!lstrcmpiW(TLB_get_bstr(funcdescs
->Name
), name
))
1708 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1709 UINT n
, MEMBERID memid
)
1712 if(vardescs
->vardesc
.memid
== memid
)
1720 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1721 UINT n
, const OLECHAR
*name
)
1724 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1732 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1734 TLBCustData
*cust_data
;
1735 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1736 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1741 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1742 UINT n
, const OLECHAR
*name
)
1745 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1753 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1755 list_init(&var_desc
->custdata_list
);
1758 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1762 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1767 TLBVarDesc_Constructor(&ret
[n
-1]);
1774 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1778 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1783 list_init(&ret
[n
-1].custdata_list
);
1790 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1792 list_init(&func_desc
->custdata_list
);
1795 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1799 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1804 TLBFuncDesc_Constructor(&ret
[n
-1]);
1811 static void TLBImplType_Constructor(TLBImplType
*impl
)
1813 list_init(&impl
->custdata_list
);
1816 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1820 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1825 TLBImplType_Constructor(&ret
[n
-1]);
1832 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1833 const GUID
*new_guid
, HREFTYPE hreftype
)
1837 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1838 if (IsEqualGUID(&guid
->guid
, new_guid
))
1842 guid
= heap_alloc(sizeof(TLBGuid
));
1846 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1847 guid
->hreftype
= hreftype
;
1849 list_add_tail(guid_list
, &guid
->entry
);
1854 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1856 TLBCustData
*cust_data
;
1868 return DISP_E_BADVARTYPE
;
1871 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1874 cust_data
= heap_alloc(sizeof(TLBCustData
));
1876 return E_OUTOFMEMORY
;
1878 cust_data
->guid
= tlbguid
;
1879 VariantInit(&cust_data
->data
);
1881 list_add_tail(custdata_list
, &cust_data
->entry
);
1883 VariantClear(&cust_data
->data
);
1885 return VariantCopy(&cust_data
->data
, var
);
1888 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1892 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1893 if (strcmpW(str
->str
, new_str
) == 0)
1897 str
= heap_alloc(sizeof(TLBString
));
1901 str
->str
= SysAllocString(new_str
);
1907 list_add_tail(string_list
, &str
->entry
);
1912 /**********************************************************************
1914 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1916 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1921 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
1923 if (where
!= DO_NOT_SEEK
)
1925 where
+= pcx
->oStart
;
1926 if (where
> pcx
->length
)
1929 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
1937 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
1939 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1940 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1942 MSFT_Seek(pcx
, where
);
1943 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1944 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1949 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1954 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1955 FromLEDWords(buffer
, ret
);
1960 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1965 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1966 FromLEWords(buffer
, ret
);
1971 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
1974 MSFT_GuidEntry entry
;
1977 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
1979 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
1982 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
1984 guid
= heap_alloc(sizeof(TLBGuid
));
1986 guid
->offset
= offs
;
1987 guid
->guid
= entry
.guid
;
1988 guid
->hreftype
= entry
.hreftype
;
1990 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
1992 offs
+= sizeof(MSFT_GuidEntry
);
1996 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2000 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2001 if(ret
->offset
== offset
){
2002 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2010 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2012 MSFT_NameIntro niName
;
2016 ERR_(typelib
)("bad offset %d\n", offset
);
2020 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2021 pcx
->pTblDir
->pNametab
.offset
+offset
);
2023 return niName
.hreftype
;
2026 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2029 MSFT_NameIntro intro
;
2031 int offs
= 0, lengthInChars
;
2033 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2037 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2040 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2041 intro
.namelen
&= 0xFF;
2042 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2044 len_piece
= (len_piece
+ 4) & ~0x3;
2048 string
= heap_alloc(len_piece
+ 1);
2049 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2050 string
[intro
.namelen
] = '\0';
2052 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2053 string
, -1, NULL
, 0);
2054 if (!lengthInChars
) {
2056 return E_UNEXPECTED
;
2059 tlbstr
= heap_alloc(sizeof(TLBString
));
2061 tlbstr
->offset
= offs
;
2062 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2063 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2067 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2073 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2077 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2078 if (tlbstr
->offset
== offset
) {
2079 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2087 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2091 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2092 if (tlbstr
->offset
== offset
) {
2093 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2102 * read a value and fill a VARIANT structure
2104 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2108 TRACE_(typelib
)("\n");
2110 if(offset
<0) { /* data are packed in here */
2111 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2112 V_I4(pVar
) = offset
& 0x3ffffff;
2115 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2116 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2117 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2118 switch (V_VT(pVar
)){
2119 case VT_EMPTY
: /* FIXME: is this right? */
2120 case VT_NULL
: /* FIXME: is this right? */
2121 case VT_I2
: /* this should not happen */
2132 case VT_VOID
: /* FIXME: is this right? */
2140 case VT_DECIMAL
: /* FIXME: is this right? */
2143 /* pointer types with known behaviour */
2146 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2149 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
2152 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
2154 nullPos
= MSFT_Tell(pcx
);
2155 size
= nullPos
- origPos
;
2156 MSFT_Seek(pcx
, origPos
);
2158 ptr
= heap_alloc_zero(size
);/* allocate temp buffer */
2159 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
2160 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2161 /* FIXME: do we need a AtoW conversion here? */
2162 V_UNION(pVar
, bstrVal
[size
])='\0';
2163 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2167 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2174 case VT_USERDEFINED
:
2180 case VT_STREAMED_OBJECT
:
2181 case VT_STORED_OBJECT
:
2182 case VT_BLOB_OBJECT
:
2187 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2191 if(size
>0) /* (big|small) endian correct? */
2192 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2196 * create a linked list with custom data
2198 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2204 TRACE_(typelib
)("\n");
2206 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2210 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2211 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2212 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2213 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2214 list_add_head(custdata_list
, &pNew
->entry
);
2215 offset
= entry
.next
;
2220 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
2224 pTd
->vt
=type
& VT_TYPEMASK
;
2226 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2228 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2231 static int TLB_is_propgetput(INVOKEKIND invkind
)
2233 return (invkind
== INVOKE_PROPERTYGET
||
2234 invkind
== INVOKE_PROPERTYPUT
||
2235 invkind
== INVOKE_PROPERTYPUTREF
);
2239 MSFT_DoFuncs(TLBContext
* pcx
,
2244 TLBFuncDesc
** pptfd
)
2247 * member information is stored in a data structure at offset
2248 * indicated by the memoffset field of the typeinfo structure
2249 * There are several distinctive parts.
2250 * The first part starts with a field that holds the total length
2251 * of this (first) part excluding this field. Then follow the records,
2252 * for each member there is one record.
2254 * The first entry is always the length of the record (including this
2256 * The rest of the record depends on the type of the member. If there is
2257 * a field indicating the member type (function, variable, interface, etc)
2258 * I have not found it yet. At this time we depend on the information
2259 * in the type info and the usual order how things are stored.
2261 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2264 * Third is an equal sized array with file offsets to the name entry
2267 * The fourth and last (?) part is an array with offsets to the records
2268 * in the first part of this file segment.
2271 int infolen
, nameoffset
, reclength
, i
;
2272 int recoffset
= offset
+ sizeof(INT
);
2274 char *recbuf
= heap_alloc(0xffff);
2275 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2276 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2278 TRACE_(typelib
)("\n");
2280 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2282 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2284 for ( i
= 0; i
< cFuncs
; i
++ )
2288 /* name, eventually add to a hash table */
2289 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2290 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2292 /* read the function information record */
2293 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2295 reclength
&= 0xffff;
2297 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2299 /* size without argument data */
2300 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2301 if (pFuncRec
->FKCCIC
& 0x1000)
2302 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2304 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2305 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2307 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2308 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2310 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2312 if (pFuncRec
->FKCCIC
& 0x2000 )
2314 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2315 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2316 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2319 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2322 ptfd
->Entry
= (TLBString
*)-1;
2324 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2325 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2327 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2328 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2330 /* fill the FuncDesc Structure */
2331 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2332 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2334 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2335 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2336 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2337 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2338 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2339 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2340 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2342 /* nameoffset is sometimes -1 on the second half of a propget/propput
2343 * pair of functions */
2344 if ((nameoffset
== -1) && (i
> 0) &&
2345 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2346 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2347 ptfd
->Name
= ptfd_prev
->Name
;
2349 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2353 &ptfd
->funcdesc
.elemdescFunc
.tdesc
,
2356 /* do the parameters/arguments */
2357 if(pFuncRec
->nrargs
)
2360 MSFT_ParameterInfo paraminfo
;
2362 ptfd
->funcdesc
.lprgelemdescParam
=
2363 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2365 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2367 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2368 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2370 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2372 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2379 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2382 if (paraminfo
.oName
!= -1)
2383 ptfd
->pParamDesc
[j
].Name
=
2384 MSFT_ReadName( pcx
, paraminfo
.oName
);
2385 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2388 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2389 (pFuncRec
->FKCCIC
& 0x1000) )
2391 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2393 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2395 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2397 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2398 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2400 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2404 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2407 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2408 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2409 pFuncRec
->FKCCIC
& 0x80 )
2412 pFuncRec
->oArgCustData
[j
],
2413 &ptfd
->pParamDesc
[j
].custdata_list
);
2416 /* SEEK value = jump to offset,
2417 * from there jump to the end of record,
2418 * go back by (j-1) arguments
2420 MSFT_ReadLEDWords( ¶minfo
,
2421 sizeof(MSFT_ParameterInfo
), pcx
,
2422 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2423 * sizeof(MSFT_ParameterInfo
)));
2427 /* scode is not used: archaic win16 stuff FIXME: right? */
2428 ptfd
->funcdesc
.cScodes
= 0 ;
2429 ptfd
->funcdesc
.lprgscode
= NULL
;
2433 recoffset
+= reclength
;
2438 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2439 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2441 int infolen
, nameoffset
, reclength
;
2443 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2448 TRACE_(typelib
)("\n");
2450 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2451 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2452 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2453 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2454 recoffset
+= offset
+sizeof(INT
);
2455 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2456 /* name, eventually add to a hash table */
2457 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2458 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2459 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2460 /* read the variable information record */
2461 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2463 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2466 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2467 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2469 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2470 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2472 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2473 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2475 /* fill the VarDesc Structure */
2476 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2477 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2478 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2479 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2480 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2481 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2482 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2483 if(pVarRec
->VarKind
== VAR_CONST
){
2484 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2485 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2486 pVarRec
->OffsValue
, pcx
);
2488 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2489 recoffset
+= reclength
;
2493 /* process Implemented Interfaces of a com class */
2494 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2498 MSFT_RefRecord refrec
;
2501 TRACE_(typelib
)("\n");
2503 pTI
->impltypes
= TLBImplType_Alloc(count
);
2504 pImpl
= pTI
->impltypes
;
2505 for(i
=0;i
<count
;i
++){
2506 if(offset
<0) break; /* paranoia */
2507 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2508 pImpl
->hRef
= refrec
.reftype
;
2509 pImpl
->implflags
=refrec
.flags
;
2510 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2511 offset
=refrec
.onext
;
2516 * process a typeinfo record
2518 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2521 ITypeLibImpl
* pLibInfo
)
2523 MSFT_TypeInfoBase tiBase
;
2524 ITypeInfoImpl
*ptiRet
;
2526 TRACE_(typelib
)("count=%u\n", count
);
2528 ptiRet
= ITypeInfoImpl_Constructor();
2529 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2530 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2532 /* this is where we are coming from */
2533 ptiRet
->pTypeLib
= pLibInfo
;
2534 ptiRet
->index
=count
;
2536 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2537 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2538 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2539 ptiRet
->cbSizeInstance
=tiBase
.size
;
2540 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2541 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2542 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2543 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2544 ptiRet
->wTypeFlags
=tiBase
.flags
;
2545 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2546 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2547 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2548 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2549 if(ptiRet
->typekind
== TKIND_ALIAS
)
2550 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2551 &ptiRet
->tdescAlias
, ptiRet
);
2554 /* IDLDESC idldescType; *//* never saw this one != zero */
2556 /* name, eventually add to a hash table */
2557 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2558 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2559 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2561 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2562 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2563 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2565 if (ptiRet
->typekind
== TKIND_MODULE
)
2566 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2568 /* note: InfoType's Help file and HelpStringDll come from the containing
2569 * library. Further HelpString and Docstring appear to be the same thing :(
2572 if(ptiRet
->cFuncs
>0 )
2573 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2575 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2577 if(ptiRet
->cVars
>0 )
2578 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2580 tiBase
.memoffset
, &ptiRet
->vardescs
);
2581 if(ptiRet
->cImplTypes
>0 ) {
2582 switch(ptiRet
->typekind
)
2585 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2588 case TKIND_DISPATCH
:
2589 /* This is not -1 when the interface is a non-base dual interface or
2590 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2591 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2595 if (tiBase
.datatype1
!= -1)
2597 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2598 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2602 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2603 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2607 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2609 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2610 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2611 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2612 typekind_desc
[ptiRet
->typekind
]);
2613 if (TRACE_ON(typelib
))
2614 dump_TypeInfo(ptiRet
);
2619 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2622 INT16 len_str
, len_piece
;
2623 int offs
= 0, lengthInChars
;
2625 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2629 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2632 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2633 len_piece
= len_str
+ sizeof(INT16
);
2635 len_piece
= (len_piece
+ 4) & ~0x3;
2639 string
= heap_alloc(len_piece
+ 1);
2640 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2641 string
[len_str
] = '\0';
2643 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2644 string
, -1, NULL
, 0);
2645 if (!lengthInChars
) {
2647 return E_UNEXPECTED
;
2650 tlbstr
= heap_alloc(sizeof(TLBString
));
2652 tlbstr
->offset
= offs
;
2653 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2654 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2658 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2664 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2669 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2670 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2671 MSFT_ImpInfo impinfo
;
2674 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2676 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2677 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2679 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2680 if(pImpLib
->offset
==impinfo
.oImpFile
)
2683 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2684 ref
->reference
= offs
;
2685 ref
->pImpTLInfo
= pImpLib
;
2686 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2687 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2688 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2689 ref
->index
= TLB_REF_USE_GUID
;
2691 ref
->index
= impinfo
.oGuid
;
2693 ERR("Cannot find a reference\n");
2694 ref
->reference
= -1;
2695 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2698 offs
+= sizeof(impinfo
);
2704 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2705 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2706 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2709 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2710 static CRITICAL_SECTION cache_section
;
2711 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2713 0, 0, &cache_section
,
2714 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2715 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2717 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2720 typedef struct TLB_PEFile
2722 IUnknown IUnknown_iface
;
2725 HRSRC typelib_resource
;
2726 HGLOBAL typelib_global
;
2727 LPVOID typelib_base
;
2730 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2732 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2735 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2737 if (IsEqualIID(riid
, &IID_IUnknown
))
2740 IUnknown_AddRef(iface
);
2744 return E_NOINTERFACE
;
2747 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2749 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2750 return InterlockedIncrement(&This
->refs
);
2753 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2755 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2756 ULONG refs
= InterlockedDecrement(&This
->refs
);
2759 if (This
->typelib_global
)
2760 FreeResource(This
->typelib_global
);
2762 FreeLibrary(This
->dll
);
2768 static const IUnknownVtbl TLB_PEFile_Vtable
=
2770 TLB_PEFile_QueryInterface
,
2775 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2778 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2780 This
= heap_alloc(sizeof(TLB_PEFile
));
2782 return E_OUTOFMEMORY
;
2784 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2787 This
->typelib_resource
= NULL
;
2788 This
->typelib_global
= NULL
;
2789 This
->typelib_base
= NULL
;
2791 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2792 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2796 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2797 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2798 if (This
->typelib_resource
)
2800 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2801 if (This
->typelib_global
)
2803 This
->typelib_base
= LockResource(This
->typelib_global
);
2805 if (This
->typelib_base
)
2807 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2808 *ppBase
= This
->typelib_base
;
2809 *ppFile
= &This
->IUnknown_iface
;
2815 TRACE("No TYPELIB resource found\n");
2819 TLB_PEFile_Release(&This
->IUnknown_iface
);
2823 typedef struct TLB_NEFile
2825 IUnknown IUnknown_iface
;
2827 LPVOID typelib_base
;
2830 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2832 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2835 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2837 if (IsEqualIID(riid
, &IID_IUnknown
))
2840 IUnknown_AddRef(iface
);
2844 return E_NOINTERFACE
;
2847 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2849 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2850 return InterlockedIncrement(&This
->refs
);
2853 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2855 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2856 ULONG refs
= InterlockedDecrement(&This
->refs
);
2859 heap_free(This
->typelib_base
);
2865 static const IUnknownVtbl TLB_NEFile_Vtable
=
2867 TLB_NEFile_QueryInterface
,
2872 /***********************************************************************
2873 * read_xx_header [internal]
2875 static int read_xx_header( HFILE lzfd
)
2877 IMAGE_DOS_HEADER mzh
;
2880 LZSeek( lzfd
, 0, SEEK_SET
);
2881 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2883 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2886 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2887 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2890 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2892 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2893 return IMAGE_OS2_SIGNATURE
;
2894 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2895 return IMAGE_NT_SIGNATURE
;
2898 WARN("Can't handle %s files.\n", magic
);
2903 /***********************************************************************
2904 * find_ne_resource [internal]
2906 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2907 DWORD
*resLen
, DWORD
*resOff
)
2909 IMAGE_OS2_HEADER nehd
;
2910 NE_TYPEINFO
*typeInfo
;
2911 NE_NAMEINFO
*nameInfo
;
2917 /* Read in NE header */
2918 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2919 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2921 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2924 TRACE("No resources in NE dll\n" );
2928 /* Read in resource table */
2929 resTab
= heap_alloc( resTabSize
);
2930 if ( !resTab
) return FALSE
;
2932 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2933 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2935 heap_free( resTab
);
2940 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2942 if (!IS_INTRESOURCE(typeid)) /* named type */
2944 BYTE len
= strlen( typeid );
2945 while (typeInfo
->type_id
)
2947 if (!(typeInfo
->type_id
& 0x8000))
2949 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2950 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2952 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2953 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2956 else /* numeric type id */
2958 WORD id
= LOWORD(typeid) | 0x8000;
2959 while (typeInfo
->type_id
)
2961 if (typeInfo
->type_id
== id
) goto found_type
;
2962 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2963 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2966 TRACE("No typeid entry found for %p\n", typeid );
2967 heap_free( resTab
);
2971 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2973 if (!IS_INTRESOURCE(resid
)) /* named resource */
2975 BYTE len
= strlen( resid
);
2976 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2978 BYTE
*p
= resTab
+ nameInfo
->id
;
2979 if (nameInfo
->id
& 0x8000) continue;
2980 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2983 else /* numeric resource id */
2985 WORD id
= LOWORD(resid
) | 0x8000;
2986 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2987 if (nameInfo
->id
== id
) goto found_name
;
2989 TRACE("No resid entry found for %p\n", typeid );
2990 heap_free( resTab
);
2994 /* Return resource data */
2995 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2996 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2998 heap_free( resTab
);
3002 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3006 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3009 This
= heap_alloc(sizeof(TLB_NEFile
));
3010 if (!This
) return E_OUTOFMEMORY
;
3012 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3014 This
->typelib_base
= NULL
;
3016 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3017 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3019 DWORD reslen
, offset
;
3020 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3022 This
->typelib_base
= heap_alloc(reslen
);
3023 if( !This
->typelib_base
)
3027 LZSeek( lzfd
, offset
, SEEK_SET
);
3028 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3030 *ppBase
= This
->typelib_base
;
3031 *pdwTLBLength
= reslen
;
3032 *ppFile
= &This
->IUnknown_iface
;
3038 if( lzfd
>= 0) LZClose( lzfd
);
3039 TLB_NEFile_Release(&This
->IUnknown_iface
);
3043 typedef struct TLB_Mapping
3045 IUnknown IUnknown_iface
;
3049 LPVOID typelib_base
;
3052 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3054 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3057 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3059 if (IsEqualIID(riid
, &IID_IUnknown
))
3062 IUnknown_AddRef(iface
);
3066 return E_NOINTERFACE
;
3069 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3071 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3072 return InterlockedIncrement(&This
->refs
);
3075 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3077 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3078 ULONG refs
= InterlockedDecrement(&This
->refs
);
3081 if (This
->typelib_base
)
3082 UnmapViewOfFile(This
->typelib_base
);
3084 CloseHandle(This
->mapping
);
3085 if (This
->file
!= INVALID_HANDLE_VALUE
)
3086 CloseHandle(This
->file
);
3092 static const IUnknownVtbl TLB_Mapping_Vtable
=
3094 TLB_Mapping_QueryInterface
,
3099 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3103 This
= heap_alloc(sizeof(TLB_Mapping
));
3105 return E_OUTOFMEMORY
;
3107 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3109 This
->file
= INVALID_HANDLE_VALUE
;
3110 This
->mapping
= NULL
;
3111 This
->typelib_base
= NULL
;
3113 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3114 if (INVALID_HANDLE_VALUE
!= This
->file
)
3116 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3119 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3120 if(This
->typelib_base
)
3122 /* retrieve file size */
3123 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3124 *ppBase
= This
->typelib_base
;
3125 *ppFile
= &This
->IUnknown_iface
;
3131 IUnknown_Release(&This
->IUnknown_iface
);
3132 return TYPE_E_CANTLOADLIBRARY
;
3135 /****************************************************************************
3138 * find the type of the typelib file and map the typelib resource into
3142 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3143 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3145 ITypeLibImpl
*entry
;
3148 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3149 LPVOID pBase
= NULL
;
3150 DWORD dwTLBLength
= 0;
3151 IUnknown
*pFile
= NULL
;
3156 index_str
= strrchrW(pszFileName
, '\\');
3157 if(index_str
&& *++index_str
!= '\0')
3160 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3161 if(*end_ptr
== '\0')
3163 int str_len
= index_str
- pszFileName
- 1;
3165 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3166 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3171 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3173 if(strchrW(file
, '\\'))
3175 lstrcpyW(pszPath
, file
);
3179 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3180 pszPath
[len
] = '\\';
3181 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3185 if(file
!= pszFileName
) heap_free(file
);
3187 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_ALWAYS
,
3188 FILE_ATTRIBUTE_NORMAL
, NULL
);
3189 if(h
!= INVALID_HANDLE_VALUE
){
3190 FILE_NAME_INFORMATION
*info
;
3191 char data
[MAX_PATH
* sizeof(WCHAR
) + sizeof(info
->FileNameLength
)];
3194 info
= (FILE_NAME_INFORMATION
*)data
;
3195 /* GetFileInformationByHandleEx returns the path of the file without
3196 * WOW64 redirection */
3197 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, data
, sizeof(data
));
3199 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3200 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3205 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3207 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3208 EnterCriticalSection(&cache_section
);
3209 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3211 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3213 TRACE("cache hit\n");
3214 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3215 ITypeLib2_AddRef(*ppTypeLib
);
3216 LeaveCriticalSection(&cache_section
);
3220 LeaveCriticalSection(&cache_section
);
3222 /* now actually load and parse the typelib */
3224 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3225 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3226 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3227 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3228 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3231 if (dwTLBLength
>= 4)
3233 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3234 if (dwSignature
== MSFT_SIGNATURE
)
3235 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3236 else if (dwSignature
== SLTG_SIGNATURE
)
3237 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3240 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3241 ret
= TYPE_E_CANTLOADLIBRARY
;
3245 ret
= TYPE_E_CANTLOADLIBRARY
;
3246 IUnknown_Release(pFile
);
3250 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3252 TRACE("adding to cache\n");
3253 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3254 lstrcpyW(impl
->path
, pszPath
);
3255 /* We should really canonicalise the path here. */
3256 impl
->index
= index
;
3258 /* FIXME: check if it has added already in the meantime */
3259 EnterCriticalSection(&cache_section
);
3260 list_add_head(&tlb_cache
, &impl
->entry
);
3261 LeaveCriticalSection(&cache_section
);
3267 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3269 ret
= TYPE_E_CANTLOADLIBRARY
;
3276 /*================== ITypeLib(2) Methods ===================================*/
3278 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3280 ITypeLibImpl
* pTypeLibImpl
;
3282 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3283 if (!pTypeLibImpl
) return NULL
;
3285 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3286 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3287 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3288 pTypeLibImpl
->ref
= 1;
3290 list_init(&pTypeLibImpl
->implib_list
);
3291 list_init(&pTypeLibImpl
->custdata_list
);
3292 list_init(&pTypeLibImpl
->name_list
);
3293 list_init(&pTypeLibImpl
->string_list
);
3294 list_init(&pTypeLibImpl
->guid_list
);
3295 list_init(&pTypeLibImpl
->ref_list
);
3296 pTypeLibImpl
->dispatch_href
= -1;
3298 return pTypeLibImpl
;
3301 /****************************************************************************
3302 * ITypeLib2_Constructor_MSFT
3304 * loading an MSFT typelib from an in-memory image
3306 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3310 MSFT_Header tlbHeader
;
3311 MSFT_SegDir tlbSegDir
;
3312 ITypeLibImpl
* pTypeLibImpl
;
3314 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3316 pTypeLibImpl
= TypeLibImpl_Constructor();
3317 if (!pTypeLibImpl
) return NULL
;
3319 /* get pointer to beginning of typelib data */
3323 cx
.pLibInfo
= pTypeLibImpl
;
3324 cx
.length
= dwTLBLength
;
3327 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3328 TRACE_(typelib
)("header:\n");
3329 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3330 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3331 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3334 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3336 /* there is a small amount of information here until the next important
3338 * the segment directory . Try to calculate the amount of data */
3339 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3341 /* now read the segment directory */
3342 TRACE("read segment directory (at %d)\n",lPSegDir
);
3343 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3344 cx
.pTblDir
= &tlbSegDir
;
3346 /* just check two entries */
3347 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3349 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3350 heap_free(pTypeLibImpl
);
3354 MSFT_ReadAllNames(&cx
);
3355 MSFT_ReadAllStrings(&cx
);
3356 MSFT_ReadAllGuids(&cx
);
3358 /* now fill our internal data */
3359 /* TLIBATTR fields */
3360 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3362 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3363 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3364 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3365 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3366 pTypeLibImpl
->libflags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3368 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3369 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3371 /* name, eventually add to a hash table */
3372 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3375 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3376 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3378 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3381 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3382 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3385 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3388 if(tlbHeader
.CustomDataOffset
>= 0)
3390 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3393 /* fill in type descriptions */
3394 if(tlbSegDir
.pTypdescTab
.length
> 0)
3396 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3398 pTypeLibImpl
->ctTypeDesc
= cTD
;
3399 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3400 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3403 /* FIXME: add several sanity checks here */
3404 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3405 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3407 /* FIXME: check safearray */
3409 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3411 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3413 else if(td
[0] == VT_CARRAY
)
3415 /* array descr table here */
3416 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3418 else if(td
[0] == VT_USERDEFINED
)
3420 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3422 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3425 /* second time around to fill the array subscript info */
3428 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3429 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3431 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3432 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3435 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3437 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3439 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3441 for(j
= 0; j
<td
[2]; j
++)
3443 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3444 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3445 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3446 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3451 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3452 ERR("didn't find array description data\n");
3457 /* imported type libs */
3458 if(tlbSegDir
.pImpFiles
.offset
>0)
3461 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3464 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3468 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3469 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3470 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3472 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3473 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3474 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3475 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3478 name
= heap_alloc_zero(size
+1);
3479 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3480 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3483 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3484 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3486 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3490 MSFT_ReadAllRefs(&cx
);
3492 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3495 if(tlbHeader
.nrtypeinfos
>= 0 )
3497 ITypeInfoImpl
**ppTI
;
3500 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3502 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3504 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3507 (pTypeLibImpl
->TypeInfoCount
)++;
3511 TRACE("(%p)\n", pTypeLibImpl
);
3512 return &pTypeLibImpl
->ITypeLib2_iface
;
3516 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3522 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3523 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3527 guid
->Data4
[0] = s
>> 8;
3528 guid
->Data4
[1] = s
& 0xff;
3531 for(i
= 0; i
< 6; i
++) {
3532 memcpy(b
, str
+ 24 + 2 * i
, 2);
3533 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3538 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3545 bytelen
= *(const WORD
*)ptr
;
3546 if(bytelen
== 0xffff) return 2;
3548 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3549 tmp_str
= SysAllocStringLen(NULL
, len
);
3551 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3552 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3553 SysFreeString(tmp_str
);
3558 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3563 bytelen
= *(const WORD
*)ptr
;
3564 if(bytelen
== 0xffff) return 2;
3565 *str
= heap_alloc(bytelen
+ 1);
3566 memcpy(*str
, ptr
+ 2, bytelen
);
3567 (*str
)[bytelen
] = '\0';
3571 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3576 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3577 if (tlbstr
->offset
== offset
)
3581 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3582 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3583 SysFreeString(tmp_str
);
3588 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3590 char *ptr
= pLibBlk
;
3593 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3594 FIXME("libblk magic = %04x\n", w
);
3599 if((w
= *(WORD
*)ptr
) != 0xffff) {
3600 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3605 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3607 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3609 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3612 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3613 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3616 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3617 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3619 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3622 ptr
+= 4; /* skip res12 */
3624 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3627 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3630 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3633 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3634 ptr
+= sizeof(GUID
);
3636 return ptr
- (char*)pLibBlk
;
3639 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3644 } sltg_ref_lookup_t
;
3646 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3647 HREFTYPE
*typelib_ref
)
3649 if(table
&& typeinfo_ref
< table
->num
)
3651 *typelib_ref
= table
->refs
[typeinfo_ref
];
3655 ERR_(typelib
)("Unable to find reference\n");
3660 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3665 if((*pType
& 0xe00) == 0xe00) {
3667 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3668 pTD
= pTD
->u
.lptdesc
;
3670 switch(*pType
& 0x3f) {
3673 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3674 pTD
= pTD
->u
.lptdesc
;
3677 case VT_USERDEFINED
:
3678 pTD
->vt
= VT_USERDEFINED
;
3679 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3685 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3688 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3690 pTD
->vt
= VT_CARRAY
;
3691 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3692 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3693 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3694 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3696 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3702 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3706 pTD
->vt
= VT_SAFEARRAY
;
3707 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3708 pTD
= pTD
->u
.lptdesc
;
3712 pTD
->vt
= *pType
& 0x3f;
3721 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3722 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3724 /* Handle [in/out] first */
3725 if((*pType
& 0xc000) == 0xc000)
3726 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3727 else if(*pType
& 0x8000)
3728 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3729 else if(*pType
& 0x4000)
3730 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3732 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3735 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3738 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3740 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3744 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3749 TLBRefType
*ref_type
;
3750 sltg_ref_lookup_t
*table
;
3751 HREFTYPE typelib_ref
;
3753 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3754 FIXME("Ref magic = %x\n", pRef
->magic
);
3757 name
= ( (char*)pRef
->names
+ pRef
->number
);
3759 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3760 table
->num
= pRef
->number
>> 3;
3762 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3764 /* We don't want the first href to be 0 */
3765 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3767 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3769 unsigned int lib_offs
, type_num
;
3771 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3773 name
+= SLTG_ReadStringA(name
, &refname
);
3774 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3775 FIXME_(typelib
)("Can't sscanf ref\n");
3776 if(lib_offs
!= 0xffff) {
3779 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3780 if(import
->offset
== lib_offs
)
3783 if(&import
->entry
== &pTL
->implib_list
) {
3784 char fname
[MAX_PATH
+1];
3788 import
= heap_alloc_zero(sizeof(*import
));
3789 import
->offset
= lib_offs
;
3790 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3791 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3792 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3793 &import
->wVersionMajor
,
3794 &import
->wVersionMinor
,
3795 &import
->lcid
, fname
) != 4) {
3796 FIXME_(typelib
)("can't sscanf ref %s\n",
3797 pNameTable
+ lib_offs
+ 40);
3799 len
= strlen(fname
);
3800 if(fname
[len
-1] != '#')
3801 FIXME("fname = %s\n", fname
);
3802 fname
[len
-1] = '\0';
3803 import
->name
= TLB_MultiByteToBSTR(fname
);
3804 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3806 ref_type
->pImpTLInfo
= import
;
3808 /* Store a reference to IDispatch */
3809 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3810 pTL
->dispatch_href
= typelib_ref
;
3812 } else { /* internal ref */
3813 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3815 ref_type
->reference
= typelib_ref
;
3816 ref_type
->index
= type_num
;
3819 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3821 table
->refs
[ref
] = typelib_ref
;
3824 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3825 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3826 dump_TLBRefType(pTL
);
3830 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3831 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3833 SLTG_ImplInfo
*info
;
3834 TLBImplType
*pImplType
;
3835 /* I don't really get this structure, usually it's 0x16 bytes
3836 long, but iuser.tlb contains some that are 0x18 bytes long.
3837 That's ok because we can use the next ptr to jump to the next
3838 one. But how do we know the length of the last one? The WORD
3839 at offs 0x8 might be the clue. For now I'm just assuming that
3840 the last one is the regular 0x16 bytes. */
3842 info
= (SLTG_ImplInfo
*)pBlk
;
3845 if(info
->next
== 0xffff)
3847 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3850 info
= (SLTG_ImplInfo
*)pBlk
;
3851 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
3852 pImplType
= pTI
->impltypes
;
3854 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3855 pImplType
->implflags
= info
->impltypeflags
;
3858 if(info
->next
== 0xffff)
3861 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3862 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3864 info
++; /* see comment at top of function */
3868 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3869 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3871 TLBVarDesc
*pVarDesc
;
3872 const TLBString
*prevName
= NULL
;
3873 SLTG_Variable
*pItem
;
3877 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
3879 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3880 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3882 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3884 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3885 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3886 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3890 if (pItem
->name
== 0xfffe)
3891 pVarDesc
->Name
= prevName
;
3893 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
3895 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
3896 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3897 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3899 if(pItem
->flags
& 0x02)
3900 pType
= &pItem
->type
;
3902 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3904 if (pItem
->flags
& ~0xda)
3905 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3907 SLTG_DoElem(pType
, pBlk
,
3908 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3910 if (TRACE_ON(typelib
)) {
3912 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3913 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3916 if (pItem
->flags
& 0x40) {
3917 TRACE_(typelib
)("VAR_DISPATCH\n");
3918 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3920 else if (pItem
->flags
& 0x10) {
3921 TRACE_(typelib
)("VAR_CONST\n");
3922 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3923 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3924 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3925 if (pItem
->flags
& 0x08)
3926 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3928 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3934 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3936 TRACE_(typelib
)("len = %u\n", len
);
3937 if (len
== 0xffff) {
3940 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3941 str
= SysAllocStringLen(NULL
, alloc_len
);
3942 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3944 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3945 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3954 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3955 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3958 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3963 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3964 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3965 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3968 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3969 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3971 if (pItem
->flags
& 0x80)
3972 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3974 prevName
= pVarDesc
->Name
;
3979 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3980 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3982 SLTG_Function
*pFunc
;
3984 TLBFuncDesc
*pFuncDesc
;
3986 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
3988 pFuncDesc
= pTI
->funcdescs
;
3989 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
3990 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
3995 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3996 case SLTG_FUNCTION_MAGIC
:
3997 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3999 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4000 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4002 case SLTG_STATIC_FUNCTION_MAGIC
:
4003 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4006 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4009 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4011 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4012 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4013 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4014 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4015 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4016 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4018 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4019 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4021 if(pFunc
->retnextopt
& 0x80)
4022 pType
= &pFunc
->rettype
;
4024 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4026 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4028 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4029 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4030 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4032 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4034 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4035 char *paramName
= pNameTable
+ *pArg
;
4037 /* If arg type follows then paramName points to the 2nd
4038 letter of the name, else the next WORD is an offset to
4039 the arg type and paramName points to the first letter.
4040 So let's take one char off paramName and see if we're
4041 pointing at an alpha-numeric char. However if *pArg is
4042 0xffff or 0xfffe then the param has no name, the former
4043 meaning that the next WORD is the type, the latter
4044 meaning that the next WORD is an offset to the type. */
4049 else if(*pArg
== 0xfffe) {
4053 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4058 if(HaveOffs
) { /* the next word is an offset to type */
4059 pType
= (WORD
*)(pBlk
+ *pArg
);
4060 SLTG_DoElem(pType
, pBlk
,
4061 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4066 pArg
= SLTG_DoElem(pArg
, pBlk
,
4067 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4070 /* Are we an optional param ? */
4071 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4072 pFuncDesc
->funcdesc
.cParamsOpt
)
4073 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4076 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4077 paramName
- pNameTable
, pTI
->pTypeLib
);
4079 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4083 pTI
->cFuncs
= cFuncs
;
4086 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4087 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4088 SLTG_TypeInfoTail
*pTITail
)
4091 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4093 if(pTIHeader
->href_table
!= 0xffffffff) {
4094 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4100 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4101 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4103 heap_free(ref_lookup
);
4107 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4108 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4109 const SLTG_TypeInfoTail
*pTITail
)
4112 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4114 if(pTIHeader
->href_table
!= 0xffffffff) {
4115 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4121 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4122 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4125 if (pTITail
->funcs_off
!= 0xffff)
4126 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4128 heap_free(ref_lookup
);
4130 if (TRACE_ON(typelib
))
4131 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4134 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4135 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4136 const SLTG_TypeInfoTail
*pTITail
)
4138 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4141 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4142 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4143 const SLTG_TypeInfoTail
*pTITail
)
4146 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4148 if (pTITail
->simple_alias
) {
4149 /* if simple alias, no more processing required */
4150 pTI
->tdescAlias
.vt
= pTITail
->tdescalias_vt
;
4154 if(pTIHeader
->href_table
!= 0xffffffff) {
4155 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4159 /* otherwise it is an offset to a type */
4160 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4162 SLTG_DoType(pType
, pBlk
, &pTI
->tdescAlias
, ref_lookup
);
4164 heap_free(ref_lookup
);
4167 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4168 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4169 const SLTG_TypeInfoTail
*pTITail
)
4171 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4172 if (pTIHeader
->href_table
!= 0xffffffff)
4173 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4176 if (pTITail
->vars_off
!= 0xffff)
4177 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4179 if (pTITail
->funcs_off
!= 0xffff)
4180 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4182 if (pTITail
->impls_off
!= 0xffff)
4183 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4185 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4186 * of dispinterface functions including the IDispatch ones, so
4187 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4188 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4190 heap_free(ref_lookup
);
4191 if (TRACE_ON(typelib
))
4192 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4195 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4196 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4197 const SLTG_TypeInfoTail
*pTITail
)
4199 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4202 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4203 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4204 const SLTG_TypeInfoTail
*pTITail
)
4206 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4207 if (pTIHeader
->href_table
!= 0xffffffff)
4208 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4211 if (pTITail
->vars_off
!= 0xffff)
4212 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4214 if (pTITail
->funcs_off
!= 0xffff)
4215 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4216 heap_free(ref_lookup
);
4217 if (TRACE_ON(typelib
))
4221 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4222 manageable copy of it into this */
4235 } SLTG_InternalOtherTypeInfo
;
4237 /****************************************************************************
4238 * ITypeLib2_Constructor_SLTG
4240 * loading a SLTG typelib from an in-memory image
4242 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4244 ITypeLibImpl
*pTypeLibImpl
;
4245 SLTG_Header
*pHeader
;
4246 SLTG_BlkEntry
*pBlkEntry
;
4250 LPVOID pBlk
, pFirstBlk
;
4251 SLTG_LibBlk
*pLibBlk
;
4252 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4253 char *pAfterOTIBlks
= NULL
;
4254 char *pNameTable
, *ptr
;
4257 ITypeInfoImpl
**ppTypeInfoImpl
;
4259 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4262 pTypeLibImpl
= TypeLibImpl_Constructor();
4263 if (!pTypeLibImpl
) return NULL
;
4267 TRACE_(typelib
)("header:\n");
4268 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4269 pHeader
->nrOfFileBlks
);
4270 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4271 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4272 pHeader
->SLTG_magic
);
4276 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4277 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4279 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4280 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4282 /* Next we have a magic block */
4283 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4285 /* Let's see if we're still in sync */
4286 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4287 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4288 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4291 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4292 sizeof(SLTG_DIR_MAGIC
))) {
4293 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4297 pIndex
= (SLTG_Index
*)(pMagic
+1);
4299 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4301 pFirstBlk
= pPad9
+ 1;
4303 /* We'll set up a ptr to the main library block, which is the last one. */
4305 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4306 pBlkEntry
[order
].next
!= 0;
4307 order
= pBlkEntry
[order
].next
- 1, i
++) {
4308 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4312 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4314 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4319 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4321 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4324 ptr
= (char*)pLibBlk
+ len
;
4326 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4330 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4332 w
= *(WORD
*)(ptr
+ 2);
4335 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4336 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4337 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4339 w
= *(WORD
*)(ptr
+ 4 + len
);
4341 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4343 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4344 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4345 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4347 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4348 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4349 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4351 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4352 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4355 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4356 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4357 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4358 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4359 len
+= sizeof(SLTG_OtherTypeInfo
);
4363 pAfterOTIBlks
= ptr
;
4365 /* Skip this WORD and get the next DWORD */
4366 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4368 /* Now add this to pLibBLk look at what we're pointing at and
4369 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4370 dust and we should be pointing at the beginning of the name
4373 pNameTable
= (char*)pLibBlk
+ len
;
4375 switch(*(WORD
*)pNameTable
) {
4382 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4386 pNameTable
+= 0x216;
4390 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4392 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4395 /* Hopefully we now have enough ptrs set up to actually read in
4396 some TypeInfos. It's not clear which order to do them in, so
4397 I'll just follow the links along the BlkEntry chain and read
4398 them in the order in which they are in the file */
4400 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4401 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4403 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4404 pBlkEntry
[order
].next
!= 0;
4405 order
= pBlkEntry
[order
].next
- 1, i
++) {
4407 SLTG_TypeInfoHeader
*pTIHeader
;
4408 SLTG_TypeInfoTail
*pTITail
;
4409 SLTG_MemberHeader
*pMemHeader
;
4411 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4412 FIXME_(typelib
)("Index strings don't match\n");
4413 heap_free(pOtherTypeInfoBlks
);
4418 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4419 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4420 heap_free(pOtherTypeInfoBlks
);
4423 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4424 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4425 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4427 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4428 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4429 (*ppTypeInfoImpl
)->index
= i
;
4430 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4431 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4432 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4433 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4434 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4435 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4436 (*ppTypeInfoImpl
)->wTypeFlags
=
4437 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4439 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4440 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4442 if((pTIHeader
->typeflags1
& 7) != 2)
4443 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4444 if(pTIHeader
->typeflags3
!= 2)
4445 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4447 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4448 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4449 typekind_desc
[pTIHeader
->typekind
],
4450 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4451 (*ppTypeInfoImpl
)->wTypeFlags
);
4453 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4455 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4457 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4458 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4459 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4461 switch(pTIHeader
->typekind
) {
4463 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4464 pTIHeader
, pTITail
);
4468 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4469 pTIHeader
, pTITail
);
4472 case TKIND_INTERFACE
:
4473 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4474 pTIHeader
, pTITail
);
4478 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4479 pTIHeader
, pTITail
);
4483 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4484 pTIHeader
, pTITail
);
4487 case TKIND_DISPATCH
:
4488 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4489 pTIHeader
, pTITail
);
4493 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4494 pTIHeader
, pTITail
);
4498 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4503 /* could get cFuncs, cVars and cImplTypes from here
4504 but we've already set those */
4505 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4521 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4524 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4525 FIXME("Somehow processed %d TypeInfos\n", i
);
4526 heap_free(pOtherTypeInfoBlks
);
4530 heap_free(pOtherTypeInfoBlks
);
4531 return &pTypeLibImpl
->ITypeLib2_iface
;
4534 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4536 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4538 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4540 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4541 IsEqualIID(riid
,&IID_ITypeLib
)||
4542 IsEqualIID(riid
,&IID_ITypeLib2
))
4544 *ppv
= &This
->ITypeLib2_iface
;
4546 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4547 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4549 *ppv
= &This
->ICreateTypeLib2_iface
;
4554 TRACE("-- Interface: E_NOINTERFACE\n");
4555 return E_NOINTERFACE
;
4558 IUnknown_AddRef((IUnknown
*)*ppv
);
4562 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4564 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4565 ULONG ref
= InterlockedIncrement(&This
->ref
);
4567 TRACE("(%p) ref=%u\n", This
, ref
);
4572 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4574 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4575 ULONG ref
= InterlockedDecrement(&This
->ref
);
4577 TRACE("(%p) ref=%u\n",This
, ref
);
4581 TLBImpLib
*pImpLib
, *pImpLibNext
;
4582 TLBRefType
*ref_type
;
4583 TLBString
*tlbstr
, *tlbstr_next
;
4584 TLBGuid
*tlbguid
, *tlbguid_next
;
4588 /* remove cache entry */
4591 TRACE("removing from cache list\n");
4592 EnterCriticalSection(&cache_section
);
4593 if(This
->entry
.next
)
4594 list_remove(&This
->entry
);
4595 LeaveCriticalSection(&cache_section
);
4596 heap_free(This
->path
);
4598 TRACE(" destroying ITypeLib(%p)\n",This
);
4600 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4601 list_remove(&tlbstr
->entry
);
4602 SysFreeString(tlbstr
->str
);
4606 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4607 list_remove(&tlbstr
->entry
);
4608 SysFreeString(tlbstr
->str
);
4612 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4613 list_remove(&tlbguid
->entry
);
4617 TLB_FreeCustData(&This
->custdata_list
);
4619 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4620 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4621 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4623 heap_free(This
->pTypeDesc
);
4625 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4627 if (pImpLib
->pImpTypeLib
)
4628 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4629 SysFreeString(pImpLib
->name
);
4631 list_remove(&pImpLib
->entry
);
4635 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4637 list_remove(&ref_type
->entry
);
4638 heap_free(ref_type
);
4641 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4642 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4643 heap_free(This
->typeinfos
);
4651 /* ITypeLib::GetTypeInfoCount
4653 * Returns the number of type descriptions in the type library
4655 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4657 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4658 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4659 return This
->TypeInfoCount
;
4662 /* ITypeLib::GetTypeInfo
4664 * retrieves the specified type description in the library.
4666 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4669 ITypeInfo
**ppTInfo
)
4671 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4673 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4676 return E_INVALIDARG
;
4678 if(index
>= This
->TypeInfoCount
)
4679 return TYPE_E_ELEMENTNOTFOUND
;
4681 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4682 ITypeInfo_AddRef(*ppTInfo
);
4688 /* ITypeLibs::GetTypeInfoType
4690 * Retrieves the type of a type description.
4692 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4697 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4699 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4702 return E_INVALIDARG
;
4704 if(index
>= This
->TypeInfoCount
)
4705 return TYPE_E_ELEMENTNOTFOUND
;
4707 *pTKind
= This
->typeinfos
[index
]->typekind
;
4712 /* ITypeLib::GetTypeInfoOfGuid
4714 * Retrieves the type description that corresponds to the specified GUID.
4717 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4720 ITypeInfo
**ppTInfo
)
4722 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4725 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4727 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4728 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4729 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4730 ITypeInfo_AddRef(*ppTInfo
);
4735 return TYPE_E_ELEMENTNOTFOUND
;
4738 /* ITypeLib::GetLibAttr
4740 * Retrieves the structure that contains the library's attributes.
4743 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4747 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4749 TRACE("(%p, %p)\n", This
, attr
);
4751 if (!attr
) return E_INVALIDARG
;
4753 *attr
= heap_alloc(sizeof(**attr
));
4754 if (!*attr
) return E_OUTOFMEMORY
;
4756 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4757 (*attr
)->lcid
= This
->set_lcid
;
4758 (*attr
)->syskind
= This
->syskind
;
4759 (*attr
)->wMajorVerNum
= This
->ver_major
;
4760 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4761 (*attr
)->wLibFlags
= This
->libflags
;
4766 /* ITypeLib::GetTypeComp
4768 * Enables a client compiler to bind to a library's types, variables,
4769 * constants, and global functions.
4772 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4774 ITypeComp
**ppTComp
)
4776 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4778 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4779 *ppTComp
= &This
->ITypeComp_iface
;
4780 ITypeComp_AddRef(*ppTComp
);
4785 /* ITypeLib::GetDocumentation
4787 * Retrieves the library's documentation string, the complete Help file name
4788 * and path, and the context identifier for the library Help topic in the Help
4791 * On a successful return all non-null BSTR pointers will have been set,
4794 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4798 BSTR
*pBstrDocString
,
4799 DWORD
*pdwHelpContext
,
4800 BSTR
*pBstrHelpFile
)
4802 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4803 HRESULT result
= E_INVALIDARG
;
4806 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4808 pBstrName
, pBstrDocString
,
4809 pdwHelpContext
, pBstrHelpFile
);
4813 /* documentation for the typelib */
4818 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4826 if (This
->DocString
)
4828 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4832 *pBstrDocString
= NULL
;
4836 *pdwHelpContext
= This
->dwHelpContext
;
4842 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4846 *pBstrHelpFile
= NULL
;
4853 /* for a typeinfo */
4854 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4856 if(SUCCEEDED(result
))
4858 result
= ITypeInfo_GetDocumentation(pTInfo
,
4862 pdwHelpContext
, pBstrHelpFile
);
4864 ITypeInfo_Release(pTInfo
);
4869 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4871 if (pBstrName
) SysFreeString (*pBstrName
);
4873 return STG_E_INSUFFICIENTMEMORY
;
4878 * Indicates whether a passed-in string contains the name of a type or member
4879 * described in the library.
4882 static HRESULT WINAPI
ITypeLib2_fnIsName(
4888 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4890 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
4892 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4896 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4897 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4898 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4899 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
4900 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4902 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4903 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
4904 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4905 goto ITypeLib2_fnIsName_exit
;
4908 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
4909 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4910 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4916 ITypeLib2_fnIsName_exit
:
4917 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4918 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4923 /* ITypeLib::FindName
4925 * Finds occurrences of a type description in a type library. This may be used
4926 * to quickly verify that a name exists in a type library.
4929 static HRESULT WINAPI
ITypeLib2_fnFindName(
4933 ITypeInfo
**ppTInfo
,
4937 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4942 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
4944 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
4945 return E_INVALIDARG
;
4947 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
4948 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
4949 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4953 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4954 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
4955 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
4958 if(!TLB_str_memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4959 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
4960 if(!TLB_str_memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
4961 goto ITypeLib2_fnFindName_exit
;
4965 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
4967 goto ITypeLib2_fnFindName_exit
;
4970 ITypeLib2_fnFindName_exit
:
4971 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
4972 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
4975 TRACE("found %d typeinfos\n", count
);
4982 /* ITypeLib::ReleaseTLibAttr
4984 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4987 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4989 TLIBATTR
*pTLibAttr
)
4991 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4992 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
4993 heap_free(pTLibAttr
);
4996 /* ITypeLib2::GetCustData
4998 * gets the custom data
5000 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5005 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5006 TLBCustData
*pCData
;
5008 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5010 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5012 return TYPE_E_ELEMENTNOTFOUND
;
5014 VariantInit(pVarVal
);
5015 VariantCopy(pVarVal
, &pCData
->data
);
5020 /* ITypeLib2::GetLibStatistics
5022 * Returns statistics about a type library that are required for efficient
5023 * sizing of hash tables.
5026 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5028 ULONG
*pcUniqueNames
,
5029 ULONG
*pcchUniqueNames
)
5031 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5033 FIXME("(%p): stub!\n", This
);
5035 if(pcUniqueNames
) *pcUniqueNames
=1;
5036 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5040 /* ITypeLib2::GetDocumentation2
5042 * Retrieves the library's documentation string, the complete Help file name
5043 * and path, the localization context to use, and the context ID for the
5044 * library Help topic in the Help file.
5047 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5051 BSTR
*pbstrHelpString
,
5052 DWORD
*pdwHelpStringContext
,
5053 BSTR
*pbstrHelpStringDll
)
5055 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5059 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5061 /* the help string should be obtained from the helpstringdll,
5062 * using the _DLLGetDocumentation function, based on the supplied
5063 * lcid. Nice to do sometime...
5067 /* documentation for the typelib */
5069 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5070 if(pdwHelpStringContext
)
5071 *pdwHelpStringContext
=This
->dwHelpContext
;
5072 if(pbstrHelpStringDll
)
5073 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5079 /* for a typeinfo */
5080 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5082 if(SUCCEEDED(result
))
5084 ITypeInfo2
* pTInfo2
;
5085 result
= ITypeInfo_QueryInterface(pTInfo
,
5087 (LPVOID
*) &pTInfo2
);
5089 if(SUCCEEDED(result
))
5091 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5095 pdwHelpStringContext
,
5096 pbstrHelpStringDll
);
5098 ITypeInfo2_Release(pTInfo2
);
5101 ITypeInfo_Release(pTInfo
);
5107 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5109 TLBCustData
*pCData
;
5113 ct
= list_count(custdata_list
);
5115 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
5116 if(!pCustData
->prgCustData
)
5117 return E_OUTOFMEMORY
;
5119 pCustData
->cCustData
= ct
;
5121 cdi
= pCustData
->prgCustData
;
5122 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5123 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5124 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5132 /* ITypeLib2::GetAllCustData
5134 * Gets all custom data items for the library.
5137 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5139 CUSTDATA
*pCustData
)
5141 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5142 TRACE("(%p)->(%p)\n", This
, pCustData
);
5143 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5146 static const ITypeLib2Vtbl tlbvt
= {
5147 ITypeLib2_fnQueryInterface
,
5149 ITypeLib2_fnRelease
,
5150 ITypeLib2_fnGetTypeInfoCount
,
5151 ITypeLib2_fnGetTypeInfo
,
5152 ITypeLib2_fnGetTypeInfoType
,
5153 ITypeLib2_fnGetTypeInfoOfGuid
,
5154 ITypeLib2_fnGetLibAttr
,
5155 ITypeLib2_fnGetTypeComp
,
5156 ITypeLib2_fnGetDocumentation
,
5158 ITypeLib2_fnFindName
,
5159 ITypeLib2_fnReleaseTLibAttr
,
5161 ITypeLib2_fnGetCustData
,
5162 ITypeLib2_fnGetLibStatistics
,
5163 ITypeLib2_fnGetDocumentation2
,
5164 ITypeLib2_fnGetAllCustData
5168 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5170 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5172 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5175 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5177 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5179 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5182 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5184 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5186 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5189 static HRESULT WINAPI
ITypeLibComp_fnBind(
5194 ITypeInfo
** ppTInfo
,
5195 DESCKIND
* pDescKind
,
5198 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5199 int typemismatch
=0, i
;
5201 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5203 *pDescKind
= DESCKIND_NONE
;
5204 pBindPtr
->lptcomp
= NULL
;
5207 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5208 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5209 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5211 /* FIXME: check wFlags here? */
5212 /* FIXME: we should use a hash table to look this info up using lHash
5213 * instead of an O(n) search */
5214 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5215 (pTypeInfo
->typekind
== TKIND_MODULE
))
5217 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5219 *pDescKind
= DESCKIND_TYPECOMP
;
5220 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5221 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5222 TRACE("module or enum: %s\n", debugstr_w(szName
));
5227 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5228 (pTypeInfo
->typekind
== TKIND_ENUM
))
5230 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5233 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5234 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5236 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5239 else if (hr
== TYPE_E_TYPEMISMATCH
)
5243 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5244 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5246 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5248 ITypeInfo
*subtypeinfo
;
5250 DESCKIND subdesckind
;
5252 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5253 &subtypeinfo
, &subdesckind
, &subbindptr
);
5254 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5256 TYPEDESC tdesc_appobject
;
5257 const VARDESC vardesc_appobject
=
5260 NULL
, /* lpstrSchema */
5275 VAR_STATIC
/* varkind */
5278 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5279 tdesc_appobject
.vt
= VT_USERDEFINED
;
5281 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5283 /* cleanup things filled in by Bind call so we can put our
5284 * application object data in there instead */
5285 switch (subdesckind
)
5287 case DESCKIND_FUNCDESC
:
5288 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5290 case DESCKIND_VARDESC
:
5291 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5296 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5298 if (pTypeInfo
->hreftype
== -1)
5299 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5301 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5305 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5306 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5307 ITypeInfo_AddRef(*ppTInfo
);
5310 else if (hr
== TYPE_E_TYPEMISMATCH
)
5317 TRACE("type mismatch %s\n", debugstr_w(szName
));
5318 return TYPE_E_TYPEMISMATCH
;
5322 TRACE("name not found %s\n", debugstr_w(szName
));
5327 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5331 ITypeInfo
** ppTInfo
,
5332 ITypeComp
** ppTComp
)
5334 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5335 ITypeInfoImpl
*info
;
5337 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5339 if(!szName
|| !ppTInfo
|| !ppTComp
)
5340 return E_INVALIDARG
;
5342 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5349 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5350 ITypeInfo_AddRef(*ppTInfo
);
5351 *ppTComp
= &info
->ITypeComp_iface
;
5352 ITypeComp_AddRef(*ppTComp
);
5357 static const ITypeCompVtbl tlbtcvt
=
5360 ITypeLibComp_fnQueryInterface
,
5361 ITypeLibComp_fnAddRef
,
5362 ITypeLibComp_fnRelease
,
5364 ITypeLibComp_fnBind
,
5365 ITypeLibComp_fnBindType
5368 /*================== ITypeInfo(2) Methods ===================================*/
5369 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5371 ITypeInfoImpl
*pTypeInfoImpl
;
5373 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5376 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5377 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5378 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5379 pTypeInfoImpl
->ref
= 0;
5380 pTypeInfoImpl
->hreftype
= -1;
5381 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5382 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5383 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5384 list_init(pTypeInfoImpl
->pcustdata_list
);
5386 TRACE("(%p)\n", pTypeInfoImpl
);
5387 return pTypeInfoImpl
;
5390 /* ITypeInfo::QueryInterface
5392 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5397 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5399 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5402 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5403 IsEqualIID(riid
,&IID_ITypeInfo
)||
5404 IsEqualIID(riid
,&IID_ITypeInfo2
))
5406 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5407 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5408 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5411 ITypeInfo2_AddRef(iface
);
5412 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5415 TRACE("-- Interface: E_NOINTERFACE\n");
5416 return E_NOINTERFACE
;
5419 /* ITypeInfo::AddRef
5421 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5423 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5424 ULONG ref
= InterlockedIncrement(&This
->ref
);
5426 TRACE("(%p)->ref is %u\n",This
, ref
);
5428 if (ref
== 1 /* incremented from 0 */)
5429 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5434 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5438 TRACE("destroying ITypeInfo(%p)\n",This
);
5440 for (i
= 0; i
< This
->cFuncs
; ++i
)
5443 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5444 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5446 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5447 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5448 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5449 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5451 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5452 heap_free(pFInfo
->pParamDesc
);
5453 TLB_FreeCustData(&pFInfo
->custdata_list
);
5455 heap_free(This
->funcdescs
);
5457 for(i
= 0; i
< This
->cVars
; ++i
)
5459 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5460 if (pVInfo
->vardesc_create
) {
5461 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5462 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5463 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5464 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5466 TLB_FreeCustData(&pVInfo
->custdata_list
);
5468 heap_free(This
->vardescs
);
5470 if(This
->impltypes
){
5471 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5472 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5473 TLB_FreeCustData(&pImpl
->custdata_list
);
5475 heap_free(This
->impltypes
);
5478 TLB_FreeCustData(&This
->custdata_list
);
5483 /* ITypeInfo::Release
5485 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5487 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5488 ULONG ref
= InterlockedDecrement(&This
->ref
);
5490 TRACE("(%p)->(%u)\n",This
, ref
);
5494 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5495 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5496 if (not_attached_to_typelib
)
5498 /* otherwise This will be freed when typelib is freed */
5504 /* ITypeInfo::GetTypeAttr
5506 * Retrieves a TYPEATTR structure that contains the attributes of the type
5510 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5511 LPTYPEATTR
*ppTypeAttr
)
5513 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5516 TRACE("(%p)\n",This
);
5518 size
= sizeof(**ppTypeAttr
);
5519 if (This
->typekind
== TKIND_ALIAS
)
5520 size
+= TLB_SizeTypeDesc(&This
->tdescAlias
, FALSE
);
5522 *ppTypeAttr
= heap_alloc(size
);
5524 return E_OUTOFMEMORY
;
5526 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5527 (*ppTypeAttr
)->lcid
= This
->lcid
;
5528 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5529 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5530 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5531 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5532 (*ppTypeAttr
)->typekind
= This
->typekind
;
5533 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5534 (*ppTypeAttr
)->cVars
= This
->cVars
;
5535 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5536 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5537 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5538 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5539 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5540 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5541 (*ppTypeAttr
)->tdescAlias
= This
->tdescAlias
;
5542 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5544 if (This
->typekind
== TKIND_ALIAS
)
5545 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5546 &This
->tdescAlias
, *ppTypeAttr
+ 1);
5548 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5549 /* This should include all the inherited funcs */
5550 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5551 /* This is always the size of IDispatch's vtbl */
5552 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5553 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5558 /* ITypeInfo::GetTypeComp
5560 * Retrieves the ITypeComp interface for the type description, which enables a
5561 * client compiler to bind to the type description's members.
5564 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5565 ITypeComp
* *ppTComp
)
5567 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5569 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5571 *ppTComp
= &This
->ITypeComp_iface
;
5572 ITypeComp_AddRef(*ppTComp
);
5576 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5578 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5579 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5580 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5584 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5587 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5588 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5590 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5591 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5592 *buffer
+= sizeof(PARAMDESCEX
);
5593 *pparamdescex_dest
= *pparamdescex_src
;
5594 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5595 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5596 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5597 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5600 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5604 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5606 UINT len
= SysStringLen(str
), i
;
5607 for (i
= 0; i
< len
; ++i
)
5613 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5615 if (V_VT(var
) == VT_INT
)
5616 return VariantChangeType(var
, var
, 0, VT_I4
);
5617 else if (V_VT(var
) == VT_UINT
)
5618 return VariantChangeType(var
, var
, 0, VT_UI4
);
5619 else if (V_VT(var
) == VT_BSTR
)
5620 return TLB_SanitizeBSTR(V_BSTR(var
));
5625 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5627 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5628 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5631 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5635 SIZE_T size
= sizeof(*src
);
5639 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5640 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5641 for (i
= 0; i
< src
->cParams
; i
++)
5643 size
+= sizeof(ELEMDESC
);
5644 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5647 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5648 if (!dest
) return E_OUTOFMEMORY
;
5651 if (dispinterface
) /* overwrite funckind */
5652 dest
->funckind
= FUNC_DISPATCH
;
5653 buffer
= (char *)(dest
+ 1);
5655 dest
->oVft
= dest
->oVft
& 0xFFFC;
5657 if (dest
->cScodes
) {
5658 dest
->lprgscode
= (SCODE
*)buffer
;
5659 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5660 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5662 dest
->lprgscode
= NULL
;
5664 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5667 SysFreeString((BSTR
)dest
);
5671 if (dest
->cParams
) {
5672 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5673 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5674 for (i
= 0; i
< src
->cParams
; i
++)
5676 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5682 /* undo the above actions */
5683 for (i
= i
- 1; i
>= 0; i
--)
5684 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5685 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5686 SysFreeString((BSTR
)dest
);
5690 dest
->lprgelemdescParam
= NULL
;
5692 /* special treatment for dispinterfaces: this makes functions appear
5693 * to return their [retval] value when it is really returning an
5695 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5697 if (dest
->cParams
&&
5698 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5700 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5701 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5703 ERR("elemdesc should have started with VT_PTR instead of:\n");
5705 dump_ELEMDESC(elemdesc
);
5706 return E_UNEXPECTED
;
5709 /* copy last parameter to the return value. we are using a flat
5710 * buffer so there is no danger of leaking memory in
5712 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5714 /* remove the last parameter */
5718 /* otherwise this function is made to appear to have no return
5720 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5728 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5730 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5731 if (var_desc
->varkind
== VAR_CONST
)
5732 VariantClear(var_desc
->u
.lpvarValue
);
5733 SysFreeString((BSTR
)var_desc
);
5736 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5738 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5740 if (index
>= This
->cFuncs
)
5741 return TYPE_E_ELEMENTNOTFOUND
;
5743 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5747 /* internal function to make the inherited interfaces' methods appear
5748 * part of the interface */
5749 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5750 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5752 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5754 UINT implemented_funcs
= 0;
5759 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5763 ITypeInfo
*pSubTypeInfo
;
5766 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5770 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5773 &sub_funcs
, hrefoffset
);
5774 implemented_funcs
+= sub_funcs
;
5775 ITypeInfo_Release(pSubTypeInfo
);
5778 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5782 *funcs
= implemented_funcs
+ This
->cFuncs
;
5786 if (index
< implemented_funcs
)
5787 return E_INVALIDARG
;
5788 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5792 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5794 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5797 switch (pTypeDesc
->vt
)
5799 case VT_USERDEFINED
:
5800 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5804 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5807 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5815 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5818 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5819 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5820 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5823 /* ITypeInfo::GetFuncDesc
5825 * Retrieves the FUNCDESC structure that contains information about a
5826 * specified function.
5829 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5830 LPFUNCDESC
*ppFuncDesc
)
5832 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5833 const FUNCDESC
*internal_funcdesc
;
5835 UINT hrefoffset
= 0;
5837 TRACE("(%p) index %d\n", This
, index
);
5840 return E_INVALIDARG
;
5842 if (This
->needs_layout
)
5843 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5845 if (This
->typekind
== TKIND_DISPATCH
)
5846 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5847 &internal_funcdesc
, NULL
,
5850 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5851 &internal_funcdesc
);
5854 WARN("description for function %d not found\n", index
);
5858 hr
= TLB_AllocAndInitFuncDesc(
5861 This
->typekind
== TKIND_DISPATCH
);
5863 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
5864 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5866 TRACE("-- 0x%08x\n", hr
);
5870 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5874 SIZE_T size
= sizeof(*src
);
5877 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5878 if (src
->varkind
== VAR_CONST
)
5879 size
+= sizeof(VARIANT
);
5880 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5882 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5883 if (!dest
) return E_OUTOFMEMORY
;
5886 buffer
= (char *)(dest
+ 1);
5887 if (src
->lpstrSchema
)
5890 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5891 len
= strlenW(src
->lpstrSchema
);
5892 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5893 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5896 if (src
->varkind
== VAR_CONST
)
5900 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5901 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5902 buffer
+= sizeof(VARIANT
);
5903 VariantInit(dest
->u
.lpvarValue
);
5904 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5907 SysFreeString((BSTR
)dest
);
5911 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5914 if (src
->varkind
== VAR_CONST
)
5915 VariantClear(dest
->u
.lpvarValue
);
5916 SysFreeString((BSTR
)dest
);
5923 /* ITypeInfo::GetVarDesc
5925 * Retrieves a VARDESC structure that describes the specified variable.
5928 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5929 LPVARDESC
*ppVarDesc
)
5931 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5932 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5934 TRACE("(%p) index %d\n", This
, index
);
5936 if(index
>= This
->cVars
)
5937 return TYPE_E_ELEMENTNOTFOUND
;
5939 if (This
->needs_layout
)
5940 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5942 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5945 /* ITypeInfo_GetNames
5947 * Retrieves the variable with the specified member ID (or the name of the
5948 * property or method and its parameters) that correspond to the specified
5951 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5952 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5954 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5955 const TLBFuncDesc
*pFDesc
;
5956 const TLBVarDesc
*pVDesc
;
5958 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5961 return E_INVALIDARG
;
5965 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
5968 if(!cMaxNames
|| !pFDesc
->Name
)
5971 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
5974 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
5975 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
5977 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
5983 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
5986 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
5991 if(This
->impltypes
&&
5992 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
5993 /* recursive search */
5996 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5997 if(SUCCEEDED(result
))
5999 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6000 ITypeInfo_Release(pTInfo
);
6003 WARN("Could not search inherited interface!\n");
6007 WARN("no names found\n");
6010 return TYPE_E_ELEMENTNOTFOUND
;
6016 /* ITypeInfo::GetRefTypeOfImplType
6018 * If a type description describes a COM class, it retrieves the type
6019 * description of the implemented interface types. For an interface,
6020 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6024 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6029 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6032 TRACE("(%p) index %d\n", This
, index
);
6033 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6037 /* only valid on dual interfaces;
6038 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6041 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6047 hr
= TYPE_E_ELEMENTNOTFOUND
;
6050 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6052 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6053 *pRefType
= This
->pTypeLib
->dispatch_href
;
6057 if(index
>= This
->cImplTypes
)
6058 hr
= TYPE_E_ELEMENTNOTFOUND
;
6060 *pRefType
= This
->impltypes
[index
].hRef
;
6061 if(This
->typekind
== TKIND_INTERFACE
)
6069 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6071 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6077 /* ITypeInfo::GetImplTypeFlags
6079 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6080 * or base interface in a type description.
6082 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6083 UINT index
, INT
*pImplTypeFlags
)
6085 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6087 TRACE("(%p) index %d\n", This
, index
);
6090 return E_INVALIDARG
;
6092 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6093 *pImplTypeFlags
= 0;
6097 if(index
>= This
->cImplTypes
)
6098 return TYPE_E_ELEMENTNOTFOUND
;
6100 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6106 * Maps between member names and member IDs, and parameter names and
6109 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6110 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6112 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6113 const TLBVarDesc
*pVDesc
;
6117 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6120 /* init out parameters in case of failure */
6121 for (i
= 0; i
< cNames
; i
++)
6122 pMemId
[i
] = MEMBERID_NIL
;
6124 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6126 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6127 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6128 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6129 for(i
=1; i
< cNames
; i
++){
6130 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6131 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6133 if( j
<pFDesc
->funcdesc
.cParams
)
6136 ret
=DISP_E_UNKNOWNNAME
;
6138 TRACE("-- 0x%08x\n", ret
);
6142 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6145 *pMemId
= pVDesc
->vardesc
.memid
;
6148 /* not found, see if it can be found in an inherited interface */
6149 if(This
->impltypes
) {
6150 /* recursive search */
6152 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6154 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6155 ITypeInfo_Release(pTInfo
);
6158 WARN("Could not search inherited interface!\n");
6160 WARN("no names found\n");
6161 return DISP_E_UNKNOWNNAME
;
6167 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6168 __ASM_GLOBAL_FUNC( call_method
,
6170 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6171 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6172 "movl %esp,%ebp\n\t"
6173 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6175 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6177 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6178 "movl 12(%ebp),%edx\n\t"
6179 "movl %esp,%edi\n\t"
6182 "subl %edx,%edi\n\t"
6183 "andl $~15,%edi\n\t"
6184 "movl %edi,%esp\n\t"
6185 "movl 12(%ebp),%ecx\n\t"
6186 "movl 16(%ebp),%esi\n\t"
6189 "1:\tcall *8(%ebp)\n\t"
6190 "subl %esp,%edi\n\t"
6191 "movl 20(%ebp),%ecx\n\t"
6192 "movl %edi,(%ecx)\n\t"
6193 "leal -8(%ebp),%esp\n\t"
6195 __ASM_CFI(".cfi_same_value %edi\n\t")
6197 __ASM_CFI(".cfi_same_value %esi\n\t")
6199 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6200 __ASM_CFI(".cfi_same_value %ebp\n\t")
6203 /* same function but returning floating point */
6204 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6206 /* ITypeInfo::Invoke
6208 * Invokes a method, or accesses a property of an object, that implements the
6209 * interface described by the type description.
6212 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6216 if (TRACE_ON(ole
)) {
6218 TRACE("Calling %p(",func
);
6219 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6220 if (nrargs
> 30) TRACE("...");
6227 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6230 FIXME("unsupported calling convention %d\n",callconv
);
6234 TRACE("returns %08x\n",res
);
6238 #elif defined(__x86_64__)
6240 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6241 __ASM_GLOBAL_FUNC( call_method
,
6243 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6244 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6245 "movq %rsp,%rbp\n\t"
6246 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6248 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6250 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6251 "movq %rcx,%rax\n\t"
6254 "cmovgq %rdx,%rcx\n\t"
6255 "leaq 0(,%rcx,8),%rdx\n\t"
6256 "subq %rdx,%rsp\n\t"
6257 "andq $~15,%rsp\n\t"
6258 "movq %rsp,%rdi\n\t"
6261 "movq 0(%rsp),%rcx\n\t"
6262 "movq 8(%rsp),%rdx\n\t"
6263 "movq 16(%rsp),%r8\n\t"
6264 "movq 24(%rsp),%r9\n\t"
6265 "movq %rcx,%xmm0\n\t"
6266 "movq %rdx,%xmm1\n\t"
6267 "movq %r8,%xmm2\n\t"
6268 "movq %r9,%xmm3\n\t"
6270 "leaq -16(%rbp),%rsp\n\t"
6272 __ASM_CFI(".cfi_same_value %rdi\n\t")
6274 __ASM_CFI(".cfi_same_value %rsi\n\t")
6275 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6277 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6278 __ASM_CFI(".cfi_same_value %rbp\n\t")
6281 /* same function but returning floating point */
6282 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6284 #endif /* __x86_64__ */
6286 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6289 ITypeInfo
*tinfo2
= NULL
;
6290 TYPEATTR
*tattr
= NULL
;
6292 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6295 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6297 tdesc
->u
.hreftype
, hr
);
6300 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6303 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6304 ITypeInfo_Release(tinfo2
);
6308 switch (tattr
->typekind
)
6315 tdesc
= &tattr
->tdescAlias
;
6316 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6319 case TKIND_INTERFACE
:
6320 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6326 case TKIND_DISPATCH
:
6335 FIXME("TKIND_RECORD unhandled.\n");
6340 FIXME("TKIND_UNION unhandled.\n");
6345 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6349 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6350 ITypeInfo_Release(tinfo2
);
6354 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6358 /* enforce only one level of pointer indirection */
6359 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6361 tdesc
= tdesc
->u
.lptdesc
;
6363 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6364 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6365 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6366 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6367 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6369 VARTYPE vt_userdefined
= 0;
6370 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6371 if (tdesc
->vt
== VT_PTR
)
6373 vt_userdefined
= VT_BYREF
;
6374 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6376 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6378 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6379 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6381 *vt
|= vt_userdefined
;
6393 case VT_USERDEFINED
:
6394 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6401 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6402 hr
= DISP_E_BADVARTYPE
;
6406 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6421 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6427 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6431 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6433 ITypeInfo_Release(tinfo2
);
6437 switch(tattr
->typekind
) {
6439 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6442 case TKIND_INTERFACE
:
6443 case TKIND_DISPATCH
:
6444 *guid
= tattr
->guid
;
6448 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6449 hres
= E_UNEXPECTED
;
6452 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6453 ITypeInfo_Release(tinfo2
);
6457 /***********************************************************************
6458 * DispCallFunc (OLEAUT32.@)
6460 * Invokes a function of the specified calling convention, passing the
6461 * specified arguments and returns the result.
6464 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6465 * oVft [I] The offset in the vtable. See notes.
6466 * cc [I] Calling convention of the function to call.
6467 * vtReturn [I] The return type of the function.
6468 * cActuals [I] Number of parameters.
6469 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6470 * prgpvarg [I] The arguments to pass.
6471 * pvargResult [O] The return value of the function. Can be NULL.
6475 * Failure: HRESULT code.
6478 * The HRESULT return value of this function is not affected by the return
6479 * value of the user supplied function, which is returned in pvargResult.
6481 * If pvInstance is NULL then a non-object function is to be called and oVft
6482 * is the address of the function to call.
6484 * The cc parameter can be one of the following values:
6497 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6498 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6501 int argspos
, stack_offset
;
6506 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6507 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6508 pvargResult
, V_VT(pvargResult
));
6510 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6512 FIXME("unsupported calling convention %d\n",cc
);
6513 return E_INVALIDARG
;
6516 /* maximum size for an argument is sizeof(VARIANT) */
6517 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6519 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6523 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6524 func
= vtable
[oVft
/sizeof(void *)];
6525 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6527 else func
= (void *)oVft
;
6529 for (i
= 0; i
< cActuals
; i
++)
6531 VARIANT
*arg
= prgpvarg
[i
];
6542 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6543 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6547 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6548 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6550 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6551 args
[argspos
++] = V_BOOL(arg
);
6554 args
[argspos
++] = V_UI4(arg
);
6557 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6564 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6567 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6571 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6575 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6576 call_method( func
, argspos
, args
, &stack_offset
);
6581 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6584 WARN("invalid return type %u\n", vtReturn
);
6586 return E_INVALIDARG
;
6588 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6592 if (stack_offset
&& cc
== CC_STDCALL
)
6594 WARN( "stack pointer off by %d\n", stack_offset
);
6595 return DISP_E_BADCALLEE
;
6597 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6598 TRACE("retval: "); dump_Variant(pvargResult
);
6601 #elif defined(__x86_64__)
6607 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6608 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6609 pvargResult
, V_VT(pvargResult
));
6611 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6613 FIXME("unsupported calling convention %d\n",cc
);
6614 return E_INVALIDARG
;
6617 /* maximum size for an argument is sizeof(DWORD_PTR) */
6618 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6620 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6624 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6625 func
= vtable
[oVft
/sizeof(void *)];
6626 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6628 else func
= (void *)oVft
;
6630 for (i
= 0; i
< cActuals
; i
++)
6632 VARIANT
*arg
= prgpvarg
[i
];
6638 args
[argspos
++] = (ULONG_PTR
)arg
;
6640 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6641 args
[argspos
++] = V_BOOL(arg
);
6644 args
[argspos
++] = V_UI8(arg
);
6647 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6654 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6658 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6662 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6663 call_method( func
, argspos
, args
);
6666 WARN("invalid return type %u\n", vtReturn
);
6668 return E_INVALIDARG
;
6670 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6674 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6675 TRACE("retval: "); dump_Variant(pvargResult
);
6679 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6680 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6685 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6687 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6690 #define INVBUF_ELEMENT_SIZE \
6691 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6692 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6693 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6694 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6695 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6696 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6697 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6698 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6700 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6705 DISPPARAMS
*pDispParams
,
6706 VARIANT
*pVarResult
,
6707 EXCEPINFO
*pExcepInfo
,
6710 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6712 unsigned int var_index
;
6715 const TLBFuncDesc
*pFuncInfo
;
6718 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6719 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6722 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6723 return DISP_E_MEMBERNOTFOUND
;
6727 ERR("NULL pDispParams not allowed\n");
6728 return E_INVALIDARG
;
6731 dump_DispParms(pDispParams
);
6733 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6735 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6736 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6737 return E_INVALIDARG
;
6740 /* we do this instead of using GetFuncDesc since it will return a fake
6741 * FUNCDESC for dispinterfaces and we want the real function description */
6742 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6743 pFuncInfo
= &This
->funcdescs
[fdc
];
6744 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6745 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6746 !func_restricted( &pFuncInfo
->funcdesc
))
6750 if (fdc
< This
->cFuncs
) {
6751 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6755 TRACE("invoking:\n");
6756 dump_TLBFuncDescOne(pFuncInfo
);
6759 switch (func_desc
->funckind
) {
6760 case FUNC_PUREVIRTUAL
:
6761 case FUNC_VIRTUAL
: {
6762 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6764 VARIANT retval
; /* pointer for storing byref retvals in */
6765 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6766 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6767 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6768 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6769 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6770 UINT vargs_converted
=0;
6774 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6776 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6778 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6779 hres
= DISP_E_PARAMNOTFOUND
;
6784 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6786 ERR("functions with the vararg attribute do not support named arguments\n");
6787 hres
= DISP_E_NONAMEDARGS
;
6791 for (i
= 0; i
< func_desc
->cParams
; i
++)
6793 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6794 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6799 TRACE("changing args\n");
6800 for (i
= 0; i
< func_desc
->cParams
; i
++)
6802 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6803 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6804 VARIANTARG
*src_arg
;
6806 if (wParamFlags
& PARAMFLAG_FLCID
)
6809 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6811 V_I4(arg
) = This
->pTypeLib
->lcid
;
6820 for (j
= 0; j
< cNamedArgs
; j
++)
6821 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6823 src_arg
= &pDispParams
->rgvarg
[j
];
6828 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6830 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6834 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6836 /* under most conditions the caller is not allowed to
6837 * pass in a dispparam arg in the index of what would be
6838 * the retval parameter. however, there is an exception
6839 * where the extra parameter is used in an extra
6840 * IDispatch::Invoke below */
6841 if ((i
< pDispParams
->cArgs
) &&
6842 ((func_desc
->cParams
!= 1) || !pVarResult
||
6843 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6845 hres
= DISP_E_BADPARAMCOUNT
;
6849 /* note: this check is placed so that if the caller passes
6850 * in a VARIANTARG for the retval we just ignore it, like
6852 if (i
== func_desc
->cParams
- 1)
6855 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6856 memset(arg
, 0, sizeof(*arg
));
6857 V_VT(arg
) = rgvt
[i
];
6858 memset(&retval
, 0, sizeof(retval
));
6859 V_BYREF(arg
) = &retval
;
6863 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6864 hres
= E_UNEXPECTED
;
6870 dump_Variant(src_arg
);
6872 if(rgvt
[i
]!=V_VT(src_arg
))
6874 if (rgvt
[i
] == VT_VARIANT
)
6875 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6876 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6878 if (rgvt
[i
] == V_VT(src_arg
))
6879 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6882 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6883 if (wParamFlags
& PARAMFLAG_FIN
)
6884 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6885 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6887 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6889 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6892 SAFEARRAYBOUND bound
;
6896 bound
.cElements
= pDispParams
->cArgs
-i
;
6897 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6899 ERR("SafeArrayCreate failed\n");
6902 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6905 ERR("SafeArrayAccessData failed with %x\n", hres
);
6906 SafeArrayDestroy(a
);
6909 for (j
= 0; j
< bound
.cElements
; j
++)
6910 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6911 hres
= SafeArrayUnaccessData(a
);
6914 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6915 SafeArrayDestroy(a
);
6918 V_ARRAY(&rgvarg
[i
]) = a
;
6919 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6921 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6923 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6924 if (wParamFlags
& PARAMFLAG_FIN
)
6925 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6927 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6928 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6929 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6931 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6933 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6934 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6938 /* FIXME: this doesn't work for VT_BYREF arguments if
6939 * they are not the same type as in the paramdesc */
6940 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6941 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6942 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6947 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6948 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6949 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6952 prgpvarg
[i
] = &rgvarg
[i
];
6956 prgpvarg
[i
] = src_arg
;
6959 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
6960 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
6961 && V_UNKNOWN(prgpvarg
[i
])) {
6962 IUnknown
*userdefined_iface
;
6965 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
6969 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
6971 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
6975 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
6976 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
6979 else if (wParamFlags
& PARAMFLAG_FOPT
)
6982 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6983 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6985 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6991 VARIANTARG
*missing_arg
;
6992 /* if the function wants a pointer to a variant then
6993 * set that up, otherwise just pass the VT_ERROR in
6994 * the argument by value */
6995 if (rgvt
[i
] & VT_BYREF
)
6997 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6998 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6999 V_VARIANTREF(arg
) = missing_arg
;
7003 V_VT(missing_arg
) = VT_ERROR
;
7004 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7009 hres
= DISP_E_BADPARAMCOUNT
;
7013 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7015 /* VT_VOID is a special case for return types, so it is not
7016 * handled in the general function */
7017 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7018 V_VT(&varresult
) = VT_EMPTY
;
7021 V_VT(&varresult
) = 0;
7022 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7023 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7026 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7027 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7028 prgpvarg
, &varresult
);
7030 vargs_converted
= 0;
7032 for (i
= 0; i
< func_desc
->cParams
; i
++)
7034 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7035 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7037 if (wParamFlags
& PARAMFLAG_FLCID
)
7039 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7043 TRACE("[retval] value: ");
7044 dump_Variant(prgpvarg
[i
]);
7049 VariantInit(pVarResult
);
7050 /* deref return value */
7051 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7054 VARIANT_ClearInd(prgpvarg
[i
]);
7056 else if (vargs_converted
< pDispParams
->cArgs
)
7058 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7059 if (wParamFlags
& PARAMFLAG_FOUT
)
7061 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7063 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7067 ERR("failed to convert param %d to vt %d\n", i
,
7068 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7073 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7074 func_desc
->cParamsOpt
< 0 &&
7075 i
== func_desc
->cParams
-1)
7077 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7080 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7083 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7086 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7089 ERR("SafeArrayAccessData failed with %x\n", hres
);
7092 for (j
= 0; j
<= ubound
; j
++)
7093 VariantClear(&v
[j
]);
7094 hres
= SafeArrayUnaccessData(a
);
7097 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7101 VariantClear(&rgvarg
[i
]);
7104 else if (wParamFlags
& PARAMFLAG_FOPT
)
7106 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7107 VariantClear(&rgvarg
[i
]);
7110 VariantClear(&missing_arg
[i
]);
7113 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7115 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7116 hres
= DISP_E_EXCEPTION
;
7119 IErrorInfo
*pErrorInfo
;
7120 pExcepInfo
->scode
= V_ERROR(&varresult
);
7121 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7123 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7124 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7125 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7126 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7128 IErrorInfo_Release(pErrorInfo
);
7132 if (V_VT(&varresult
) != VT_ERROR
)
7134 TRACE("varresult value: ");
7135 dump_Variant(&varresult
);
7139 VariantClear(pVarResult
);
7140 *pVarResult
= varresult
;
7143 VariantClear(&varresult
);
7146 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7147 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7148 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7149 (pDispParams
->cArgs
!= 0))
7151 if (V_VT(pVarResult
) == VT_DISPATCH
)
7153 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7154 /* Note: not VariantClear; we still need the dispatch
7155 * pointer to be valid */
7156 VariantInit(pVarResult
);
7157 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7158 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7159 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7160 IDispatch_Release(pDispatch
);
7164 VariantClear(pVarResult
);
7165 hres
= DISP_E_NOTACOLLECTION
;
7173 case FUNC_DISPATCH
: {
7176 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7177 if (SUCCEEDED(hres
)) {
7178 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7179 hres
= IDispatch_Invoke(
7180 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7181 pVarResult
,pExcepInfo
,pArgErr
7184 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7185 IDispatch_Release(disp
);
7187 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7191 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7196 TRACE("-- 0x%08x\n", hres
);
7199 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7202 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7203 if(FAILED(hres
)) return hres
;
7205 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7206 dump_VARDESC(var_desc
);
7207 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7211 /* not found, look for it in inherited interfaces */
7212 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7213 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7214 if(This
->impltypes
) {
7215 /* recursive search */
7217 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7218 if(SUCCEEDED(hres
)){
7219 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7220 ITypeInfo_Release(pTInfo
);
7223 WARN("Could not search inherited interface!\n");
7226 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7227 return DISP_E_MEMBERNOTFOUND
;
7230 /* ITypeInfo::GetDocumentation
7232 * Retrieves the documentation string, the complete Help file name and path,
7233 * and the context ID for the Help topic for a specified type description.
7235 * (Can be tested by the Visual Basic Editor in Word for instance.)
7237 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7238 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7239 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7241 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7242 const TLBFuncDesc
*pFDesc
;
7243 const TLBVarDesc
*pVDesc
;
7244 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7245 " HelpContext(%p) HelpFile(%p)\n",
7246 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7247 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7249 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7251 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7253 *pdwHelpContext
=This
->dwHelpContext
;
7255 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7257 }else {/* for a member */
7258 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7261 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7263 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7265 *pdwHelpContext
=pFDesc
->helpcontext
;
7267 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7270 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7273 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7275 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7277 *pdwHelpContext
=pVDesc
->HelpContext
;
7279 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7284 if(This
->impltypes
&&
7285 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7286 /* recursive search */
7289 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7290 if(SUCCEEDED(result
)) {
7291 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7292 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7293 ITypeInfo_Release(pTInfo
);
7296 WARN("Could not search inherited interface!\n");
7299 WARN("member %d not found\n", memid
);
7300 return TYPE_E_ELEMENTNOTFOUND
;
7303 /* ITypeInfo::GetDllEntry
7305 * Retrieves a description or specification of an entry point for a function
7308 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7309 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7312 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7313 const TLBFuncDesc
*pFDesc
;
7315 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7317 if (pBstrDllName
) *pBstrDllName
= NULL
;
7318 if (pBstrName
) *pBstrName
= NULL
;
7319 if (pwOrdinal
) *pwOrdinal
= 0;
7321 if (This
->typekind
!= TKIND_MODULE
)
7322 return TYPE_E_BADMODULEKIND
;
7324 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7326 dump_TypeInfo(This
);
7328 dump_TLBFuncDescOne(pFDesc
);
7331 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7333 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7335 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7343 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7346 return TYPE_E_ELEMENTNOTFOUND
;
7349 /* internal function to make the inherited interfaces' methods appear
7350 * part of the interface */
7351 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7352 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7354 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7357 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7359 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7361 ITypeInfo
*pSubTypeInfo
;
7363 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7367 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7369 ITypeInfo_Release(pSubTypeInfo
);
7373 *hRefType
-= DISPATCH_HREF_OFFSET
;
7375 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7376 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7381 /* ITypeInfo::GetRefTypeInfo
7383 * If a type description references other type descriptions, it retrieves
7384 * the referenced type descriptions.
7386 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7389 ITypeInfo
**ppTInfo
)
7391 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7392 HRESULT result
= E_FAIL
;
7395 return E_INVALIDARG
;
7397 if ((INT
)hRefType
< 0) {
7398 ITypeInfoImpl
*pTypeInfoImpl
;
7400 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7401 !(This
->typekind
== TKIND_INTERFACE
||
7402 This
->typekind
== TKIND_DISPATCH
))
7403 return TYPE_E_ELEMENTNOTFOUND
;
7405 /* when we meet a DUAL typeinfo, we must create the alternate
7408 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7410 *pTypeInfoImpl
= *This
;
7411 pTypeInfoImpl
->ref
= 0;
7412 list_init(&pTypeInfoImpl
->custdata_list
);
7414 if (This
->typekind
== TKIND_INTERFACE
)
7415 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7417 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7419 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7420 /* the AddRef implicitly adds a reference to the parent typelib, which
7421 * stops the copied data from being destroyed until the new typeinfo's
7422 * refcount goes to zero, but we need to signal to the new instance to
7423 * not free its data structures when it is destroyed */
7424 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7426 ITypeInfo_AddRef(*ppTInfo
);
7429 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7430 (This
->typekind
== TKIND_DISPATCH
))
7432 HREFTYPE href_dispatch
= hRefType
;
7433 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7435 TLBRefType
*ref_type
;
7436 ITypeLib
*pTLib
= NULL
;
7439 if(!(hRefType
& 0x1)){
7440 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7442 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7445 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7446 ITypeInfo_AddRef(*ppTInfo
);
7452 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7454 if(ref_type
->reference
== (hRefType
& (~0x3)))
7457 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7459 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7463 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7465 TRACE("internal reference\n");
7466 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7468 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7469 TRACE("typeinfo in imported typelib that is already loaded\n");
7470 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7471 ITypeLib_AddRef(pTLib
);
7476 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7478 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7479 ref_type
->pImpTLInfo
->wVersionMajor
,
7480 ref_type
->pImpTLInfo
->wVersionMinor
,
7481 This
->pTypeLib
->syskind
,
7482 ref_type
->pImpTLInfo
->lcid
, &libnam
);
7484 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7486 result
= LoadTypeLib(libnam
, &pTLib
);
7487 SysFreeString(libnam
);
7489 if(SUCCEEDED(result
)) {
7490 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7491 ITypeLib_AddRef(pTLib
);
7495 if(SUCCEEDED(result
)) {
7496 if(ref_type
->index
== TLB_REF_USE_GUID
)
7497 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7499 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7502 ITypeLib_Release(pTLib
);
7506 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7507 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7511 /* ITypeInfo::AddressOfMember
7513 * Retrieves the addresses of static functions or variables, such as those
7516 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7517 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7519 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7525 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7527 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7531 module
= LoadLibraryW(dll
);
7534 ERR("couldn't load %s\n", debugstr_w(dll
));
7536 SysFreeString(entry
);
7537 return STG_E_FILENOTFOUND
;
7539 /* FIXME: store library somewhere where we can free it */
7544 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7545 entryA
= heap_alloc(len
);
7546 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7548 *ppv
= GetProcAddress(module
, entryA
);
7550 ERR("function not found %s\n", debugstr_a(entryA
));
7556 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7558 ERR("function not found %d\n", ordinal
);
7562 SysFreeString(entry
);
7565 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7570 /* ITypeInfo::CreateInstance
7572 * Creates a new instance of a type that describes a component object class
7575 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7576 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7578 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7582 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7588 WARN("Not able to aggregate\n");
7589 return CLASS_E_NOAGGREGATION
;
7592 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7593 if(FAILED(hr
)) return hr
;
7595 if(pTA
->typekind
!= TKIND_COCLASS
)
7597 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7603 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7606 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7607 TRACE("GetActiveObject rets %08x\n", hr
);
7610 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7611 IUnknown_Release(pUnk
);
7616 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7617 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7621 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7625 /* ITypeInfo::GetMops
7627 * Retrieves marshalling information.
7629 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7632 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7633 FIXME("(%p %d) stub!\n", This
, memid
);
7638 /* ITypeInfo::GetContainingTypeLib
7640 * Retrieves the containing type library and the index of the type description
7641 * within that type library.
7643 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7644 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7646 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7648 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7650 *pIndex
=This
->index
;
7651 TRACE("returning pIndex=%d\n", *pIndex
);
7655 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7656 ITypeLib_AddRef(*ppTLib
);
7657 TRACE("returning ppTLib=%p\n", *ppTLib
);
7663 /* ITypeInfo::ReleaseTypeAttr
7665 * Releases a TYPEATTR previously returned by Get
7668 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7669 TYPEATTR
* pTypeAttr
)
7671 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7672 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7673 heap_free(pTypeAttr
);
7676 /* ITypeInfo::ReleaseFuncDesc
7678 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7680 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7682 FUNCDESC
*pFuncDesc
)
7684 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7687 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7689 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7690 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7691 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7693 SysFreeString((BSTR
)pFuncDesc
);
7696 /* ITypeInfo::ReleaseVarDesc
7698 * Releases a VARDESC previously returned by GetVarDesc.
7700 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7703 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7704 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7706 TLB_FreeVarDesc(pVarDesc
);
7709 /* ITypeInfo2::GetTypeKind
7711 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7714 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7715 TYPEKIND
*pTypeKind
)
7717 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7718 *pTypeKind
=This
->typekind
;
7719 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7723 /* ITypeInfo2::GetTypeFlags
7725 * Returns the type flags without any allocations. This returns a DWORD type
7726 * flag, which expands the type flags without growing the TYPEATTR (type
7730 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7732 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7733 *pTypeFlags
=This
->wTypeFlags
;
7734 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7738 /* ITypeInfo2::GetFuncIndexOfMemId
7739 * Binds to a specific member based on a known DISPID, where the member name
7740 * is not known (for example, when binding to a default member).
7743 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7744 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7746 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7750 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7751 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7752 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7755 if(fdc
< This
->cFuncs
) {
7759 result
= TYPE_E_ELEMENTNOTFOUND
;
7761 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7762 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7766 /* TypeInfo2::GetVarIndexOfMemId
7768 * Binds to a specific member based on a known DISPID, where the member name
7769 * is not known (for example, when binding to a default member).
7772 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7773 MEMBERID memid
, UINT
*pVarIndex
)
7775 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7776 TLBVarDesc
*pVarInfo
;
7778 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7780 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7782 return TYPE_E_ELEMENTNOTFOUND
;
7784 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7789 /* ITypeInfo2::GetCustData
7791 * Gets the custom data
7793 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7798 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7799 TLBCustData
*pCData
;
7801 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7803 if(!guid
|| !pVarVal
)
7804 return E_INVALIDARG
;
7806 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
7808 VariantInit( pVarVal
);
7810 VariantCopy( pVarVal
, &pCData
->data
);
7812 VariantClear( pVarVal
);
7816 /* ITypeInfo2::GetFuncCustData
7818 * Gets the custom data
7820 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7826 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7827 TLBCustData
*pCData
;
7828 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7830 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7832 if(index
>= This
->cFuncs
)
7833 return TYPE_E_ELEMENTNOTFOUND
;
7835 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7837 return TYPE_E_ELEMENTNOTFOUND
;
7839 VariantInit(pVarVal
);
7840 VariantCopy(pVarVal
, &pCData
->data
);
7845 /* ITypeInfo2::GetParamCustData
7847 * Gets the custom data
7849 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7856 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7857 TLBCustData
*pCData
;
7858 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7860 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7861 debugstr_guid(guid
), pVarVal
);
7863 if(indexFunc
>= This
->cFuncs
)
7864 return TYPE_E_ELEMENTNOTFOUND
;
7866 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7867 return TYPE_E_ELEMENTNOTFOUND
;
7869 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7871 return TYPE_E_ELEMENTNOTFOUND
;
7873 VariantInit(pVarVal
);
7874 VariantCopy(pVarVal
, &pCData
->data
);
7879 /* ITypeInfo2::GetVarCustData
7881 * Gets the custom data
7883 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7889 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7890 TLBCustData
*pCData
;
7891 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7893 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7895 if(index
>= This
->cVars
)
7896 return TYPE_E_ELEMENTNOTFOUND
;
7898 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7900 return TYPE_E_ELEMENTNOTFOUND
;
7902 VariantInit(pVarVal
);
7903 VariantCopy(pVarVal
, &pCData
->data
);
7908 /* ITypeInfo2::GetImplCustData
7910 * Gets the custom data
7912 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7918 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7919 TLBCustData
*pCData
;
7920 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7922 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7924 if(index
>= This
->cImplTypes
)
7925 return TYPE_E_ELEMENTNOTFOUND
;
7927 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7929 return TYPE_E_ELEMENTNOTFOUND
;
7931 VariantInit(pVarVal
);
7932 VariantCopy(pVarVal
, &pCData
->data
);
7937 /* ITypeInfo2::GetDocumentation2
7939 * Retrieves the documentation string, the complete Help file name and path,
7940 * the localization context to use, and the context ID for the library Help
7941 * topic in the Help file.
7944 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7948 BSTR
*pbstrHelpString
,
7949 DWORD
*pdwHelpStringContext
,
7950 BSTR
*pbstrHelpStringDll
)
7952 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7953 const TLBFuncDesc
*pFDesc
;
7954 const TLBVarDesc
*pVDesc
;
7955 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7956 "HelpStringContext(%p) HelpStringDll(%p)\n",
7957 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7958 pbstrHelpStringDll
);
7959 /* the help string should be obtained from the helpstringdll,
7960 * using the _DLLGetDocumentation function, based on the supplied
7961 * lcid. Nice to do sometime...
7963 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7965 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
7966 if(pdwHelpStringContext
)
7967 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7968 if(pbstrHelpStringDll
)
7969 *pbstrHelpStringDll
=
7970 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7972 }else {/* for a member */
7973 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7976 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7977 if(pdwHelpStringContext
)
7978 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7979 if(pbstrHelpStringDll
)
7980 *pbstrHelpStringDll
=
7981 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7984 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7987 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7988 if(pdwHelpStringContext
)
7989 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7990 if(pbstrHelpStringDll
)
7991 *pbstrHelpStringDll
=
7992 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
7996 return TYPE_E_ELEMENTNOTFOUND
;
7999 /* ITypeInfo2::GetAllCustData
8001 * Gets all custom data items for the Type info.
8004 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8006 CUSTDATA
*pCustData
)
8008 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8010 TRACE("%p %p\n", This
, pCustData
);
8012 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8015 /* ITypeInfo2::GetAllFuncCustData
8017 * Gets all custom data items for the specified Function
8020 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8023 CUSTDATA
*pCustData
)
8025 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8026 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8028 TRACE("%p %u %p\n", This
, index
, pCustData
);
8030 if(index
>= This
->cFuncs
)
8031 return TYPE_E_ELEMENTNOTFOUND
;
8033 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8036 /* ITypeInfo2::GetAllParamCustData
8038 * Gets all custom data items for the Functions
8041 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8042 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8044 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8045 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8047 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8049 if(indexFunc
>= This
->cFuncs
)
8050 return TYPE_E_ELEMENTNOTFOUND
;
8052 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8053 return TYPE_E_ELEMENTNOTFOUND
;
8055 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8058 /* ITypeInfo2::GetAllVarCustData
8060 * Gets all custom data items for the specified Variable
8063 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8064 UINT index
, CUSTDATA
*pCustData
)
8066 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8067 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8069 TRACE("%p %u %p\n", This
, index
, pCustData
);
8071 if(index
>= This
->cVars
)
8072 return TYPE_E_ELEMENTNOTFOUND
;
8074 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8077 /* ITypeInfo2::GetAllImplCustData
8079 * Gets all custom data items for the specified implementation type
8082 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8085 CUSTDATA
*pCustData
)
8087 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8088 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8090 TRACE("%p %u %p\n", This
, index
, pCustData
);
8092 if(index
>= This
->cImplTypes
)
8093 return TYPE_E_ELEMENTNOTFOUND
;
8095 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8098 static const ITypeInfo2Vtbl tinfvt
=
8101 ITypeInfo_fnQueryInterface
,
8103 ITypeInfo_fnRelease
,
8105 ITypeInfo_fnGetTypeAttr
,
8106 ITypeInfo_fnGetTypeComp
,
8107 ITypeInfo_fnGetFuncDesc
,
8108 ITypeInfo_fnGetVarDesc
,
8109 ITypeInfo_fnGetNames
,
8110 ITypeInfo_fnGetRefTypeOfImplType
,
8111 ITypeInfo_fnGetImplTypeFlags
,
8112 ITypeInfo_fnGetIDsOfNames
,
8114 ITypeInfo_fnGetDocumentation
,
8115 ITypeInfo_fnGetDllEntry
,
8116 ITypeInfo_fnGetRefTypeInfo
,
8117 ITypeInfo_fnAddressOfMember
,
8118 ITypeInfo_fnCreateInstance
,
8119 ITypeInfo_fnGetMops
,
8120 ITypeInfo_fnGetContainingTypeLib
,
8121 ITypeInfo_fnReleaseTypeAttr
,
8122 ITypeInfo_fnReleaseFuncDesc
,
8123 ITypeInfo_fnReleaseVarDesc
,
8125 ITypeInfo2_fnGetTypeKind
,
8126 ITypeInfo2_fnGetTypeFlags
,
8127 ITypeInfo2_fnGetFuncIndexOfMemId
,
8128 ITypeInfo2_fnGetVarIndexOfMemId
,
8129 ITypeInfo2_fnGetCustData
,
8130 ITypeInfo2_fnGetFuncCustData
,
8131 ITypeInfo2_fnGetParamCustData
,
8132 ITypeInfo2_fnGetVarCustData
,
8133 ITypeInfo2_fnGetImplTypeCustData
,
8134 ITypeInfo2_fnGetDocumentation2
,
8135 ITypeInfo2_fnGetAllCustData
,
8136 ITypeInfo2_fnGetAllFuncCustData
,
8137 ITypeInfo2_fnGetAllParamCustData
,
8138 ITypeInfo2_fnGetAllVarCustData
,
8139 ITypeInfo2_fnGetAllImplTypeCustData
,
8142 /******************************************************************************
8143 * CreateDispTypeInfo [OLEAUT32.31]
8145 * Build type information for an object so it can be called through an
8146 * IDispatch interface.
8149 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8150 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8153 * This call allows an objects methods to be accessed through IDispatch, by
8154 * building an ITypeInfo object that IDispatch can use to call through.
8156 HRESULT WINAPI
CreateDispTypeInfo(
8157 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8158 LCID lcid
, /* [I] Locale Id */
8159 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8161 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8162 ITypeLibImpl
*pTypeLibImpl
;
8163 unsigned int param
, func
;
8164 TLBFuncDesc
*pFuncDesc
;
8168 pTypeLibImpl
= TypeLibImpl_Constructor();
8169 if (!pTypeLibImpl
) return E_FAIL
;
8171 pTypeLibImpl
->TypeInfoCount
= 2;
8172 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8174 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8175 pTIIface
->pTypeLib
= pTypeLibImpl
;
8176 pTIIface
->index
= 0;
8177 pTIIface
->Name
= NULL
;
8178 pTIIface
->dwHelpContext
= -1;
8179 pTIIface
->guid
= NULL
;
8180 pTIIface
->lcid
= lcid
;
8181 pTIIface
->typekind
= TKIND_INTERFACE
;
8182 pTIIface
->wMajorVerNum
= 0;
8183 pTIIface
->wMinorVerNum
= 0;
8184 pTIIface
->cbAlignment
= 2;
8185 pTIIface
->cbSizeInstance
= -1;
8186 pTIIface
->cbSizeVft
= -1;
8187 pTIIface
->cFuncs
= 0;
8188 pTIIface
->cImplTypes
= 0;
8189 pTIIface
->cVars
= 0;
8190 pTIIface
->wTypeFlags
= 0;
8191 pTIIface
->hreftype
= 0;
8193 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8194 pFuncDesc
= pTIIface
->funcdescs
;
8195 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8196 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8197 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8198 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8199 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8200 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8201 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8202 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8203 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8204 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8205 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8206 pFuncDesc
->funcdesc
.cScodes
= 0;
8207 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8208 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8209 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8210 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8211 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8212 md
->cArgs
* sizeof(ELEMDESC
));
8213 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8214 for(param
= 0; param
< md
->cArgs
; param
++) {
8215 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8216 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8218 pFuncDesc
->helpcontext
= 0;
8219 pFuncDesc
->HelpStringContext
= 0;
8220 pFuncDesc
->HelpString
= NULL
;
8221 pFuncDesc
->Entry
= NULL
;
8222 list_init(&pFuncDesc
->custdata_list
);
8227 dump_TypeInfo(pTIIface
);
8229 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8230 pTIClass
->pTypeLib
= pTypeLibImpl
;
8231 pTIClass
->index
= 1;
8232 pTIClass
->Name
= NULL
;
8233 pTIClass
->dwHelpContext
= -1;
8234 pTIClass
->guid
= NULL
;
8235 pTIClass
->lcid
= lcid
;
8236 pTIClass
->typekind
= TKIND_COCLASS
;
8237 pTIClass
->wMajorVerNum
= 0;
8238 pTIClass
->wMinorVerNum
= 0;
8239 pTIClass
->cbAlignment
= 2;
8240 pTIClass
->cbSizeInstance
= -1;
8241 pTIClass
->cbSizeVft
= -1;
8242 pTIClass
->cFuncs
= 0;
8243 pTIClass
->cImplTypes
= 1;
8244 pTIClass
->cVars
= 0;
8245 pTIClass
->wTypeFlags
= 0;
8246 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8248 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8250 ref
= heap_alloc_zero(sizeof(*ref
));
8251 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8252 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8254 dump_TypeInfo(pTIClass
);
8256 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8258 ITypeInfo_AddRef(*pptinfo
);
8259 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8265 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8267 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8269 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8272 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8274 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8276 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8279 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8281 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8283 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8286 static HRESULT WINAPI
ITypeComp_fnBind(
8291 ITypeInfo
** ppTInfo
,
8292 DESCKIND
* pDescKind
,
8295 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8296 const TLBFuncDesc
*pFDesc
;
8297 const TLBVarDesc
*pVDesc
;
8298 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8301 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8303 *pDescKind
= DESCKIND_NONE
;
8304 pBindPtr
->lpfuncdesc
= NULL
;
8307 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8308 pFDesc
= &This
->funcdescs
[fdc
];
8309 if (!strcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8310 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8313 /* name found, but wrong flags */
8314 hr
= TYPE_E_TYPEMISMATCH
;
8318 if (fdc
< This
->cFuncs
)
8320 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8322 &pBindPtr
->lpfuncdesc
,
8323 This
->typekind
== TKIND_DISPATCH
);
8326 *pDescKind
= DESCKIND_FUNCDESC
;
8327 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8328 ITypeInfo_AddRef(*ppTInfo
);
8331 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8333 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8336 *pDescKind
= DESCKIND_VARDESC
;
8337 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8338 ITypeInfo_AddRef(*ppTInfo
);
8342 /* FIXME: search each inherited interface, not just the first */
8343 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8344 /* recursive search */
8348 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8351 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8352 ITypeInfo_Release(pTInfo
);
8356 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8357 ITypeComp_Release(pTComp
);
8360 WARN("Could not search inherited interface!\n");
8362 if (hr
== DISP_E_MEMBERNOTFOUND
)
8364 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8368 static HRESULT WINAPI
ITypeComp_fnBindType(
8372 ITypeInfo
** ppTInfo
,
8373 ITypeComp
** ppTComp
)
8375 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8377 /* strange behaviour (does nothing) but like the
8380 if (!ppTInfo
|| !ppTComp
)
8389 static const ITypeCompVtbl tcompvt
=
8392 ITypeComp_fnQueryInterface
,
8394 ITypeComp_fnRelease
,
8397 ITypeComp_fnBindType
8400 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8401 ICreateTypeLib2
** ppctlib
)
8406 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8408 if (!szFile
) return E_INVALIDARG
;
8410 This
= TypeLibImpl_Constructor();
8412 return E_OUTOFMEMORY
;
8414 This
->lcid
= GetSystemDefaultLCID();
8415 This
->syskind
= syskind
;
8416 This
->ptr_size
= get_ptr_size(syskind
);
8418 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8420 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8421 return E_OUTOFMEMORY
;
8423 lstrcpyW(This
->path
, szFile
);
8425 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8426 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8430 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8431 REFIID riid
, void **object
)
8433 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8435 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8438 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8440 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8442 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8445 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8447 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8449 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8452 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8453 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8455 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8456 ITypeInfoImpl
*info
;
8459 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8461 if (!ctinfo
|| !name
)
8462 return E_INVALIDARG
;
8464 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8466 return TYPE_E_NAMECONFLICT
;
8468 if (This
->typeinfos
)
8469 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8470 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8472 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8474 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8476 info
->pTypeLib
= This
;
8477 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8478 info
->index
= This
->TypeInfoCount
;
8479 info
->typekind
= kind
;
8480 info
->cbAlignment
= 4;
8482 switch(info
->typekind
) {
8484 case TKIND_INTERFACE
:
8485 case TKIND_DISPATCH
:
8487 info
->cbSizeInstance
= 4;
8491 info
->cbSizeInstance
= 0;
8494 info
->cbSizeInstance
= 2;
8497 info
->cbSizeInstance
= -0x75;
8500 FIXME("unrecognized typekind %d\n", info
->typekind
);
8501 info
->cbSizeInstance
= 0xdeadbeef;
8505 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8506 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8508 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8512 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8514 ++This
->TypeInfoCount
;
8519 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8522 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8524 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8527 return E_INVALIDARG
;
8529 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8534 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8535 WORD majorVerNum
, WORD minorVerNum
)
8537 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8539 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8541 This
->ver_major
= majorVerNum
;
8542 This
->ver_minor
= minorVerNum
;
8547 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8550 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8552 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8554 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8559 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8562 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8564 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8567 return E_INVALIDARG
;
8569 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8574 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8575 LPOLESTR helpFileName
)
8577 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8579 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8582 return E_INVALIDARG
;
8584 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8589 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8592 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8594 TRACE("%p %d\n", This
, helpContext
);
8596 This
->dwHelpContext
= helpContext
;
8601 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8604 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8606 TRACE("%p %x\n", This
, lcid
);
8608 This
->set_lcid
= lcid
;
8613 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8616 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8618 TRACE("%p %x\n", This
, libFlags
);
8620 This
->libflags
= libFlags
;
8625 typedef struct tagWMSFT_SegContents
{
8628 } WMSFT_SegContents
;
8630 typedef struct tagWMSFT_TLBFile
{
8632 WMSFT_SegContents typeinfo_seg
;
8633 WMSFT_SegContents impfile_seg
;
8634 WMSFT_SegContents impinfo_seg
;
8635 WMSFT_SegContents ref_seg
;
8636 WMSFT_SegContents guidhash_seg
;
8637 WMSFT_SegContents guid_seg
;
8638 WMSFT_SegContents namehash_seg
;
8639 WMSFT_SegContents name_seg
;
8640 WMSFT_SegContents string_seg
;
8641 WMSFT_SegContents typdesc_seg
;
8642 WMSFT_SegContents arraydesc_seg
;
8643 WMSFT_SegContents custdata_seg
;
8644 WMSFT_SegContents cdguids_seg
;
8646 WMSFT_SegContents aux_seg
;
8649 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8650 WMSFT_TLBFile
*file
)
8656 file
->string_seg
.len
= 0;
8657 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8660 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8662 return E_UNEXPECTED
;
8664 size
+= sizeof(INT16
);
8666 size
= (size
+ 4) & ~0x3;
8670 file
->string_seg
.len
+= size
;
8672 /* temporarily use str->offset to store the length of the aligned,
8673 * converted string */
8677 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8680 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8683 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8684 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8686 heap_free(file
->string_seg
.data
);
8687 return E_UNEXPECTED
;
8690 *((INT16
*)data
) = size
;
8692 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8696 str
->offset
= last_offs
;
8703 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8704 WMSFT_TLBFile
*file
)
8709 MSFT_NameIntro
*last_intro
= NULL
;
8711 file
->header
.nametablecount
= 0;
8712 file
->header
.nametablechars
= 0;
8714 file
->name_seg
.len
= 0;
8715 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8718 size
= strlenW(str
->str
);
8719 file
->header
.nametablechars
+= size
;
8720 file
->header
.nametablecount
++;
8722 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8724 return E_UNEXPECTED
;
8726 size
+= sizeof(MSFT_NameIntro
);
8728 size
= (size
+ 4) & ~0x3;
8732 file
->name_seg
.len
+= size
;
8734 /* temporarily use str->offset to store the length of the aligned,
8735 * converted string */
8739 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
);
8742 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8744 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8746 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8747 data
+ sizeof(MSFT_NameIntro
),
8748 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8750 heap_free(file
->name_seg
.data
);
8751 return E_UNEXPECTED
;
8753 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8755 intro
->hreftype
= -1; /* TODO? */
8756 intro
->namelen
= size
& 0xFF;
8757 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8758 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8759 intro
->namelen
|= hash
<< 16;
8760 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8761 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
8763 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
8764 str
->offset
- size
- sizeof(MSFT_NameIntro
));
8766 /* update str->offset to actual value to use in other
8767 * compilation functions that require positions within
8768 * the string table */
8772 str
->offset
= last_offs
;
8777 last_intro
->hreftype
= 0; /* last one is 0? */
8782 static inline int hash_guid(GUID
*guid
)
8786 for (i
= 0; i
< 8; i
++)
8787 hash
^= ((const short *)guid
)[i
];
8792 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
8795 MSFT_GuidEntry
*entry
;
8797 int hash_key
, *guidhashtab
;
8799 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
8800 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
8802 entry
= file
->guid_seg
.data
;
8804 guidhashtab
= file
->guidhash_seg
.data
;
8805 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
8806 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
8807 entry
->hreftype
= guid
->hreftype
;
8809 hash_key
= hash_guid(&guid
->guid
);
8810 entry
->next_hash
= guidhashtab
[hash_key
];
8811 guidhashtab
[hash_key
] = offs
;
8813 guid
->offset
= offs
;
8814 offs
+= sizeof(MSFT_GuidEntry
);
8821 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
8824 VARTYPE arg_type
= V_VT(value
);
8827 DWORD ret
= file
->custdata_seg
.len
;
8829 if(arg_type
== VT_INT
)
8831 if(arg_type
== VT_UINT
)
8835 if(V_VT(value
) != arg_type
) {
8836 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
8838 ERR("VariantChangeType failed: %08x\n", hres
);
8843 /* Check if default value can be stored in-place */
8848 if(V_UI4(&v
) > 0x3ffffff)
8861 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
8864 /* have to allocate space in custdata_seg */
8873 /* Construct the data to be allocated */
8876 if(file
->custdata_seg
.data
){
8877 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
8878 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
8879 file
->custdata_seg
.len
+= sizeof(int) * 2;
8881 file
->custdata_seg
.len
= sizeof(int) * 2;
8882 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
8885 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
8886 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
8888 /* TODO: Check if the encoded data is already present in custdata_seg */
8894 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
8897 if(file
->custdata_seg
.data
){
8898 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
8899 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
8900 file
->custdata_seg
.len
+= len
;
8902 file
->custdata_seg
.len
= len
;
8903 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
8906 *((unsigned short *)data
) = V_VT(value
);
8907 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
8908 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
8909 if(V_BSTR(&v
)[i
] <= 0x7f)
8910 data
[i
+6] = V_BSTR(&v
)[i
];
8914 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
8915 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
8918 /* TODO: Check if the encoded data is already present in custdata_seg */
8923 FIXME("Argument type not yet handled\n");
8928 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
8930 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
8932 DWORD offs
= file
->arraydesc_seg
.len
;
8936 /* TODO: we should check for duplicates, but that's harder because each
8937 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
8938 * at the library-level) */
8940 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
8941 if(!file
->arraydesc_seg
.data
)
8942 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
8944 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
8945 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
) + offs
;
8947 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
8948 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
8949 for(i
= 0; i
< desc
->cDims
; ++i
){
8950 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
8951 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
8957 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
8963 VARTYPE vt
= desc
->vt
& VT_TYPEMASK
, subtype
;
9004 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9007 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9009 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9010 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9012 *out_size
+= 2 * sizeof(DWORD
);
9013 }else if(vt
== VT_CARRAY
){
9014 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9015 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9017 }else if(vt
== VT_USERDEFINED
){
9018 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9019 encoded
[1] = desc
->u
.hreftype
;
9020 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9022 FIXME("Don't know what to do! VT: 0x%x\n", desc
->vt
);
9023 *out_mix
= desc
->vt
;
9024 return 0x80000000 | (desc
->vt
<< 16) | desc
->vt
;
9027 data
= file
->typdesc_seg
.data
;
9028 while(offs
< file
->typdesc_seg
.len
){
9029 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9031 offs
+= sizeof(encoded
);
9034 file
->typdesc_seg
.len
+= sizeof(encoded
);
9035 if(!file
->typdesc_seg
.data
)
9036 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9038 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9040 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9045 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9047 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9048 DWORD ret
= cdguids_seg
->len
, offs
;
9049 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9052 if(list_empty(custdata_list
))
9055 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9056 if(!cdguids_seg
->data
){
9057 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9059 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9061 offs
= ret
+ sizeof(MSFT_CDGuid
);
9062 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9063 cdguid
->GuidOffset
= cd
->guid
->offset
;
9064 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9065 cdguid
->next
= offs
;
9066 offs
+= sizeof(MSFT_CDGuid
);
9076 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9077 WMSFT_TLBFile
*file
)
9079 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9080 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9081 MSFT_VarRecord
*varrecord
;
9082 MSFT_FuncRecord
*funcrecord
;
9084 DWORD
*name
, *offsets
, offs
;
9086 for(i
= 0; i
< info
->cFuncs
; ++i
){
9087 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9089 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9091 /* optional fields */
9092 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9093 if(!list_empty(&desc
->custdata_list
))
9094 recorded_size
+= 7 * sizeof(INT
);
9095 else if(desc
->HelpStringContext
!= 0)
9096 recorded_size
+= 6 * sizeof(INT
);
9098 else if(desc
->Entry
)
9099 recorded_size
+= 3 * sizeof(INT
);
9100 else if(desc
->HelpString
)
9101 recorded_size
+= 2 * sizeof(INT
);
9102 else if(desc
->helpcontext
)
9103 recorded_size
+= sizeof(INT
);
9105 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9107 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9108 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9109 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9114 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9117 for(i
= 0; i
< info
->cVars
; ++i
){
9118 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9120 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9122 /* optional fields */
9123 if(desc
->HelpStringContext
!= 0)
9124 recorded_size
+= 5 * sizeof(INT
);
9125 else if(!list_empty(&desc
->custdata_list
))
9126 recorded_size
+= 4 * sizeof(INT
);
9128 else if(desc
->HelpString
)
9129 recorded_size
+= 2 * sizeof(INT
);
9130 else if(desc
->HelpContext
!= 0)
9131 recorded_size
+= sizeof(INT
);
9133 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9136 if(!recorded_size
&& !extra_size
)
9139 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9141 aux_seg
->len
+= recorded_size
+ extra_size
;
9143 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9146 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9148 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9150 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9152 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9155 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9156 for(i
= 0; i
< info
->cFuncs
; ++i
){
9157 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9158 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9160 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9161 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9162 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9163 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9166 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9171 * ^has_param_defaults
9172 * ^oEntry_is_intresource
9174 funcrecord
->FKCCIC
=
9175 desc
->funcdesc
.funckind
|
9176 (desc
->funcdesc
.invkind
<< 3) |
9177 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9178 (desc
->funcdesc
.callconv
<< 8);
9180 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9181 funcrecord
->FKCCIC
|= 0x2000;
9183 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9184 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9185 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9186 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9189 if(paramdefault_size
> 0)
9190 funcrecord
->FKCCIC
|= 0x1000;
9192 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9193 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9195 /* optional fields */
9197 if(!list_empty(&desc
->custdata_list
)){
9198 size
+= 7 * sizeof(INT
);
9199 funcrecord
->HelpContext
= desc
->helpcontext
;
9200 if(desc
->HelpString
)
9201 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9203 funcrecord
->oHelpString
= -1;
9205 funcrecord
->oEntry
= -1;
9206 else if(IS_INTRESOURCE(desc
->Entry
))
9207 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9209 funcrecord
->oEntry
= desc
->Entry
->offset
;
9210 funcrecord
->res9
= -1;
9211 funcrecord
->resA
= -1;
9212 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9213 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9214 }else if(desc
->HelpStringContext
!= 0){
9215 size
+= 6 * sizeof(INT
);
9216 funcrecord
->HelpContext
= desc
->helpcontext
;
9217 if(desc
->HelpString
)
9218 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9220 funcrecord
->oHelpString
= -1;
9222 funcrecord
->oEntry
= -1;
9223 else if(IS_INTRESOURCE(desc
->Entry
))
9224 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9226 funcrecord
->oEntry
= desc
->Entry
->offset
;
9227 funcrecord
->res9
= -1;
9228 funcrecord
->resA
= -1;
9229 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9230 }else if(desc
->Entry
){
9231 size
+= 3 * sizeof(INT
);
9232 funcrecord
->HelpContext
= desc
->helpcontext
;
9233 if(desc
->HelpString
)
9234 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9236 funcrecord
->oHelpString
= -1;
9238 funcrecord
->oEntry
= -1;
9239 else if(IS_INTRESOURCE(desc
->Entry
))
9240 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9242 funcrecord
->oEntry
= desc
->Entry
->offset
;
9243 }else if(desc
->HelpString
){
9244 size
+= 2 * sizeof(INT
);
9245 funcrecord
->HelpContext
= desc
->helpcontext
;
9246 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9247 }else if(desc
->helpcontext
){
9248 size
+= sizeof(INT
);
9249 funcrecord
->HelpContext
= desc
->helpcontext
;
9252 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9253 size
+= paramdefault_size
;
9255 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9256 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9258 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9259 if(desc
->pParamDesc
[j
].Name
)
9260 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9263 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9265 if(paramdefault_size
){
9266 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9267 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9268 else if(paramdefault_size
)
9273 size
+= sizeof(MSFT_ParameterInfo
);
9276 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9282 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9285 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9286 for(i
= 0; i
< info
->cVars
; ++i
){
9287 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9288 DWORD size
= 5 * sizeof(INT
);
9290 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9291 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9292 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9293 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9295 if(desc
->vardesc
.varkind
== VAR_CONST
){
9296 varrecord
->vardescsize
+= sizeof(VARIANT
);
9297 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9299 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9302 if(desc
->HelpStringContext
!= 0){
9303 size
+= 5 * sizeof(INT
);
9304 varrecord
->HelpContext
= desc
->HelpContext
;
9305 if(desc
->HelpString
)
9306 varrecord
->HelpString
= desc
->HelpString
->offset
;
9308 varrecord
->HelpString
= -1;
9309 varrecord
->res9
= -1;
9310 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9311 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9312 }else if(!list_empty(&desc
->custdata_list
)){
9313 size
+= 4 * sizeof(INT
);
9314 varrecord
->HelpContext
= desc
->HelpContext
;
9315 if(desc
->HelpString
)
9316 varrecord
->HelpString
= desc
->HelpString
->offset
;
9318 varrecord
->HelpString
= -1;
9319 varrecord
->res9
= -1;
9320 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9321 }else if(desc
->HelpString
){
9322 size
+= 2 * sizeof(INT
);
9323 varrecord
->HelpContext
= desc
->HelpContext
;
9324 if(desc
->HelpString
)
9325 varrecord
->HelpString
= desc
->HelpString
->offset
;
9327 varrecord
->HelpString
= -1;
9328 }else if(desc
->HelpContext
!= 0){
9329 size
+= sizeof(INT
);
9330 varrecord
->HelpContext
= desc
->HelpContext
;
9333 varrecord
->Info
= size
| (i
<< 16);
9339 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9342 memid
= (MEMBERID
*)varrecord
;
9343 for(i
= 0; i
< info
->cFuncs
; ++i
){
9344 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9345 *memid
= desc
->funcdesc
.memid
;
9348 for(i
= 0; i
< info
->cVars
; ++i
){
9349 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9350 *memid
= desc
->vardesc
.memid
;
9354 name
= (UINT
*)memid
;
9355 for(i
= 0; i
< info
->cFuncs
; ++i
){
9356 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9358 *name
= desc
->Name
->offset
;
9363 for(i
= 0; i
< info
->cVars
; ++i
){
9364 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9366 *name
= desc
->Name
->offset
;
9375 typedef struct tagWMSFT_RefChunk
{
9382 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9384 DWORD offs
= file
->ref_seg
.len
, i
;
9385 WMSFT_RefChunk
*chunk
;
9387 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9388 if(!file
->ref_seg
.data
)
9389 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9391 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9393 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9395 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9396 chunk
->href
= info
->impltypes
[i
].hRef
;
9397 chunk
->res04
= info
->impltypes
[i
].implflags
;
9399 if(i
< info
->cImplTypes
- 1)
9400 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9409 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9413 size
= sizeof(MSFT_TypeInfoBase
);
9416 MSFT_TypeInfoBase
*base
= (void*)data
;
9417 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9418 base
->typekind
= TKIND_DISPATCH
;
9420 base
->typekind
= info
->typekind
;
9421 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9422 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9423 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9428 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9434 base
->posguid
= info
->guid
->offset
;
9437 base
->flags
= info
->wTypeFlags
;
9439 base
->NameOffset
= info
->Name
->offset
;
9441 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9442 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9444 base
->NameOffset
= -1;
9446 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9448 base
->docstringoffs
= info
->DocString
->offset
;
9450 base
->docstringoffs
= -1;
9451 base
->helpstringcontext
= info
->dwHelpStringContext
;
9452 base
->helpcontext
= info
->dwHelpContext
;
9453 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9454 base
->cImplTypes
= info
->cImplTypes
;
9455 base
->cbSizeVft
= info
->cbSizeVft
;
9456 base
->size
= info
->cbSizeInstance
;
9457 if(info
->typekind
== TKIND_COCLASS
){
9458 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9459 }else if(info
->typekind
== TKIND_ALIAS
){
9460 base
->datatype1
= WMSFT_append_typedesc(&info
->tdescAlias
, file
, NULL
, NULL
);
9461 }else if(info
->typekind
== TKIND_MODULE
){
9463 base
->datatype1
= info
->DllName
->offset
;
9465 base
->datatype1
= -1;
9467 if(info
->cImplTypes
> 0)
9468 base
->datatype1
= info
->impltypes
[0].hRef
;
9470 base
->datatype1
= -1;
9472 base
->datatype2
= index
; /* FIXME: i think there's more here */
9480 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9484 file
->typeinfo_seg
.len
= 0;
9485 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9486 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9487 *junk
= file
->typeinfo_seg
.len
;
9489 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9492 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9493 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9495 file
->aux_seg
.len
= 0;
9496 file
->aux_seg
.data
= NULL
;
9498 file
->typeinfo_seg
.len
= 0;
9499 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9500 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9501 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9502 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9506 typedef struct tagWMSFT_ImpFile
{
9512 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9515 WMSFT_ImpFile
*impfile
;
9517 DWORD last_offs
= 0;
9519 file
->impfile_seg
.len
= 0;
9520 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9524 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9528 path
= implib
->name
;
9529 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9531 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9534 size
+= sizeof(INT16
);
9536 size
= (size
+ 4) & ~0x3;
9540 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9543 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9545 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9546 int strlen
= 0, size
;
9548 impfile
= (WMSFT_ImpFile
*)data
;
9549 impfile
->guid_offs
= implib
->guid
->offset
;
9550 impfile
->lcid
= implib
->lcid
;
9551 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9553 data
+= sizeof(WMSFT_ImpFile
);
9556 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9560 path
= implib
->name
;
9561 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9562 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9564 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9567 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9569 size
= strlen
+ sizeof(INT16
);
9571 size
= (size
+ 4) & ~0x3;
9574 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9577 implib
->offset
= last_offs
;
9578 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9582 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9585 TLBRefType
*ref_type
;
9588 WMSFT_compile_impfile(This
, file
);
9590 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9591 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9593 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9594 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9595 if(ref_type
->index
== TLB_REF_USE_GUID
){
9596 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9597 info
->oGuid
= ref_type
->guid
->offset
;
9599 info
->oGuid
= ref_type
->index
;
9600 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9606 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9608 file
->guidhash_seg
.len
= 0x80;
9609 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9610 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9613 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9615 file
->namehash_seg
.len
= 0x200;
9616 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9617 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9620 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9622 if(contents
&& contents
->len
){
9623 segdir
->offset
= *running_offset
;
9624 segdir
->length
= contents
->len
;
9625 *running_offset
+= segdir
->length
;
9627 segdir
->offset
= -1;
9631 /* TODO: do these ever change? */
9633 segdir
->res0c
= 0xf;
9636 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9640 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9643 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9647 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9649 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9650 base
->memoffset
+= file_len
;
9657 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9659 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9660 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9661 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9662 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9663 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9664 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9665 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9666 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9667 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9668 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9669 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9670 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9671 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9672 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9675 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9677 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9679 DWORD written
, junk_size
, junk_offs
, running_offset
;
9685 TRACE("%p\n", This
);
9687 memset(&file
, 0, sizeof(file
));
9689 file
.header
.magic1
= 0x5446534D;
9690 file
.header
.magic2
= 0x00010002;
9691 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9692 file
.header
.lcid2
= This
->set_lcid
;
9693 file
.header
.varflags
= 0x41; /* TODO?? */
9695 file
.header
.varflags
|= 0x10;
9696 if (This
->HelpStringDll
)
9697 file
.header
.varflags
|= HELPDLLFLAG
;
9698 file
.header
.version
= (This
->ver_major
<< 16) | This
->ver_minor
;
9699 file
.header
.flags
= This
->libflags
;
9700 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9701 file
.header
.helpcontext
= This
->dwHelpContext
;
9702 file
.header
.res44
= 0x20;
9703 file
.header
.res48
= 0x80;
9704 file
.header
.dispatchpos
= This
->dispatch_href
;
9706 WMSFT_compile_namehash(This
, &file
);
9707 /* do name and string compilation to get offsets for other compilations */
9708 hres
= WMSFT_compile_names(This
, &file
);
9710 WMSFT_free_file(&file
);
9714 hres
= WMSFT_compile_strings(This
, &file
);
9716 WMSFT_free_file(&file
);
9720 WMSFT_compile_guidhash(This
, &file
);
9721 hres
= WMSFT_compile_guids(This
, &file
);
9723 WMSFT_free_file(&file
);
9728 file
.header
.helpfile
= This
->HelpFile
->offset
;
9730 file
.header
.helpfile
= -1;
9733 file
.header
.helpstring
= This
->DocString
->offset
;
9735 file
.header
.helpstring
= -1;
9737 /* do some more segment compilation */
9738 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9739 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9742 file
.header
.NameOffset
= This
->Name
->offset
;
9744 file
.header
.NameOffset
= -1;
9746 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9749 file
.header
.posguid
= This
->guid
->offset
;
9751 file
.header
.posguid
= -1;
9753 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9754 if(file
.header
.varflags
& HELPDLLFLAG
)
9755 junk_size
+= sizeof(DWORD
);
9757 junk
= heap_alloc_zero(junk_size
);
9758 if(file
.header
.varflags
& HELPDLLFLAG
){
9759 *junk
= This
->HelpStringDll
->offset
;
9768 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9769 WMSFT_compile_impinfo(This
, &file
);
9773 TRACE("header at: 0x%x\n", running_offset
);
9774 running_offset
+= sizeof(file
.header
);
9776 TRACE("junk at: 0x%x\n", running_offset
);
9777 running_offset
+= junk_size
;
9779 TRACE("segdir at: 0x%x\n", running_offset
);
9780 running_offset
+= sizeof(file
.segdir
);
9782 TRACE("typeinfo at: 0x%x\n", running_offset
);
9783 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
9785 TRACE("guidhashtab at: 0x%x\n", running_offset
);
9786 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
9788 TRACE("guidtab at: 0x%x\n", running_offset
);
9789 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
9791 TRACE("reftab at: 0x%x\n", running_offset
);
9792 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
9794 TRACE("impinfo at: 0x%x\n", running_offset
);
9795 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
9797 TRACE("impfiles at: 0x%x\n", running_offset
);
9798 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
9800 TRACE("namehashtab at: 0x%x\n", running_offset
);
9801 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
9803 TRACE("nametab at: 0x%x\n", running_offset
);
9804 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
9806 TRACE("stringtab at: 0x%x\n", running_offset
);
9807 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
9809 TRACE("typdesc at: 0x%x\n", running_offset
);
9810 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
9812 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
9813 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
9815 TRACE("custdata at: 0x%x\n", running_offset
);
9816 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
9818 TRACE("cdguids at: 0x%x\n", running_offset
);
9819 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
9821 TRACE("res0e at: 0x%x\n", running_offset
);
9822 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
9824 TRACE("res0f at: 0x%x\n", running_offset
);
9825 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
9827 TRACE("aux_seg at: 0x%x\n", running_offset
);
9829 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
9831 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
9832 FILE_ATTRIBUTE_NORMAL
, 0);
9833 if (outfile
== INVALID_HANDLE_VALUE
){
9834 WMSFT_free_file(&file
);
9836 return TYPE_E_IOERROR
;
9839 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
9841 WMSFT_free_file(&file
);
9842 CloseHandle(outfile
);
9844 return TYPE_E_IOERROR
;
9847 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
9850 WMSFT_free_file(&file
);
9851 CloseHandle(outfile
);
9852 return TYPE_E_IOERROR
;
9855 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
9857 WMSFT_free_file(&file
);
9858 CloseHandle(outfile
);
9859 return TYPE_E_IOERROR
;
9862 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
9863 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
9864 WMSFT_write_segment(outfile
, &file
.guid_seg
);
9865 WMSFT_write_segment(outfile
, &file
.ref_seg
);
9866 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
9867 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
9868 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
9869 WMSFT_write_segment(outfile
, &file
.name_seg
);
9870 WMSFT_write_segment(outfile
, &file
.string_seg
);
9871 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
9872 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
9873 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
9874 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
9875 WMSFT_write_segment(outfile
, &file
.aux_seg
);
9877 WMSFT_free_file(&file
);
9879 CloseHandle(outfile
);
9884 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
9887 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9888 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
9892 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
9893 REFGUID guid
, VARIANT
*varVal
)
9895 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9896 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
9900 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
9901 ULONG helpStringContext
)
9903 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9904 FIXME("%p %u - stub\n", This
, helpStringContext
);
9908 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
9911 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9912 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
9915 return E_INVALIDARG
;
9917 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
9922 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
9923 ICreateTypeLib2_fnQueryInterface
,
9924 ICreateTypeLib2_fnAddRef
,
9925 ICreateTypeLib2_fnRelease
,
9926 ICreateTypeLib2_fnCreateTypeInfo
,
9927 ICreateTypeLib2_fnSetName
,
9928 ICreateTypeLib2_fnSetVersion
,
9929 ICreateTypeLib2_fnSetGuid
,
9930 ICreateTypeLib2_fnSetDocString
,
9931 ICreateTypeLib2_fnSetHelpFileName
,
9932 ICreateTypeLib2_fnSetHelpContext
,
9933 ICreateTypeLib2_fnSetLcid
,
9934 ICreateTypeLib2_fnSetLibFlags
,
9935 ICreateTypeLib2_fnSaveAllChanges
,
9936 ICreateTypeLib2_fnDeleteTypeInfo
,
9937 ICreateTypeLib2_fnSetCustData
,
9938 ICreateTypeLib2_fnSetHelpStringContext
,
9939 ICreateTypeLib2_fnSetHelpStringDll
9942 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
9943 REFIID riid
, void **object
)
9945 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9947 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
9950 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
9952 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9954 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
9957 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
9959 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9961 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
9964 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
9967 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9969 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9971 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
9976 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
9979 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
9983 TRACE("%p %x\n", This
, typeFlags
);
9985 if (typeFlags
& TYPEFLAG_FDUAL
) {
9986 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
9988 ITypeInfo
*dispatch
;
9992 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
9996 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
9997 ITypeLib_Release(stdole
);
10001 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10002 ITypeInfo_Release(dispatch
);
10007 old_flags
= This
->wTypeFlags
;
10008 This
->wTypeFlags
= typeFlags
;
10010 hres
= ICreateTypeInfo2_LayOut(iface
);
10011 if (FAILED(hres
)) {
10012 This
->wTypeFlags
= old_flags
;
10019 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10022 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10024 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10027 return E_INVALIDARG
;
10029 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10034 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10037 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10039 TRACE("%p %d\n", This
, helpContext
);
10041 This
->dwHelpContext
= helpContext
;
10046 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10047 WORD majorVerNum
, WORD minorVerNum
)
10049 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10051 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10053 This
->wMajorVerNum
= majorVerNum
;
10054 This
->wMinorVerNum
= minorVerNum
;
10059 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10060 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10062 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10064 ITypeLib
*container
;
10065 TLBRefType
*ref_type
;
10067 TYPEATTR
*typeattr
;
10071 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10073 if (!typeInfo
|| !refType
)
10074 return E_INVALIDARG
;
10076 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10080 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10081 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10083 ITypeLib_Release(container
);
10085 *refType
= target
->hreftype
;
10090 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10091 if (FAILED(hres
)) {
10092 ITypeLib_Release(container
);
10096 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10097 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10098 implib
->lcid
== libattr
->lcid
&&
10099 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10100 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10104 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10105 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10107 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10108 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10109 implib
->name
= SysAllocString(our_container
->path
);
10111 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10112 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10114 implib
->name
= NULL
;
10115 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10119 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10120 implib
->lcid
= libattr
->lcid
;
10121 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10122 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10124 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10127 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10128 ITypeLib_Release(container
);
10130 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10135 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10136 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10137 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10138 ref_type
->tkind
== typeattr
->typekind
)
10143 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10144 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10146 ref_type
->tkind
= typeattr
->typekind
;
10147 ref_type
->pImpTLInfo
= implib
;
10148 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10150 ref_type
->index
= TLB_REF_USE_GUID
;
10152 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10154 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10157 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10159 *refType
= ref_type
->reference
| 0x1;
10161 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10162 This
->pTypeLib
->dispatch_href
= *refType
;
10167 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10168 UINT index
, FUNCDESC
*funcDesc
)
10170 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10171 TLBFuncDesc tmp_func_desc
, *func_desc
;
10176 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10178 if (!funcDesc
|| funcDesc
->oVft
& 3)
10179 return E_INVALIDARG
;
10181 switch (This
->typekind
) {
10183 if (funcDesc
->funckind
!= FUNC_STATIC
)
10184 return TYPE_E_BADMODULEKIND
;
10186 case TKIND_DISPATCH
:
10187 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10188 return TYPE_E_BADMODULEKIND
;
10191 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10192 return TYPE_E_BADMODULEKIND
;
10195 if (index
> This
->cFuncs
)
10196 return TYPE_E_ELEMENTNOTFOUND
;
10198 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10199 !funcDesc
->cParams
)
10200 return TYPE_E_INCONSISTENTPROPFUNCS
;
10202 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10203 TLBFuncDesc_Constructor(&tmp_func_desc
);
10205 tmp_func_desc
.funcdesc
= *funcDesc
;
10207 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10208 tmp_func_desc
.funcdesc
.oVft
|= 1;
10210 if (funcDesc
->cScodes
) {
10211 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10212 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10214 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10216 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10217 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10218 buf_size
+= sizeof(ELEMDESC
);
10219 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10221 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10222 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10224 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10225 if (FAILED(hres
)) {
10226 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10227 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10231 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10232 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10233 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10234 if (FAILED(hres
)) {
10235 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10236 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10239 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10240 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10241 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10242 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10243 if (FAILED(hres
)) {
10244 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10245 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10251 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10253 if (This
->funcdescs
) {
10254 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10255 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10257 if (index
< This
->cFuncs
) {
10258 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10259 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10260 func_desc
= This
->funcdescs
+ index
;
10262 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10264 /* move custdata lists to the new memory location */
10265 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10267 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10268 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10269 list_init(&fd
->custdata_list
);
10271 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10272 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10277 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10279 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10280 list_init(&func_desc
->custdata_list
);
10284 This
->needs_layout
= TRUE
;
10289 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10290 UINT index
, HREFTYPE refType
)
10292 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10293 TLBImplType
*impl_type
;
10296 TRACE("%p %u %d\n", This
, index
, refType
);
10298 switch(This
->typekind
){
10299 case TKIND_COCLASS
: {
10301 FIXME("Unhandled index: -1\n");
10305 if(index
!= This
->cImplTypes
)
10306 return TYPE_E_ELEMENTNOTFOUND
;
10310 case TKIND_INTERFACE
:
10311 case TKIND_DISPATCH
:
10312 if (index
!= 0 || This
->cImplTypes
)
10313 return TYPE_E_ELEMENTNOTFOUND
;
10316 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10320 if (This
->impltypes
){
10323 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10324 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10326 if (index
< This
->cImplTypes
) {
10327 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10328 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10329 impl_type
= This
->impltypes
+ index
;
10331 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10333 /* move custdata lists to the new memory location */
10334 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10336 TLBImplType
*it
= &This
->impltypes
[i
];
10337 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10338 list_init(&it
->custdata_list
);
10340 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10341 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10346 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10348 memset(impl_type
, 0, sizeof(TLBImplType
));
10349 TLBImplType_Constructor(impl_type
);
10350 impl_type
->hRef
= refType
;
10352 ++This
->cImplTypes
;
10354 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10355 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10357 hres
= ICreateTypeInfo2_LayOut(iface
);
10364 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10365 UINT index
, INT implTypeFlags
)
10367 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10368 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10370 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10372 if (This
->typekind
!= TKIND_COCLASS
)
10373 return TYPE_E_BADMODULEKIND
;
10375 if (index
>= This
->cImplTypes
)
10376 return TYPE_E_ELEMENTNOTFOUND
;
10378 impl_type
->implflags
= implTypeFlags
;
10383 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10386 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10388 TRACE("%p %d\n", This
, alignment
);
10390 This
->cbAlignment
= alignment
;
10395 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10398 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10400 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10403 return E_INVALIDARG
;
10405 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10407 This
->lpstrSchema
= This
->Schema
->str
;
10412 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10413 UINT index
, VARDESC
*varDesc
)
10415 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10416 TLBVarDesc
*var_desc
;
10418 TRACE("%p %u %p\n", This
, index
, varDesc
);
10420 if (This
->vardescs
){
10423 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10424 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10426 if (index
< This
->cVars
) {
10427 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10428 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10429 var_desc
= This
->vardescs
+ index
;
10431 var_desc
= This
->vardescs
+ This
->cVars
;
10433 /* move custdata lists to the new memory location */
10434 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10436 TLBVarDesc
*var
= &This
->vardescs
[i
];
10437 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10438 list_init(&var
->custdata_list
);
10440 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10441 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10446 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10448 TLBVarDesc_Constructor(var_desc
);
10449 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10450 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10454 This
->needs_layout
= TRUE
;
10459 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10460 UINT index
, LPOLESTR
*names
, UINT numNames
)
10462 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10463 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10466 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10469 return E_INVALIDARG
;
10471 if (index
>= This
->cFuncs
|| numNames
== 0)
10472 return TYPE_E_ELEMENTNOTFOUND
;
10474 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10475 if(numNames
> func_desc
->funcdesc
.cParams
)
10476 return TYPE_E_ELEMENTNOTFOUND
;
10478 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10479 return TYPE_E_ELEMENTNOTFOUND
;
10481 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10482 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10483 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10484 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10485 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10486 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10488 return TYPE_E_AMBIGUOUSNAME
;
10492 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10494 for (i
= 1; i
< numNames
; ++i
) {
10495 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10496 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10502 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10503 UINT index
, LPOLESTR name
)
10505 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10506 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(name
));
10510 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10511 TYPEDESC
*tdescAlias
)
10513 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10514 FIXME("%p %p - stub\n", This
, tdescAlias
);
10518 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10519 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10521 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10522 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10526 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10527 UINT index
, LPOLESTR docString
)
10529 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10530 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(docString
));
10534 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10535 UINT index
, LPOLESTR docString
)
10537 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10538 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10540 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10543 return E_INVALIDARG
;
10545 if(index
>= This
->cVars
)
10546 return TYPE_E_ELEMENTNOTFOUND
;
10548 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10553 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10554 UINT index
, DWORD helpContext
)
10556 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10557 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10559 TRACE("%p %u %d\n", This
, index
, helpContext
);
10561 if(index
>= This
->cFuncs
)
10562 return TYPE_E_ELEMENTNOTFOUND
;
10564 func_desc
->helpcontext
= helpContext
;
10569 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10570 UINT index
, DWORD helpContext
)
10572 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10573 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10575 TRACE("%p %u %d\n", This
, index
, helpContext
);
10577 if(index
>= This
->cVars
)
10578 return TYPE_E_ELEMENTNOTFOUND
;
10580 var_desc
->HelpContext
= helpContext
;
10585 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10586 UINT index
, BSTR bstrMops
)
10588 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10589 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10593 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10596 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10598 TRACE("%p %p\n", This
, idlDesc
);
10601 return E_INVALIDARG
;
10603 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10604 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10609 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10611 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10613 TLBFuncDesc
*func_desc
;
10614 UINT user_vft
= 0, i
, depth
= 0;
10615 HRESULT hres
= S_OK
;
10617 TRACE("%p\n", This
);
10619 This
->needs_layout
= FALSE
;
10621 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10625 if (This
->typekind
== TKIND_INTERFACE
) {
10630 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10632 if (SUCCEEDED(hres
)) {
10633 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10635 if (SUCCEEDED(hres
)) {
10636 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10637 if (FAILED(hres
)) {
10638 ITypeInfo_Release(inh
);
10639 ITypeInfo_Release(tinfo
);
10642 This
->cbSizeVft
= attr
->cbSizeVft
;
10643 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10647 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10648 if(SUCCEEDED(hres
)){
10650 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10651 if(SUCCEEDED(hres
)){
10652 ITypeInfo_Release(inh
);
10656 }while(SUCCEEDED(hres
));
10659 ITypeInfo_Release(inh
);
10660 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10661 This
->cbSizeVft
= 0;
10664 ITypeInfo_Release(tinfo
);
10667 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10668 This
->cbSizeVft
= 0;
10671 ITypeInfo_Release(tinfo
);
10674 } else if (This
->typekind
== TKIND_DISPATCH
)
10675 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10677 This
->cbSizeVft
= 0;
10679 func_desc
= This
->funcdescs
;
10681 while (i
< This
->cFuncs
) {
10682 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10683 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10685 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10686 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10688 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10690 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10693 BOOL reset
= FALSE
;
10695 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10697 iter
= This
->funcdescs
;
10698 while (j
< This
->cFuncs
) {
10699 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10701 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10704 ++func_desc
->funcdesc
.memid
;
10705 iter
= This
->funcdescs
;
10718 if (user_vft
> This
->cbSizeVft
)
10719 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10721 ITypeInfo_Release(tinfo
);
10725 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
10728 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10729 FIXME("%p %u - stub\n", This
, index
);
10733 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
10734 MEMBERID memid
, INVOKEKIND invKind
)
10736 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10737 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
10741 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
10744 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10745 FIXME("%p %u - stub\n", This
, index
);
10749 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
10752 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10753 FIXME("%p %x - stub\n", This
, memid
);
10757 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
10760 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10761 FIXME("%p %u - stub\n", This
, index
);
10765 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
10766 REFGUID guid
, VARIANT
*varVal
)
10770 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10772 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10774 if (!guid
|| !varVal
)
10775 return E_INVALIDARG
;
10777 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
10779 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
10782 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
10783 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10785 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10786 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10790 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
10791 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
10793 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10794 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
10798 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
10799 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10801 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10802 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10806 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
10807 UINT index
, REFGUID guid
, VARIANT
*varVal
)
10809 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10810 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
10814 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
10815 ULONG helpStringContext
)
10817 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10819 TRACE("%p %u\n", This
, helpStringContext
);
10821 This
->dwHelpStringContext
= helpStringContext
;
10826 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
10827 UINT index
, ULONG helpStringContext
)
10829 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10830 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
10834 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
10835 UINT index
, ULONG helpStringContext
)
10837 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10838 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
10842 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
10844 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10845 FIXME("%p - stub\n", This
);
10849 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
10852 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10854 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
10857 return E_INVALIDARG
;
10859 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10864 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
10865 ICreateTypeInfo2_fnQueryInterface
,
10866 ICreateTypeInfo2_fnAddRef
,
10867 ICreateTypeInfo2_fnRelease
,
10868 ICreateTypeInfo2_fnSetGuid
,
10869 ICreateTypeInfo2_fnSetTypeFlags
,
10870 ICreateTypeInfo2_fnSetDocString
,
10871 ICreateTypeInfo2_fnSetHelpContext
,
10872 ICreateTypeInfo2_fnSetVersion
,
10873 ICreateTypeInfo2_fnAddRefTypeInfo
,
10874 ICreateTypeInfo2_fnAddFuncDesc
,
10875 ICreateTypeInfo2_fnAddImplType
,
10876 ICreateTypeInfo2_fnSetImplTypeFlags
,
10877 ICreateTypeInfo2_fnSetAlignment
,
10878 ICreateTypeInfo2_fnSetSchema
,
10879 ICreateTypeInfo2_fnAddVarDesc
,
10880 ICreateTypeInfo2_fnSetFuncAndParamNames
,
10881 ICreateTypeInfo2_fnSetVarName
,
10882 ICreateTypeInfo2_fnSetTypeDescAlias
,
10883 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
10884 ICreateTypeInfo2_fnSetFuncDocString
,
10885 ICreateTypeInfo2_fnSetVarDocString
,
10886 ICreateTypeInfo2_fnSetFuncHelpContext
,
10887 ICreateTypeInfo2_fnSetVarHelpContext
,
10888 ICreateTypeInfo2_fnSetMops
,
10889 ICreateTypeInfo2_fnSetTypeIdldesc
,
10890 ICreateTypeInfo2_fnLayOut
,
10891 ICreateTypeInfo2_fnDeleteFuncDesc
,
10892 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
10893 ICreateTypeInfo2_fnDeleteVarDesc
,
10894 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
10895 ICreateTypeInfo2_fnDeleteImplType
,
10896 ICreateTypeInfo2_fnSetCustData
,
10897 ICreateTypeInfo2_fnSetFuncCustData
,
10898 ICreateTypeInfo2_fnSetParamCustData
,
10899 ICreateTypeInfo2_fnSetVarCustData
,
10900 ICreateTypeInfo2_fnSetImplTypeCustData
,
10901 ICreateTypeInfo2_fnSetHelpStringContext
,
10902 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
10903 ICreateTypeInfo2_fnSetVarHelpStringContext
,
10904 ICreateTypeInfo2_fnInvalidate
,
10905 ICreateTypeInfo2_fnSetName
10908 /******************************************************************************
10909 * ClearCustData (OLEAUT32.171)
10911 * Clear a custom data type's data.
10914 * lpCust [I] The custom data type instance
10919 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
10921 if (lpCust
&& lpCust
->cCustData
)
10923 if (lpCust
->prgCustData
)
10927 for (i
= 0; i
< lpCust
->cCustData
; i
++)
10928 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
10930 /* FIXME - Should be using a per-thread IMalloc */
10931 heap_free(lpCust
->prgCustData
);
10932 lpCust
->prgCustData
= NULL
;
10934 lpCust
->cCustData
= 0;