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
);
289 struct tlibredirect_data
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
305 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
307 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
311 WCHAR Path
[MAX_PATH
];
314 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
318 ACTCTX_SECTION_KEYED_DATA data
;
320 data
.cbSize
= sizeof(data
);
321 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
323 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
327 if (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
)
328 return TYPE_E_LIBNOTREGISTERED
;
330 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
331 len
= SearchPathW( NULL
, nameW
, NULL
, sizeof(Path
)/sizeof(WCHAR
), Path
, NULL
);
332 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
334 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
335 *path
= SysAllocString( Path
);
340 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
341 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
343 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
344 if (res
== ERROR_FILE_NOT_FOUND
)
346 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
347 return TYPE_E_LIBNOTREGISTERED
;
349 else if (res
!= ERROR_SUCCESS
)
351 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
352 return TYPE_E_REGISTRYACCESS
;
357 LONG dwPathLen
= sizeof(Path
);
359 get_lcid_subkey( myLCID
, syskind
, buffer
);
361 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
365 else if (myLCID
== lcid
)
367 /* try with sub-langid */
368 myLCID
= SUBLANGID(lcid
);
370 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
372 /* try with system langid */
382 *path
= SysAllocString( Path
);
387 TRACE_(typelib
)("-- 0x%08x\n", hr
);
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
401 * path [O] path of typelib
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
409 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
413 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
418 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
428 HRESULT WINAPI
CreateTypeLib(
429 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
453 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
454 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
466 HRESULT WINAPI
LoadTypeLibEx(
467 LPCOLESTR szFile
, /* [in] Name of file to load from */
468 REGKIND regkind
, /* [in] Specify kind of registration */
469 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath
[MAX_PATH
+1];
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
478 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
483 case REGKIND_DEFAULT
:
484 /* don't register typelibs supplied with full path. Experimentation confirms the following */
485 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
486 (szFile
[0] && (szFile
[1] == ':'))) break;
487 /* else fall-through */
489 case REGKIND_REGISTER
:
490 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
492 ITypeLib_Release(*pptLib
);
500 TRACE(" returns %08x\n",res
);
504 /******************************************************************************
505 * LoadRegTypeLib [OLEAUT32.162]
507 * Loads a registered type library.
510 * rguid [I] GUID of the registered type library.
511 * wVerMajor [I] major version.
512 * wVerMinor [I] minor version.
513 * lcid [I] locale ID.
514 * ppTLib [O] pointer that receives an ITypeLib object on success.
518 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
521 HRESULT WINAPI
LoadRegTypeLib(
533 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
537 res
= LoadTypeLib(bstr
, ppTLib
);
544 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
547 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
548 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
552 ITypeLib_Release(*ppTLib
);
554 res
= TYPE_E_LIBNOTREGISTERED
;
560 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
566 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
567 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
568 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
569 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
570 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
571 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
573 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
578 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
579 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
580 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
582 get_interface_key( &tattr
->guid
, keyName
);
583 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
584 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
587 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
588 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
590 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
591 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
592 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
593 (const BYTE
*)PSOA
, sizeof PSOA
);
597 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
598 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
599 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
600 (const BYTE
*)PSOA
, sizeof PSOA
);
604 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
605 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
608 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
609 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
611 StringFromGUID2(&libattr
->guid
, buffer
, 40);
612 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
613 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
614 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
615 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
616 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
624 /******************************************************************************
625 * RegisterTypeLib [OLEAUT32.163]
626 * Adds information about a type library to the System Registry
628 * Docs: ITypeLib FAR * ptlib
629 * Docs: OLECHAR FAR* szFullPath
630 * Docs: OLECHAR FAR* szHelpDir
636 HRESULT WINAPI
RegisterTypeLib(
637 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
638 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
639 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
651 if (ptlib
== NULL
|| szFullPath
== NULL
)
654 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
658 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
661 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
664 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
665 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
669 /* Set the human-readable name of the typelib */
670 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
674 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
675 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
681 /* Make up the name of the typelib path subkey */
682 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
684 /* Create the typelib path subkey */
685 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
686 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
688 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
689 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
697 /* Create the flags subkey */
698 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
699 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
701 /* FIXME: is %u correct? */
702 static const WCHAR formatW
[] = {'%','u',0};
704 sprintfW(buf
, formatW
, attr
->wLibFlags
);
705 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
706 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
714 /* create the helpdir subkey */
715 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
716 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
718 BOOL freeHelpDir
= FALSE
;
721 /* if we created a new key, and helpDir was null, set the helpdir
722 to the directory which contains the typelib. However,
723 if we just opened an existing key, we leave the helpdir alone */
724 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
725 szHelpDir
= SysAllocString(szFullPath
);
726 pIndexStr
= strrchrW(szHelpDir
, '\\');
733 /* if we have an szHelpDir, set it! */
734 if (szHelpDir
!= NULL
) {
735 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
736 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
742 if (freeHelpDir
) SysFreeString(szHelpDir
);
754 /* register OLE Automation-compatible interfaces for this typelib */
755 types
= ITypeLib_GetTypeInfoCount(ptlib
);
756 for (tidx
=0; tidx
<types
; tidx
++) {
757 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
758 LPOLESTR name
= NULL
;
759 ITypeInfo
*tinfo
= NULL
;
761 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
764 case TKIND_INTERFACE
:
765 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
766 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
770 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
771 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
775 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
780 TYPEATTR
*tattr
= NULL
;
781 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
784 TRACE_(typelib
)("guid=%s, flags=%04x (",
785 debugstr_guid(&tattr
->guid
),
788 if (TRACE_ON(typelib
)) {
789 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
809 /* Register all dispinterfaces (which includes dual interfaces) and
810 oleautomation interfaces */
811 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
812 kind
== TKIND_DISPATCH
)
815 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
817 /* register interface<->typelib coupling */
818 TLB_register_interface(attr
, name
, tattr
, 0);
820 /* register TLBs into the opposite registry view, too */
821 if(opposite
== KEY_WOW64_32KEY
||
822 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
823 TLB_register_interface(attr
, name
, tattr
, opposite
);
826 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
829 ITypeInfo_Release(tinfo
);
836 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
841 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
843 WCHAR subKeyName
[50];
846 /* the path to the type */
847 get_interface_key( guid
, subKeyName
);
849 /* Delete its bits */
850 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
853 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
854 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
855 RegDeleteKeyW(subKey
, TypeLibW
);
857 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
860 /******************************************************************************
861 * UnRegisterTypeLib [OLEAUT32.186]
862 * Removes information about a type library from the System Registry
869 HRESULT WINAPI
UnRegisterTypeLib(
870 REFGUID libid
, /* [in] Guid of the library */
871 WORD wVerMajor
, /* [in] major version */
872 WORD wVerMinor
, /* [in] minor version */
873 LCID lcid
, /* [in] locale id */
876 BSTR tlibPath
= NULL
;
879 WCHAR subKeyName
[50];
882 BOOL deleteOtherStuff
;
884 TYPEATTR
* typeAttr
= NULL
;
886 ITypeInfo
* typeInfo
= NULL
;
887 ITypeLib
* typeLib
= NULL
;
890 TRACE("(IID: %s)\n",debugstr_guid(libid
));
892 /* Create the path to the key */
893 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
895 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
897 TRACE("Unsupported syskind %i\n", syskind
);
898 result
= E_INVALIDARG
;
902 /* get the path to the typelib on disk */
903 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
904 result
= E_INVALIDARG
;
908 /* Try and open the key to the type library. */
909 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
910 result
= E_INVALIDARG
;
914 /* Try and load the type library */
915 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
916 result
= TYPE_E_INVALIDSTATE
;
920 /* remove any types registered with this typelib */
921 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
922 for (i
=0; i
<numTypes
; i
++) {
923 /* get the kind of type */
924 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
928 /* skip non-interfaces, and get type info for the type */
929 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
932 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
935 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
939 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
940 kind
== TKIND_DISPATCH
)
943 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
945 TLB_unregister_interface(&typeAttr
->guid
, 0);
947 /* unregister TLBs into the opposite registry view, too */
948 if(opposite
== KEY_WOW64_32KEY
||
949 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
950 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
955 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
957 if (typeInfo
) ITypeInfo_Release(typeInfo
);
961 /* Now, delete the type library path subkey */
962 get_lcid_subkey( lcid
, syskind
, subKeyName
);
963 RegDeleteKeyW(key
, subKeyName
);
964 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
965 RegDeleteKeyW(key
, subKeyName
);
967 /* check if there is anything besides the FLAGS/HELPDIR keys.
968 If there is, we don't delete them */
969 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
970 deleteOtherStuff
= TRUE
;
972 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
973 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
975 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
976 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
977 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
978 deleteOtherStuff
= FALSE
;
982 /* only delete the other parts of the key if we're absolutely sure */
983 if (deleteOtherStuff
) {
984 RegDeleteKeyW(key
, FLAGSW
);
985 RegDeleteKeyW(key
, HELPDIRW
);
989 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
990 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
991 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
995 SysFreeString(tlibPath
);
996 if (typeLib
) ITypeLib_Release(typeLib
);
997 if (key
) RegCloseKey(key
);
1001 /******************************************************************************
1002 * RegisterTypeLibForUser [OLEAUT32.442]
1003 * Adds information about a type library to the user registry
1005 * Docs: ITypeLib FAR * ptlib
1006 * Docs: OLECHAR FAR* szFullPath
1007 * Docs: OLECHAR FAR* szHelpDir
1013 HRESULT WINAPI
RegisterTypeLibForUser(
1014 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1015 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1016 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1019 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1020 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1021 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1024 /******************************************************************************
1025 * UnRegisterTypeLibForUser [OLEAUT32.443]
1026 * Removes information about a type library from the user registry
1032 HRESULT WINAPI
UnRegisterTypeLibForUser(
1033 REFGUID libid
, /* [in] GUID of the library */
1034 WORD wVerMajor
, /* [in] major version */
1035 WORD wVerMinor
, /* [in] minor version */
1036 LCID lcid
, /* [in] locale id */
1039 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1040 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1041 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1044 /*======================= ITypeLib implementation =======================*/
1046 typedef struct tagTLBGuid
{
1053 typedef struct tagTLBCustData
1060 /* data structure for import typelibs */
1061 typedef struct tagTLBImpLib
1063 int offset
; /* offset in the file (MSFT)
1064 offset in nametable (SLTG)
1065 just used to identify library while reading
1067 TLBGuid
*guid
; /* libid */
1068 BSTR name
; /* name */
1070 LCID lcid
; /* lcid of imported typelib */
1072 WORD wVersionMajor
; /* major version number */
1073 WORD wVersionMinor
; /* minor version number */
1075 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1076 NULL if not yet loaded */
1080 typedef struct tagTLBString
{
1086 /* internal ITypeLib data */
1087 typedef struct tagITypeLibImpl
1089 ITypeLib2 ITypeLib2_iface
;
1090 ITypeComp ITypeComp_iface
;
1091 ICreateTypeLib2 ICreateTypeLib2_iface
;
1102 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1103 * exported to the application as a UNICODE string.
1105 struct list string_list
;
1106 struct list name_list
;
1107 struct list guid_list
;
1109 const TLBString
*Name
;
1110 const TLBString
*DocString
;
1111 const TLBString
*HelpFile
;
1112 const TLBString
*HelpStringDll
;
1113 DWORD dwHelpContext
;
1114 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1115 struct tagITypeInfoImpl
**typeinfos
;
1116 struct list custdata_list
;
1117 struct list implib_list
;
1118 int ctTypeDesc
; /* number of items in type desc array */
1119 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1120 library. Only used while reading MSFT
1122 struct list ref_list
; /* list of ref types in this typelib */
1123 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1126 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1132 static const ITypeLib2Vtbl tlbvt
;
1133 static const ITypeCompVtbl tlbtcvt
;
1134 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1136 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1138 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1141 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1143 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1146 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1148 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1151 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1153 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1156 /* ITypeLib methods */
1157 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1158 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1160 /*======================= ITypeInfo implementation =======================*/
1162 /* data for referenced types */
1163 typedef struct tagTLBRefType
1165 INT index
; /* Type index for internal ref or for external ref
1166 it the format is SLTG. -2 indicates to
1170 TLBGuid
*guid
; /* guid of the referenced type */
1171 /* if index == TLB_REF_USE_GUID */
1173 HREFTYPE reference
; /* The href of this ref */
1174 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1175 TLB_REF_INTERNAL for internal refs
1176 TLB_REF_NOT_FOUND for broken refs */
1181 #define TLB_REF_USE_GUID -2
1183 #define TLB_REF_INTERNAL (void*)-2
1184 #define TLB_REF_NOT_FOUND (void*)-1
1186 /* internal Parameter data */
1187 typedef struct tagTLBParDesc
1189 const TLBString
*Name
;
1190 struct list custdata_list
;
1193 /* internal Function data */
1194 typedef struct tagTLBFuncDesc
1196 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1197 const TLBString
*Name
; /* the name of this function */
1198 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1200 int HelpStringContext
;
1201 const TLBString
*HelpString
;
1202 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1203 struct list custdata_list
;
1206 /* internal Variable data */
1207 typedef struct tagTLBVarDesc
1209 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1210 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1211 const TLBString
*Name
; /* the name of this variable */
1213 int HelpStringContext
;
1214 const TLBString
*HelpString
;
1215 struct list custdata_list
;
1218 /* internal implemented interface data */
1219 typedef struct tagTLBImplType
1221 HREFTYPE hRef
; /* hRef of interface */
1222 int implflags
; /* IMPLFLAG_*s */
1223 struct list custdata_list
;
1226 /* internal TypeInfo data */
1227 typedef struct tagITypeInfoImpl
1229 ITypeInfo2 ITypeInfo2_iface
;
1230 ITypeComp ITypeComp_iface
;
1231 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1233 BOOL not_attached_to_typelib
;
1238 MEMBERID memidConstructor
;
1239 MEMBERID memidDestructor
;
1240 LPOLESTR lpstrSchema
;
1241 ULONG cbSizeInstance
;
1251 TYPEDESC
*tdescAlias
;
1252 IDLDESC idldescType
;
1254 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1255 int index
; /* index in this typelib; */
1256 HREFTYPE hreftype
; /* hreftype for app object binding */
1257 /* type libs seem to store the doc strings in ascii
1258 * so why should we do it in unicode?
1260 const TLBString
*Name
;
1261 const TLBString
*DocString
;
1262 const TLBString
*DllName
;
1263 const TLBString
*Schema
;
1264 DWORD dwHelpContext
;
1265 DWORD dwHelpStringContext
;
1268 TLBFuncDesc
*funcdescs
;
1271 TLBVarDesc
*vardescs
;
1273 /* Implemented Interfaces */
1274 TLBImplType
*impltypes
;
1276 struct list
*pcustdata_list
;
1277 struct list custdata_list
;
1280 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1282 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1285 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1287 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1290 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1292 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1295 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1297 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1300 static const ITypeInfo2Vtbl tinfvt
;
1301 static const ITypeCompVtbl tcompvt
;
1302 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1304 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1305 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1307 typedef struct tagTLBContext
1309 unsigned int oStart
; /* start of TLB in file */
1310 unsigned int pos
; /* current pos */
1311 unsigned int length
; /* total length */
1312 void *mapping
; /* memory mapping */
1313 MSFT_SegDir
* pTblDir
;
1314 ITypeLibImpl
* pLibInfo
;
1318 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1320 return str
!= NULL
? str
->str
: NULL
;
1323 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1327 return memcmp(left
, str
->str
, len
);
1330 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1332 return guid
!= NULL
? &guid
->guid
: NULL
;
1335 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1337 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1340 static int get_ptr_size(SYSKIND syskind
)
1350 WARN("Unhandled syskind: 0x%x\n", syskind
);
1357 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1358 if (pTD
->vt
& VT_RESERVED
)
1359 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1360 if (pTD
->vt
& VT_BYREF
)
1361 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1362 if (pTD
->vt
& VT_ARRAY
)
1363 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1364 if (pTD
->vt
& VT_VECTOR
)
1365 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1366 switch(pTD
->vt
& VT_TYPEMASK
) {
1367 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1368 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1369 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1370 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1371 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1372 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1373 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1374 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1375 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1376 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1377 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1378 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1379 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1380 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1381 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1382 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1383 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1384 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1385 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1386 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1387 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1388 pTD
->u
.hreftype
); break;
1389 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1390 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1391 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1392 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1394 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1395 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1397 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1398 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1399 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1402 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1406 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1408 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1409 dump_TypeDesc(&edesc
->tdesc
,buf
);
1410 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1411 MESSAGE("\t\tu.paramdesc.wParamFlags");
1412 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1413 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1414 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1415 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1416 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1417 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1418 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1419 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1420 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1422 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1424 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1425 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1426 MESSAGE("Param %d:\n",i
);
1427 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1429 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1430 switch (funcdesc
->funckind
) {
1431 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1432 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1433 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1434 case FUNC_STATIC
: MESSAGE("static");break;
1435 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1436 default: MESSAGE("unknown");break;
1438 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1439 switch (funcdesc
->invkind
) {
1440 case INVOKE_FUNC
: MESSAGE("func");break;
1441 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1442 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1443 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1445 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1446 switch (funcdesc
->callconv
) {
1447 case CC_CDECL
: MESSAGE("cdecl");break;
1448 case CC_PASCAL
: MESSAGE("pascal");break;
1449 case CC_STDCALL
: MESSAGE("stdcall");break;
1450 case CC_SYSCALL
: MESSAGE("syscall");break;
1453 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1454 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1455 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1457 MESSAGE("\telemdescFunc (return value type):\n");
1458 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1461 static const char * const typekind_desc
[] =
1474 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1477 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1478 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1479 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1482 dump_FUNCDESC(&(pfd
->funcdesc
));
1484 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1485 if(pfd
->Entry
== NULL
)
1486 MESSAGE("\tentry: (null)\n");
1487 else if(pfd
->Entry
== (void*)-1)
1488 MESSAGE("\tentry: invalid\n");
1489 else if(IS_INTRESOURCE(pfd
->Entry
))
1490 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1492 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1494 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1498 dump_TLBFuncDescOne(pfd
);
1503 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1507 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1513 static void dump_TLBImpLib(const TLBImpLib
*import
)
1515 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1516 debugstr_w(import
->name
));
1517 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1518 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1521 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1525 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1527 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1528 if(ref
->index
== -1)
1529 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1531 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1533 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1535 TRACE_(typelib
)("in lib\n");
1536 dump_TLBImpLib(ref
->pImpTLInfo
);
1541 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1546 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1547 impl
->hRef
, impl
->implflags
);
1553 static void dump_DispParms(const DISPPARAMS
* pdp
)
1557 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1559 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1561 TRACE("named args:\n");
1562 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1563 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1566 if (pdp
->cArgs
&& pdp
->rgvarg
)
1569 for (index
= 0; index
< pdp
->cArgs
; index
++)
1570 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1574 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1576 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1577 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1578 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1579 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1580 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1581 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1582 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1583 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1585 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1586 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1587 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1590 static void dump_VARDESC(const VARDESC
*v
)
1592 MESSAGE("memid %d\n",v
->memid
);
1593 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1594 MESSAGE("oInst %d\n",v
->u
.oInst
);
1595 dump_ELEMDESC(&(v
->elemdescVar
));
1596 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1597 MESSAGE("varkind %d\n",v
->varkind
);
1600 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1602 /* VT_LPWSTR is largest type that, may appear in type description */
1603 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1604 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1605 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1606 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1607 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1608 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1609 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1610 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1613 static void TLB_abort(void)
1618 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1620 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1621 if (!ret
) ERR("cannot allocate memory\n");
1625 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1627 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1628 if (!ret
) ERR("cannot allocate memory\n");
1632 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1634 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1637 void heap_free(void *ptr
)
1639 HeapFree(GetProcessHeap(), 0, ptr
);
1642 /* returns the size required for a deep copy of a typedesc into a
1644 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1648 if (alloc_initial_space
)
1649 size
+= sizeof(TYPEDESC
);
1655 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1658 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1659 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1665 /* deep copy a typedesc into a flat buffer */
1666 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1671 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1680 dest
->u
.lptdesc
= buffer
;
1681 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1684 dest
->u
.lpadesc
= buffer
;
1685 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1686 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1687 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1693 /* free custom data allocated by MSFT_CustData */
1694 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1696 TLBCustData
*cd
, *cdn
;
1697 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1699 list_remove(&cd
->entry
);
1700 VariantClear(&cd
->data
);
1705 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1710 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1711 ret
= SysAllocStringLen(NULL
, len
- 1);
1712 if (!ret
) return ret
;
1713 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1717 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1718 UINT n
, MEMBERID memid
)
1721 if(funcdescs
->funcdesc
.memid
== memid
)
1729 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1730 UINT n
, MEMBERID memid
)
1733 if(vardescs
->vardesc
.memid
== memid
)
1741 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1742 UINT n
, const OLECHAR
*name
)
1745 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1753 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1755 TLBCustData
*cust_data
;
1756 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1757 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1762 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1763 UINT n
, const OLECHAR
*name
)
1766 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1774 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1776 list_init(&var_desc
->custdata_list
);
1779 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1783 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1788 TLBVarDesc_Constructor(&ret
[n
-1]);
1795 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1799 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1804 list_init(&ret
[n
-1].custdata_list
);
1811 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1813 list_init(&func_desc
->custdata_list
);
1816 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1820 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1825 TLBFuncDesc_Constructor(&ret
[n
-1]);
1832 static void TLBImplType_Constructor(TLBImplType
*impl
)
1834 list_init(&impl
->custdata_list
);
1837 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1841 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1846 TLBImplType_Constructor(&ret
[n
-1]);
1853 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1854 const GUID
*new_guid
, HREFTYPE hreftype
)
1858 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1859 if (IsEqualGUID(&guid
->guid
, new_guid
))
1863 guid
= heap_alloc(sizeof(TLBGuid
));
1867 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1868 guid
->hreftype
= hreftype
;
1870 list_add_tail(guid_list
, &guid
->entry
);
1875 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1877 TLBCustData
*cust_data
;
1889 return DISP_E_BADVARTYPE
;
1892 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1895 cust_data
= heap_alloc(sizeof(TLBCustData
));
1897 return E_OUTOFMEMORY
;
1899 cust_data
->guid
= tlbguid
;
1900 VariantInit(&cust_data
->data
);
1902 list_add_tail(custdata_list
, &cust_data
->entry
);
1904 VariantClear(&cust_data
->data
);
1906 return VariantCopy(&cust_data
->data
, var
);
1909 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1916 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1917 if (strcmpW(str
->str
, new_str
) == 0)
1921 str
= heap_alloc(sizeof(TLBString
));
1925 str
->str
= SysAllocString(new_str
);
1931 list_add_tail(string_list
, &str
->entry
);
1936 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1937 ULONG
*size
, WORD
*align
)
1943 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1947 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1949 ITypeInfo_Release(other
);
1954 *size
= attr
->cbSizeInstance
;
1956 *align
= attr
->cbAlignment
;
1958 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1959 ITypeInfo_Release(other
);
1964 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1965 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1967 ULONG i
, sub
, ptr_size
;
1970 ptr_size
= get_ptr_size(sys
);
2009 *size
= sizeof(DATE
);
2012 *size
= sizeof(VARIANT
);
2014 if(sys
== SYS_WIN32
)
2015 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2019 *size
= sizeof(DECIMAL
);
2026 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2027 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2028 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2033 case VT_USERDEFINED
:
2034 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2036 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2050 /**********************************************************************
2052 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2055 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2057 if (where
!= DO_NOT_SEEK
)
2059 where
+= pcx
->oStart
;
2060 if (where
> pcx
->length
)
2063 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2071 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2073 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2074 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2076 MSFT_Seek(pcx
, where
);
2077 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2078 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2083 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2088 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2089 FromLEDWords(buffer
, ret
);
2094 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2099 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2100 FromLEWords(buffer
, ret
);
2105 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2108 MSFT_GuidEntry entry
;
2111 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2113 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2116 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2118 guid
= heap_alloc(sizeof(TLBGuid
));
2120 guid
->offset
= offs
;
2121 guid
->guid
= entry
.guid
;
2122 guid
->hreftype
= entry
.hreftype
;
2124 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2126 offs
+= sizeof(MSFT_GuidEntry
);
2130 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2134 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2135 if(ret
->offset
== offset
){
2136 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2144 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2146 MSFT_NameIntro niName
;
2150 ERR_(typelib
)("bad offset %d\n", offset
);
2154 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2155 pcx
->pTblDir
->pNametab
.offset
+offset
);
2157 return niName
.hreftype
;
2160 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2163 MSFT_NameIntro intro
;
2165 int offs
= 0, lengthInChars
;
2167 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2171 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2174 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2175 intro
.namelen
&= 0xFF;
2176 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2178 len_piece
= (len_piece
+ 4) & ~0x3;
2182 string
= heap_alloc(len_piece
+ 1);
2183 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2184 string
[intro
.namelen
] = '\0';
2186 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2187 string
, -1, NULL
, 0);
2188 if (!lengthInChars
) {
2190 return E_UNEXPECTED
;
2193 tlbstr
= heap_alloc(sizeof(TLBString
));
2195 tlbstr
->offset
= offs
;
2196 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2197 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2201 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2207 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2211 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2212 if (tlbstr
->offset
== offset
) {
2213 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2221 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2225 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2226 if (tlbstr
->offset
== offset
) {
2227 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2236 * read a value and fill a VARIANT structure
2238 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2242 TRACE_(typelib
)("\n");
2244 if(offset
<0) { /* data are packed in here */
2245 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2246 V_I4(pVar
) = offset
& 0x3ffffff;
2249 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2250 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2251 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2252 switch (V_VT(pVar
)){
2253 case VT_EMPTY
: /* FIXME: is this right? */
2254 case VT_NULL
: /* FIXME: is this right? */
2255 case VT_I2
: /* this should not happen */
2266 case VT_VOID
: /* FIXME: is this right? */
2274 case VT_DECIMAL
: /* FIXME: is this right? */
2277 /* pointer types with known behaviour */
2280 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2282 V_BSTR(pVar
) = NULL
;
2284 ptr
= heap_alloc_zero(size
);
2285 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2286 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2287 /* FIXME: do we need a AtoW conversion here? */
2288 V_UNION(pVar
, bstrVal
[size
])='\0';
2289 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2294 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2301 case VT_USERDEFINED
:
2307 case VT_STREAMED_OBJECT
:
2308 case VT_STORED_OBJECT
:
2309 case VT_BLOB_OBJECT
:
2314 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2318 if(size
>0) /* (big|small) endian correct? */
2319 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2323 * create a linked list with custom data
2325 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2331 TRACE_(typelib
)("\n");
2333 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2337 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2338 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2339 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2340 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2341 list_add_head(custdata_list
, &pNew
->entry
);
2342 offset
= entry
.next
;
2347 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2350 pTd
->vt
=type
& VT_TYPEMASK
;
2352 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2354 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2357 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2359 return (invkind
== INVOKE_PROPERTYGET
||
2360 invkind
== INVOKE_PROPERTYPUT
||
2361 invkind
== INVOKE_PROPERTYPUTREF
);
2365 MSFT_DoFuncs(TLBContext
* pcx
,
2370 TLBFuncDesc
** pptfd
)
2373 * member information is stored in a data structure at offset
2374 * indicated by the memoffset field of the typeinfo structure
2375 * There are several distinctive parts.
2376 * The first part starts with a field that holds the total length
2377 * of this (first) part excluding this field. Then follow the records,
2378 * for each member there is one record.
2380 * The first entry is always the length of the record (including this
2382 * The rest of the record depends on the type of the member. If there is
2383 * a field indicating the member type (function, variable, interface, etc)
2384 * I have not found it yet. At this time we depend on the information
2385 * in the type info and the usual order how things are stored.
2387 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2390 * Third is an equal sized array with file offsets to the name entry
2393 * The fourth and last (?) part is an array with offsets to the records
2394 * in the first part of this file segment.
2397 int infolen
, nameoffset
, reclength
, i
;
2398 int recoffset
= offset
+ sizeof(INT
);
2400 char *recbuf
= heap_alloc(0xffff);
2401 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2402 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2404 TRACE_(typelib
)("\n");
2406 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2408 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2410 for ( i
= 0; i
< cFuncs
; i
++ )
2414 /* name, eventually add to a hash table */
2415 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2416 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2418 /* read the function information record */
2419 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2421 reclength
&= 0xffff;
2423 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2425 /* size without argument data */
2426 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2427 if (pFuncRec
->FKCCIC
& 0x1000)
2428 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2430 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2431 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2433 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2434 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2436 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2438 if (pFuncRec
->FKCCIC
& 0x2000 )
2440 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2441 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2442 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2445 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2448 ptfd
->Entry
= (TLBString
*)-1;
2450 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2451 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2453 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2454 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2456 /* fill the FuncDesc Structure */
2457 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2458 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2460 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2461 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2462 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2463 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2464 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2465 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2466 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2468 /* nameoffset is sometimes -1 on the second half of a propget/propput
2469 * pair of functions */
2470 if ((nameoffset
== -1) && (i
> 0) &&
2471 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2472 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2473 ptfd
->Name
= ptfd_prev
->Name
;
2475 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2479 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2481 /* do the parameters/arguments */
2482 if(pFuncRec
->nrargs
)
2485 MSFT_ParameterInfo paraminfo
;
2487 ptfd
->funcdesc
.lprgelemdescParam
=
2488 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2490 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2492 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2493 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2495 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2497 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2503 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2506 if (paraminfo
.oName
!= -1)
2507 ptfd
->pParamDesc
[j
].Name
=
2508 MSFT_ReadName( pcx
, paraminfo
.oName
);
2509 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2512 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2513 (pFuncRec
->FKCCIC
& 0x1000) )
2515 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2517 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2519 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2521 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2522 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2524 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2528 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2531 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2532 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2533 pFuncRec
->FKCCIC
& 0x80 )
2536 pFuncRec
->oArgCustData
[j
],
2537 &ptfd
->pParamDesc
[j
].custdata_list
);
2540 /* SEEK value = jump to offset,
2541 * from there jump to the end of record,
2542 * go back by (j-1) arguments
2544 MSFT_ReadLEDWords( ¶minfo
,
2545 sizeof(MSFT_ParameterInfo
), pcx
,
2546 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2547 * sizeof(MSFT_ParameterInfo
)));
2551 /* scode is not used: archaic win16 stuff FIXME: right? */
2552 ptfd
->funcdesc
.cScodes
= 0 ;
2553 ptfd
->funcdesc
.lprgscode
= NULL
;
2557 recoffset
+= reclength
;
2562 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2563 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2565 int infolen
, nameoffset
, reclength
;
2567 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2572 TRACE_(typelib
)("\n");
2574 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2575 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2576 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2577 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2578 recoffset
+= offset
+sizeof(INT
);
2579 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2580 /* name, eventually add to a hash table */
2581 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2582 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2583 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2584 /* read the variable information record */
2585 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2587 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2590 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2591 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2593 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2594 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2596 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2597 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2599 /* fill the VarDesc Structure */
2600 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2601 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2602 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2603 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2604 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2605 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2606 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2607 if(pVarRec
->VarKind
== VAR_CONST
){
2608 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2609 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2610 pVarRec
->OffsValue
, pcx
);
2612 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2613 recoffset
+= reclength
;
2617 /* process Implemented Interfaces of a com class */
2618 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2622 MSFT_RefRecord refrec
;
2625 TRACE_(typelib
)("\n");
2627 pTI
->impltypes
= TLBImplType_Alloc(count
);
2628 pImpl
= pTI
->impltypes
;
2629 for(i
=0;i
<count
;i
++){
2630 if(offset
<0) break; /* paranoia */
2631 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2632 pImpl
->hRef
= refrec
.reftype
;
2633 pImpl
->implflags
=refrec
.flags
;
2634 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2635 offset
=refrec
.onext
;
2641 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2642 * and some structures, and fix the alignment */
2643 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2645 if(info
->typekind
== TKIND_ALIAS
){
2646 switch(info
->tdescAlias
->vt
){
2654 info
->cbSizeInstance
= sizeof(void*);
2655 info
->cbAlignment
= sizeof(void*);
2658 case VT_USERDEFINED
:
2659 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2662 info
->cbSizeInstance
= sizeof(VARIANT
);
2663 info
->cbAlignment
= 8;
2665 if(info
->cbSizeInstance
< sizeof(void*))
2666 info
->cbAlignment
= info
->cbSizeInstance
;
2668 info
->cbAlignment
= sizeof(void*);
2671 }else if(info
->typekind
== TKIND_INTERFACE
||
2672 info
->typekind
== TKIND_DISPATCH
||
2673 info
->typekind
== TKIND_COCLASS
){
2674 info
->cbSizeInstance
= sizeof(void*);
2675 info
->cbAlignment
= sizeof(void*);
2681 * process a typeinfo record
2683 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2686 ITypeLibImpl
* pLibInfo
)
2688 MSFT_TypeInfoBase tiBase
;
2689 ITypeInfoImpl
*ptiRet
;
2691 TRACE_(typelib
)("count=%u\n", count
);
2693 ptiRet
= ITypeInfoImpl_Constructor();
2694 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2695 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2697 /* this is where we are coming from */
2698 ptiRet
->pTypeLib
= pLibInfo
;
2699 ptiRet
->index
=count
;
2701 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2702 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2703 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2704 ptiRet
->cbSizeInstance
=tiBase
.size
;
2705 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2706 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2707 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2708 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2709 ptiRet
->wTypeFlags
=tiBase
.flags
;
2710 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2711 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2712 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2713 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2714 if(ptiRet
->typekind
== TKIND_ALIAS
){
2716 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2717 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2718 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2722 /* IDLDESC idldescType; *//* never saw this one != zero */
2724 /* name, eventually add to a hash table */
2725 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2726 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2727 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2729 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2730 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2731 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2733 if (ptiRet
->typekind
== TKIND_MODULE
)
2734 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2736 /* note: InfoType's Help file and HelpStringDll come from the containing
2737 * library. Further HelpString and Docstring appear to be the same thing :(
2740 if(ptiRet
->cFuncs
>0 )
2741 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2743 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2745 if(ptiRet
->cVars
>0 )
2746 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2748 tiBase
.memoffset
, &ptiRet
->vardescs
);
2749 if(ptiRet
->cImplTypes
>0 ) {
2750 switch(ptiRet
->typekind
)
2753 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2756 case TKIND_DISPATCH
:
2757 /* This is not -1 when the interface is a non-base dual interface or
2758 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2759 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2763 if (tiBase
.datatype1
!= -1)
2765 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2766 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2770 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2771 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2775 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2777 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2778 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2779 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2780 typekind_desc
[ptiRet
->typekind
]);
2781 if (TRACE_ON(typelib
))
2782 dump_TypeInfo(ptiRet
);
2787 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2790 INT16 len_str
, len_piece
;
2791 int offs
= 0, lengthInChars
;
2793 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2797 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2800 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2801 len_piece
= len_str
+ sizeof(INT16
);
2803 len_piece
= (len_piece
+ 4) & ~0x3;
2807 string
= heap_alloc(len_piece
+ 1);
2808 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2809 string
[len_str
] = '\0';
2811 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2812 string
, -1, NULL
, 0);
2813 if (!lengthInChars
) {
2815 return E_UNEXPECTED
;
2818 tlbstr
= heap_alloc(sizeof(TLBString
));
2820 tlbstr
->offset
= offs
;
2821 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2822 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2826 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2832 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2837 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2838 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2839 MSFT_ImpInfo impinfo
;
2842 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2844 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2845 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2847 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2848 if(pImpLib
->offset
==impinfo
.oImpFile
)
2851 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2852 ref
->reference
= offs
;
2853 ref
->pImpTLInfo
= pImpLib
;
2854 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2855 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2856 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2857 ref
->index
= TLB_REF_USE_GUID
;
2859 ref
->index
= impinfo
.oGuid
;
2861 ERR("Cannot find a reference\n");
2862 ref
->reference
= -1;
2863 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2866 offs
+= sizeof(impinfo
);
2872 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2873 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2874 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2877 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2878 static CRITICAL_SECTION cache_section
;
2879 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2881 0, 0, &cache_section
,
2882 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2883 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2885 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2888 typedef struct TLB_PEFile
2890 IUnknown IUnknown_iface
;
2893 HRSRC typelib_resource
;
2894 HGLOBAL typelib_global
;
2895 LPVOID typelib_base
;
2898 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2900 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2903 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2905 if (IsEqualIID(riid
, &IID_IUnknown
))
2908 IUnknown_AddRef(iface
);
2912 return E_NOINTERFACE
;
2915 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2917 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2918 return InterlockedIncrement(&This
->refs
);
2921 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2923 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2924 ULONG refs
= InterlockedDecrement(&This
->refs
);
2927 if (This
->typelib_global
)
2928 FreeResource(This
->typelib_global
);
2930 FreeLibrary(This
->dll
);
2936 static const IUnknownVtbl TLB_PEFile_Vtable
=
2938 TLB_PEFile_QueryInterface
,
2943 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2946 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2948 This
= heap_alloc(sizeof(TLB_PEFile
));
2950 return E_OUTOFMEMORY
;
2952 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2955 This
->typelib_resource
= NULL
;
2956 This
->typelib_global
= NULL
;
2957 This
->typelib_base
= NULL
;
2959 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2960 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2964 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2965 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2966 if (This
->typelib_resource
)
2968 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2969 if (This
->typelib_global
)
2971 This
->typelib_base
= LockResource(This
->typelib_global
);
2973 if (This
->typelib_base
)
2975 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2976 *ppBase
= This
->typelib_base
;
2977 *ppFile
= &This
->IUnknown_iface
;
2983 TRACE("No TYPELIB resource found\n");
2987 TLB_PEFile_Release(&This
->IUnknown_iface
);
2991 typedef struct TLB_NEFile
2993 IUnknown IUnknown_iface
;
2995 LPVOID typelib_base
;
2998 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
3000 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
3003 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3005 if (IsEqualIID(riid
, &IID_IUnknown
))
3008 IUnknown_AddRef(iface
);
3012 return E_NOINTERFACE
;
3015 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3017 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3018 return InterlockedIncrement(&This
->refs
);
3021 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3023 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3024 ULONG refs
= InterlockedDecrement(&This
->refs
);
3027 heap_free(This
->typelib_base
);
3033 static const IUnknownVtbl TLB_NEFile_Vtable
=
3035 TLB_NEFile_QueryInterface
,
3040 /***********************************************************************
3041 * read_xx_header [internal]
3043 static int read_xx_header( HFILE lzfd
)
3045 IMAGE_DOS_HEADER mzh
;
3048 LZSeek( lzfd
, 0, SEEK_SET
);
3049 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3051 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3054 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3055 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3058 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3060 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3061 return IMAGE_OS2_SIGNATURE
;
3062 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3063 return IMAGE_NT_SIGNATURE
;
3066 WARN("Can't handle %s files.\n", magic
);
3071 /***********************************************************************
3072 * find_ne_resource [internal]
3074 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3075 DWORD
*resLen
, DWORD
*resOff
)
3077 IMAGE_OS2_HEADER nehd
;
3078 NE_TYPEINFO
*typeInfo
;
3079 NE_NAMEINFO
*nameInfo
;
3085 /* Read in NE header */
3086 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3087 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3089 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3092 TRACE("No resources in NE dll\n" );
3096 /* Read in resource table */
3097 resTab
= heap_alloc( resTabSize
);
3098 if ( !resTab
) return FALSE
;
3100 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3101 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3103 heap_free( resTab
);
3108 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3110 if (!IS_INTRESOURCE(typeid)) /* named type */
3112 BYTE len
= strlen( typeid );
3113 while (typeInfo
->type_id
)
3115 if (!(typeInfo
->type_id
& 0x8000))
3117 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3118 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3120 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3121 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3124 else /* numeric type id */
3126 WORD id
= LOWORD(typeid) | 0x8000;
3127 while (typeInfo
->type_id
)
3129 if (typeInfo
->type_id
== id
) goto found_type
;
3130 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3131 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3134 TRACE("No typeid entry found for %p\n", typeid );
3135 heap_free( resTab
);
3139 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3141 if (!IS_INTRESOURCE(resid
)) /* named resource */
3143 BYTE len
= strlen( resid
);
3144 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3146 BYTE
*p
= resTab
+ nameInfo
->id
;
3147 if (nameInfo
->id
& 0x8000) continue;
3148 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3151 else /* numeric resource id */
3153 WORD id
= LOWORD(resid
) | 0x8000;
3154 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3155 if (nameInfo
->id
== id
) goto found_name
;
3157 TRACE("No resid entry found for %p\n", typeid );
3158 heap_free( resTab
);
3162 /* Return resource data */
3163 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3164 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3166 heap_free( resTab
);
3170 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3174 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3177 This
= heap_alloc(sizeof(TLB_NEFile
));
3178 if (!This
) return E_OUTOFMEMORY
;
3180 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3182 This
->typelib_base
= NULL
;
3184 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3185 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3187 DWORD reslen
, offset
;
3188 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3190 This
->typelib_base
= heap_alloc(reslen
);
3191 if( !This
->typelib_base
)
3195 LZSeek( lzfd
, offset
, SEEK_SET
);
3196 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3198 *ppBase
= This
->typelib_base
;
3199 *pdwTLBLength
= reslen
;
3200 *ppFile
= &This
->IUnknown_iface
;
3206 if( lzfd
>= 0) LZClose( lzfd
);
3207 TLB_NEFile_Release(&This
->IUnknown_iface
);
3211 typedef struct TLB_Mapping
3213 IUnknown IUnknown_iface
;
3217 LPVOID typelib_base
;
3220 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3222 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3225 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3227 if (IsEqualIID(riid
, &IID_IUnknown
))
3230 IUnknown_AddRef(iface
);
3234 return E_NOINTERFACE
;
3237 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3239 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3240 return InterlockedIncrement(&This
->refs
);
3243 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3245 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3246 ULONG refs
= InterlockedDecrement(&This
->refs
);
3249 if (This
->typelib_base
)
3250 UnmapViewOfFile(This
->typelib_base
);
3252 CloseHandle(This
->mapping
);
3253 if (This
->file
!= INVALID_HANDLE_VALUE
)
3254 CloseHandle(This
->file
);
3260 static const IUnknownVtbl TLB_Mapping_Vtable
=
3262 TLB_Mapping_QueryInterface
,
3267 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3271 This
= heap_alloc(sizeof(TLB_Mapping
));
3273 return E_OUTOFMEMORY
;
3275 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3277 This
->file
= INVALID_HANDLE_VALUE
;
3278 This
->mapping
= NULL
;
3279 This
->typelib_base
= NULL
;
3281 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3282 if (INVALID_HANDLE_VALUE
!= This
->file
)
3284 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3287 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3288 if(This
->typelib_base
)
3290 /* retrieve file size */
3291 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3292 *ppBase
= This
->typelib_base
;
3293 *ppFile
= &This
->IUnknown_iface
;
3299 IUnknown_Release(&This
->IUnknown_iface
);
3300 return TYPE_E_CANTLOADLIBRARY
;
3303 /****************************************************************************
3306 * find the type of the typelib file and map the typelib resource into
3310 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3311 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3313 ITypeLibImpl
*entry
;
3316 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3317 LPVOID pBase
= NULL
;
3318 DWORD dwTLBLength
= 0;
3319 IUnknown
*pFile
= NULL
;
3324 index_str
= strrchrW(pszFileName
, '\\');
3325 if(index_str
&& *++index_str
!= '\0')
3328 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3329 if(*end_ptr
== '\0')
3331 int str_len
= index_str
- pszFileName
- 1;
3333 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3334 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3339 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3341 if(strchrW(file
, '\\'))
3343 lstrcpyW(pszPath
, file
);
3347 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3348 pszPath
[len
] = '\\';
3349 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3353 if(file
!= pszFileName
) heap_free(file
);
3355 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3356 if(h
!= INVALID_HANDLE_VALUE
){
3357 FILE_NAME_INFORMATION
*info
;
3358 char data
[MAX_PATH
* sizeof(WCHAR
) + sizeof(info
->FileNameLength
)];
3361 info
= (FILE_NAME_INFORMATION
*)data
;
3362 /* GetFileInformationByHandleEx returns the path of the file without
3363 * WOW64 redirection */
3364 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, data
, sizeof(data
));
3366 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3367 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3372 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3374 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3375 EnterCriticalSection(&cache_section
);
3376 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3378 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3380 TRACE("cache hit\n");
3381 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3382 ITypeLib2_AddRef(*ppTypeLib
);
3383 LeaveCriticalSection(&cache_section
);
3387 LeaveCriticalSection(&cache_section
);
3389 /* now actually load and parse the typelib */
3391 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3392 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3393 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3394 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3395 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3398 if (dwTLBLength
>= 4)
3400 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3401 if (dwSignature
== MSFT_SIGNATURE
)
3402 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3403 else if (dwSignature
== SLTG_SIGNATURE
)
3404 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3407 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3408 ret
= TYPE_E_CANTLOADLIBRARY
;
3412 ret
= TYPE_E_CANTLOADLIBRARY
;
3413 IUnknown_Release(pFile
);
3417 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3419 TRACE("adding to cache\n");
3420 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3421 lstrcpyW(impl
->path
, pszPath
);
3422 /* We should really canonicalise the path here. */
3423 impl
->index
= index
;
3425 /* FIXME: check if it has added already in the meantime */
3426 EnterCriticalSection(&cache_section
);
3427 list_add_head(&tlb_cache
, &impl
->entry
);
3428 LeaveCriticalSection(&cache_section
);
3434 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3436 ret
= TYPE_E_CANTLOADLIBRARY
;
3443 /*================== ITypeLib(2) Methods ===================================*/
3445 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3447 ITypeLibImpl
* pTypeLibImpl
;
3449 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3450 if (!pTypeLibImpl
) return NULL
;
3452 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3453 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3454 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3455 pTypeLibImpl
->ref
= 1;
3457 list_init(&pTypeLibImpl
->implib_list
);
3458 list_init(&pTypeLibImpl
->custdata_list
);
3459 list_init(&pTypeLibImpl
->name_list
);
3460 list_init(&pTypeLibImpl
->string_list
);
3461 list_init(&pTypeLibImpl
->guid_list
);
3462 list_init(&pTypeLibImpl
->ref_list
);
3463 pTypeLibImpl
->dispatch_href
= -1;
3465 return pTypeLibImpl
;
3468 /****************************************************************************
3469 * ITypeLib2_Constructor_MSFT
3471 * loading an MSFT typelib from an in-memory image
3473 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3477 MSFT_Header tlbHeader
;
3478 MSFT_SegDir tlbSegDir
;
3479 ITypeLibImpl
* pTypeLibImpl
;
3482 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3484 pTypeLibImpl
= TypeLibImpl_Constructor();
3485 if (!pTypeLibImpl
) return NULL
;
3487 /* get pointer to beginning of typelib data */
3491 cx
.pLibInfo
= pTypeLibImpl
;
3492 cx
.length
= dwTLBLength
;
3495 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3496 TRACE_(typelib
)("header:\n");
3497 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3498 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3499 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3502 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3504 /* there is a small amount of information here until the next important
3506 * the segment directory . Try to calculate the amount of data */
3507 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3509 /* now read the segment directory */
3510 TRACE("read segment directory (at %d)\n",lPSegDir
);
3511 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3512 cx
.pTblDir
= &tlbSegDir
;
3514 /* just check two entries */
3515 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3517 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3518 heap_free(pTypeLibImpl
);
3522 MSFT_ReadAllNames(&cx
);
3523 MSFT_ReadAllStrings(&cx
);
3524 MSFT_ReadAllGuids(&cx
);
3526 /* now fill our internal data */
3527 /* TLIBATTR fields */
3528 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3530 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3531 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3532 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3533 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3534 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3536 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3537 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3539 /* name, eventually add to a hash table */
3540 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3543 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3544 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3546 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3549 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3550 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3553 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3556 if(tlbHeader
.CustomDataOffset
>= 0)
3558 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3561 /* fill in type descriptions */
3562 if(tlbSegDir
.pTypdescTab
.length
> 0)
3564 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3566 pTypeLibImpl
->ctTypeDesc
= cTD
;
3567 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3568 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3571 /* FIXME: add several sanity checks here */
3572 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3573 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3575 /* FIXME: check safearray */
3577 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3579 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3581 else if(td
[0] == VT_CARRAY
)
3583 /* array descr table here */
3584 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3586 else if(td
[0] == VT_USERDEFINED
)
3588 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3590 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3593 /* second time around to fill the array subscript info */
3596 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3597 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3599 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3600 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3603 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3605 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3607 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3609 for(j
= 0; j
<td
[2]; j
++)
3611 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3612 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3613 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3614 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3619 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3620 ERR("didn't find array description data\n");
3625 /* imported type libs */
3626 if(tlbSegDir
.pImpFiles
.offset
>0)
3629 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3632 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3636 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3637 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3638 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3640 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3641 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3642 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3643 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3646 name
= heap_alloc_zero(size
+1);
3647 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3648 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3651 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3652 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3654 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3658 MSFT_ReadAllRefs(&cx
);
3660 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3663 if(tlbHeader
.nrtypeinfos
>= 0 )
3665 ITypeInfoImpl
**ppTI
;
3667 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3669 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3671 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3674 (pTypeLibImpl
->TypeInfoCount
)++;
3679 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3680 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3681 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3685 TRACE("(%p)\n", pTypeLibImpl
);
3686 return &pTypeLibImpl
->ITypeLib2_iface
;
3690 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3696 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3697 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3701 guid
->Data4
[0] = s
>> 8;
3702 guid
->Data4
[1] = s
& 0xff;
3705 for(i
= 0; i
< 6; i
++) {
3706 memcpy(b
, str
+ 24 + 2 * i
, 2);
3707 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3712 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3719 bytelen
= *(const WORD
*)ptr
;
3720 if(bytelen
== 0xffff) return 2;
3722 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3723 tmp_str
= SysAllocStringLen(NULL
, len
);
3725 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3726 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3727 SysFreeString(tmp_str
);
3732 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3737 bytelen
= *(const WORD
*)ptr
;
3738 if(bytelen
== 0xffff) return 2;
3739 *str
= heap_alloc(bytelen
+ 1);
3740 memcpy(*str
, ptr
+ 2, bytelen
);
3741 (*str
)[bytelen
] = '\0';
3745 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3750 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3751 if (tlbstr
->offset
== offset
)
3755 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3756 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3757 SysFreeString(tmp_str
);
3762 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3764 char *ptr
= pLibBlk
;
3767 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3768 FIXME("libblk magic = %04x\n", w
);
3773 if((w
= *(WORD
*)ptr
) != 0xffff) {
3774 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3779 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3781 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3783 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3786 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3787 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3790 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3791 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3793 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3796 ptr
+= 4; /* skip res12 */
3798 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3801 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3804 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3807 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3808 ptr
+= sizeof(GUID
);
3810 return ptr
- (char*)pLibBlk
;
3813 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3818 } sltg_ref_lookup_t
;
3820 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3821 HREFTYPE
*typelib_ref
)
3823 if(table
&& typeinfo_ref
< table
->num
)
3825 *typelib_ref
= table
->refs
[typeinfo_ref
];
3829 ERR_(typelib
)("Unable to find reference\n");
3834 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3839 if((*pType
& 0xe00) == 0xe00) {
3841 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3842 pTD
= pTD
->u
.lptdesc
;
3844 switch(*pType
& 0x3f) {
3847 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3848 pTD
= pTD
->u
.lptdesc
;
3851 case VT_USERDEFINED
:
3852 pTD
->vt
= VT_USERDEFINED
;
3853 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3859 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3862 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3864 pTD
->vt
= VT_CARRAY
;
3865 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3866 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3867 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3868 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3870 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3876 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3880 pTD
->vt
= VT_SAFEARRAY
;
3881 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3882 pTD
= pTD
->u
.lptdesc
;
3886 pTD
->vt
= *pType
& 0x3f;
3895 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3896 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3898 /* Handle [in/out] first */
3899 if((*pType
& 0xc000) == 0xc000)
3900 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3901 else if(*pType
& 0x8000)
3902 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3903 else if(*pType
& 0x4000)
3904 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3906 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3909 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3912 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3914 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3918 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3923 TLBRefType
*ref_type
;
3924 sltg_ref_lookup_t
*table
;
3925 HREFTYPE typelib_ref
;
3927 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3928 FIXME("Ref magic = %x\n", pRef
->magic
);
3931 name
= ( (char*)pRef
->names
+ pRef
->number
);
3933 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3934 table
->num
= pRef
->number
>> 3;
3936 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3938 /* We don't want the first href to be 0 */
3939 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3941 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3943 unsigned int lib_offs
, type_num
;
3945 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3947 name
+= SLTG_ReadStringA(name
, &refname
);
3948 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3949 FIXME_(typelib
)("Can't sscanf ref\n");
3950 if(lib_offs
!= 0xffff) {
3953 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3954 if(import
->offset
== lib_offs
)
3957 if(&import
->entry
== &pTL
->implib_list
) {
3958 char fname
[MAX_PATH
+1];
3962 import
= heap_alloc_zero(sizeof(*import
));
3963 import
->offset
= lib_offs
;
3964 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3965 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3966 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3967 &import
->wVersionMajor
,
3968 &import
->wVersionMinor
,
3969 &import
->lcid
, fname
) != 4) {
3970 FIXME_(typelib
)("can't sscanf ref %s\n",
3971 pNameTable
+ lib_offs
+ 40);
3973 len
= strlen(fname
);
3974 if(fname
[len
-1] != '#')
3975 FIXME("fname = %s\n", fname
);
3976 fname
[len
-1] = '\0';
3977 import
->name
= TLB_MultiByteToBSTR(fname
);
3978 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3980 ref_type
->pImpTLInfo
= import
;
3982 /* Store a reference to IDispatch */
3983 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3984 pTL
->dispatch_href
= typelib_ref
;
3986 } else { /* internal ref */
3987 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3989 ref_type
->reference
= typelib_ref
;
3990 ref_type
->index
= type_num
;
3993 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3995 table
->refs
[ref
] = typelib_ref
;
3998 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3999 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
4000 dump_TLBRefType(pTL
);
4004 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
4005 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
4007 SLTG_ImplInfo
*info
;
4008 TLBImplType
*pImplType
;
4009 /* I don't really get this structure, usually it's 0x16 bytes
4010 long, but iuser.tlb contains some that are 0x18 bytes long.
4011 That's ok because we can use the next ptr to jump to the next
4012 one. But how do we know the length of the last one? The WORD
4013 at offs 0x8 might be the clue. For now I'm just assuming that
4014 the last one is the regular 0x16 bytes. */
4016 info
= (SLTG_ImplInfo
*)pBlk
;
4019 if(info
->next
== 0xffff)
4021 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4024 info
= (SLTG_ImplInfo
*)pBlk
;
4025 pTI
->impltypes
= TLBImplType_Alloc(pTI
->cImplTypes
);
4026 pImplType
= pTI
->impltypes
;
4028 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4029 pImplType
->implflags
= info
->impltypeflags
;
4032 if(info
->next
== 0xffff)
4035 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4036 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4038 info
++; /* see comment at top of function */
4042 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4043 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4045 TLBVarDesc
*pVarDesc
;
4046 const TLBString
*prevName
= NULL
;
4047 SLTG_Variable
*pItem
;
4051 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4053 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4054 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4056 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4058 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4059 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4060 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4064 if (pItem
->name
== 0xfffe)
4065 pVarDesc
->Name
= prevName
;
4067 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4069 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4070 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4071 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4073 if(pItem
->flags
& 0x02)
4074 pType
= &pItem
->type
;
4076 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4078 if (pItem
->flags
& ~0xda)
4079 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4081 SLTG_DoElem(pType
, pBlk
,
4082 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4084 if (TRACE_ON(typelib
)) {
4086 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4087 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4090 if (pItem
->flags
& 0x40) {
4091 TRACE_(typelib
)("VAR_DISPATCH\n");
4092 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4094 else if (pItem
->flags
& 0x10) {
4095 TRACE_(typelib
)("VAR_CONST\n");
4096 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4097 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4098 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4099 if (pItem
->flags
& 0x08)
4100 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4102 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4108 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4110 TRACE_(typelib
)("len = %u\n", len
);
4111 if (len
== 0xffff) {
4114 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4115 str
= SysAllocStringLen(NULL
, alloc_len
);
4116 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4118 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4119 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4128 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4129 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4132 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4137 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4138 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4139 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4142 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4143 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4145 if (pItem
->flags
& 0x80)
4146 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4148 prevName
= pVarDesc
->Name
;
4153 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4154 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4156 SLTG_Function
*pFunc
;
4158 TLBFuncDesc
*pFuncDesc
;
4160 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4162 pFuncDesc
= pTI
->funcdescs
;
4163 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4164 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4169 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4170 case SLTG_FUNCTION_MAGIC
:
4171 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4173 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4174 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4176 case SLTG_STATIC_FUNCTION_MAGIC
:
4177 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4180 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4183 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4185 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4186 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4187 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4188 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4189 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4190 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
4192 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4193 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4195 if(pFunc
->retnextopt
& 0x80)
4196 pType
= &pFunc
->rettype
;
4198 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4200 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4202 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4203 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4204 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4206 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4208 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4209 char *paramName
= pNameTable
+ *pArg
;
4211 /* If arg type follows then paramName points to the 2nd
4212 letter of the name, else the next WORD is an offset to
4213 the arg type and paramName points to the first letter.
4214 So let's take one char off paramName and see if we're
4215 pointing at an alpha-numeric char. However if *pArg is
4216 0xffff or 0xfffe then the param has no name, the former
4217 meaning that the next WORD is the type, the latter
4218 meaning that the next WORD is an offset to the type. */
4223 else if(*pArg
== 0xfffe) {
4227 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4232 if(HaveOffs
) { /* the next word is an offset to type */
4233 pType
= (WORD
*)(pBlk
+ *pArg
);
4234 SLTG_DoElem(pType
, pBlk
,
4235 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4240 pArg
= SLTG_DoElem(pArg
, pBlk
,
4241 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4244 /* Are we an optional param ? */
4245 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4246 pFuncDesc
->funcdesc
.cParamsOpt
)
4247 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4250 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4251 paramName
- pNameTable
, pTI
->pTypeLib
);
4253 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4257 pTI
->cFuncs
= cFuncs
;
4260 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4261 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4262 SLTG_TypeInfoTail
*pTITail
)
4265 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4267 if(pTIHeader
->href_table
!= 0xffffffff) {
4268 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4274 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4275 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4277 heap_free(ref_lookup
);
4281 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4282 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4283 const SLTG_TypeInfoTail
*pTITail
)
4286 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4288 if(pTIHeader
->href_table
!= 0xffffffff) {
4289 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4295 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4296 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4299 if (pTITail
->funcs_off
!= 0xffff)
4300 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4302 heap_free(ref_lookup
);
4304 if (TRACE_ON(typelib
))
4305 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4308 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4309 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4310 const SLTG_TypeInfoTail
*pTITail
)
4312 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4315 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4316 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4317 const SLTG_TypeInfoTail
*pTITail
)
4320 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4322 if (pTITail
->simple_alias
) {
4323 /* if simple alias, no more processing required */
4324 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4325 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4329 if(pTIHeader
->href_table
!= 0xffffffff) {
4330 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4334 /* otherwise it is an offset to a type */
4335 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4337 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4338 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4340 heap_free(ref_lookup
);
4343 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4344 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4345 const SLTG_TypeInfoTail
*pTITail
)
4347 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4348 if (pTIHeader
->href_table
!= 0xffffffff)
4349 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4352 if (pTITail
->vars_off
!= 0xffff)
4353 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4355 if (pTITail
->funcs_off
!= 0xffff)
4356 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4358 if (pTITail
->impls_off
!= 0xffff)
4359 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4361 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4362 * of dispinterface functions including the IDispatch ones, so
4363 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4364 pTI
->cbSizeVft
= pTI
->cFuncs
* pTI
->pTypeLib
->ptr_size
;
4366 heap_free(ref_lookup
);
4367 if (TRACE_ON(typelib
))
4368 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->cFuncs
);
4371 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4372 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4373 const SLTG_TypeInfoTail
*pTITail
)
4375 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4378 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4379 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4380 const SLTG_TypeInfoTail
*pTITail
)
4382 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4383 if (pTIHeader
->href_table
!= 0xffffffff)
4384 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4387 if (pTITail
->vars_off
!= 0xffff)
4388 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4390 if (pTITail
->funcs_off
!= 0xffff)
4391 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4392 heap_free(ref_lookup
);
4393 if (TRACE_ON(typelib
))
4397 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4398 manageable copy of it into this */
4411 } SLTG_InternalOtherTypeInfo
;
4413 /****************************************************************************
4414 * ITypeLib2_Constructor_SLTG
4416 * loading a SLTG typelib from an in-memory image
4418 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4420 ITypeLibImpl
*pTypeLibImpl
;
4421 SLTG_Header
*pHeader
;
4422 SLTG_BlkEntry
*pBlkEntry
;
4426 LPVOID pBlk
, pFirstBlk
;
4427 SLTG_LibBlk
*pLibBlk
;
4428 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4429 char *pAfterOTIBlks
= NULL
;
4430 char *pNameTable
, *ptr
;
4433 ITypeInfoImpl
**ppTypeInfoImpl
;
4435 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4438 pTypeLibImpl
= TypeLibImpl_Constructor();
4439 if (!pTypeLibImpl
) return NULL
;
4443 TRACE_(typelib
)("header:\n");
4444 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4445 pHeader
->nrOfFileBlks
);
4446 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4447 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4448 pHeader
->SLTG_magic
);
4452 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4453 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4455 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4456 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4458 /* Next we have a magic block */
4459 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4461 /* Let's see if we're still in sync */
4462 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4463 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4464 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4467 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4468 sizeof(SLTG_DIR_MAGIC
))) {
4469 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4473 pIndex
= (SLTG_Index
*)(pMagic
+1);
4475 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4477 pFirstBlk
= pPad9
+ 1;
4479 /* We'll set up a ptr to the main library block, which is the last one. */
4481 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4482 pBlkEntry
[order
].next
!= 0;
4483 order
= pBlkEntry
[order
].next
- 1, i
++) {
4484 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4488 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4490 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4495 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4497 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4500 ptr
= (char*)pLibBlk
+ len
;
4502 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4506 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4508 w
= *(WORD
*)(ptr
+ 2);
4511 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4512 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4513 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4515 w
= *(WORD
*)(ptr
+ 4 + len
);
4517 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4519 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4520 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4521 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4523 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4524 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4525 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4527 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4528 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4531 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4532 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4533 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4534 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4535 len
+= sizeof(SLTG_OtherTypeInfo
);
4539 pAfterOTIBlks
= ptr
;
4541 /* Skip this WORD and get the next DWORD */
4542 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4544 /* Now add this to pLibBLk look at what we're pointing at and
4545 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4546 dust and we should be pointing at the beginning of the name
4549 pNameTable
= (char*)pLibBlk
+ len
;
4551 switch(*(WORD
*)pNameTable
) {
4558 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4562 pNameTable
+= 0x216;
4566 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4568 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4571 /* Hopefully we now have enough ptrs set up to actually read in
4572 some TypeInfos. It's not clear which order to do them in, so
4573 I'll just follow the links along the BlkEntry chain and read
4574 them in the order in which they are in the file */
4576 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4577 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4579 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4580 pBlkEntry
[order
].next
!= 0;
4581 order
= pBlkEntry
[order
].next
- 1, i
++) {
4583 SLTG_TypeInfoHeader
*pTIHeader
;
4584 SLTG_TypeInfoTail
*pTITail
;
4585 SLTG_MemberHeader
*pMemHeader
;
4587 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4588 FIXME_(typelib
)("Index strings don't match\n");
4589 heap_free(pOtherTypeInfoBlks
);
4594 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4595 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4596 heap_free(pOtherTypeInfoBlks
);
4599 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4600 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4601 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4603 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4604 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4605 (*ppTypeInfoImpl
)->index
= i
;
4606 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4607 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4608 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4609 (*ppTypeInfoImpl
)->typekind
= pTIHeader
->typekind
;
4610 (*ppTypeInfoImpl
)->wMajorVerNum
= pTIHeader
->major_version
;
4611 (*ppTypeInfoImpl
)->wMinorVerNum
= pTIHeader
->minor_version
;
4612 (*ppTypeInfoImpl
)->wTypeFlags
=
4613 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4615 if((*ppTypeInfoImpl
)->wTypeFlags
& TYPEFLAG_FDUAL
)
4616 (*ppTypeInfoImpl
)->typekind
= TKIND_DISPATCH
;
4618 if((pTIHeader
->typeflags1
& 7) != 2)
4619 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4620 if(pTIHeader
->typeflags3
!= 2)
4621 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4623 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4624 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4625 typekind_desc
[pTIHeader
->typekind
],
4626 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4627 (*ppTypeInfoImpl
)->wTypeFlags
);
4629 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4631 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4633 (*ppTypeInfoImpl
)->cbAlignment
= pTITail
->cbAlignment
;
4634 (*ppTypeInfoImpl
)->cbSizeInstance
= pTITail
->cbSizeInstance
;
4635 (*ppTypeInfoImpl
)->cbSizeVft
= pTITail
->cbSizeVft
;
4637 switch(pTIHeader
->typekind
) {
4639 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4640 pTIHeader
, pTITail
);
4644 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4645 pTIHeader
, pTITail
);
4648 case TKIND_INTERFACE
:
4649 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4650 pTIHeader
, pTITail
);
4654 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4655 pTIHeader
, pTITail
);
4659 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4660 pTIHeader
, pTITail
);
4663 case TKIND_DISPATCH
:
4664 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4665 pTIHeader
, pTITail
);
4669 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4670 pTIHeader
, pTITail
);
4674 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4679 /* could get cFuncs, cVars and cImplTypes from here
4680 but we've already set those */
4681 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4697 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4700 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4701 FIXME("Somehow processed %d TypeInfos\n", i
);
4702 heap_free(pOtherTypeInfoBlks
);
4706 heap_free(pOtherTypeInfoBlks
);
4707 return &pTypeLibImpl
->ITypeLib2_iface
;
4710 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4712 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4714 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4716 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4717 IsEqualIID(riid
,&IID_ITypeLib
)||
4718 IsEqualIID(riid
,&IID_ITypeLib2
))
4720 *ppv
= &This
->ITypeLib2_iface
;
4722 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4723 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4725 *ppv
= &This
->ICreateTypeLib2_iface
;
4730 TRACE("-- Interface: E_NOINTERFACE\n");
4731 return E_NOINTERFACE
;
4734 IUnknown_AddRef((IUnknown
*)*ppv
);
4738 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4740 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4741 ULONG ref
= InterlockedIncrement(&This
->ref
);
4743 TRACE("(%p) ref=%u\n", This
, ref
);
4748 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4750 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4751 ULONG ref
= InterlockedDecrement(&This
->ref
);
4753 TRACE("(%p) ref=%u\n",This
, ref
);
4757 TLBImpLib
*pImpLib
, *pImpLibNext
;
4758 TLBRefType
*ref_type
;
4759 TLBString
*tlbstr
, *tlbstr_next
;
4760 TLBGuid
*tlbguid
, *tlbguid_next
;
4764 /* remove cache entry */
4767 TRACE("removing from cache list\n");
4768 EnterCriticalSection(&cache_section
);
4769 if(This
->entry
.next
)
4770 list_remove(&This
->entry
);
4771 LeaveCriticalSection(&cache_section
);
4772 heap_free(This
->path
);
4774 TRACE(" destroying ITypeLib(%p)\n",This
);
4776 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4777 list_remove(&tlbstr
->entry
);
4778 SysFreeString(tlbstr
->str
);
4782 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4783 list_remove(&tlbstr
->entry
);
4784 SysFreeString(tlbstr
->str
);
4788 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4789 list_remove(&tlbguid
->entry
);
4793 TLB_FreeCustData(&This
->custdata_list
);
4795 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4796 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4797 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4799 heap_free(This
->pTypeDesc
);
4801 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4803 if (pImpLib
->pImpTypeLib
)
4804 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4805 SysFreeString(pImpLib
->name
);
4807 list_remove(&pImpLib
->entry
);
4811 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4813 list_remove(&ref_type
->entry
);
4814 heap_free(ref_type
);
4817 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4818 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4819 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4821 heap_free(This
->typeinfos
);
4829 /* ITypeLib::GetTypeInfoCount
4831 * Returns the number of type descriptions in the type library
4833 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4835 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4836 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4837 return This
->TypeInfoCount
;
4840 /* ITypeLib::GetTypeInfo
4842 * retrieves the specified type description in the library.
4844 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4847 ITypeInfo
**ppTInfo
)
4849 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4851 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4854 return E_INVALIDARG
;
4856 if(index
>= This
->TypeInfoCount
)
4857 return TYPE_E_ELEMENTNOTFOUND
;
4859 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4860 ITypeInfo_AddRef(*ppTInfo
);
4866 /* ITypeLibs::GetTypeInfoType
4868 * Retrieves the type of a type description.
4870 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4875 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4877 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4880 return E_INVALIDARG
;
4882 if(index
>= This
->TypeInfoCount
)
4883 return TYPE_E_ELEMENTNOTFOUND
;
4885 *pTKind
= This
->typeinfos
[index
]->typekind
;
4890 /* ITypeLib::GetTypeInfoOfGuid
4892 * Retrieves the type description that corresponds to the specified GUID.
4895 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4898 ITypeInfo
**ppTInfo
)
4900 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4903 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4905 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4906 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4907 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4908 ITypeInfo_AddRef(*ppTInfo
);
4913 return TYPE_E_ELEMENTNOTFOUND
;
4916 /* ITypeLib::GetLibAttr
4918 * Retrieves the structure that contains the library's attributes.
4921 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4925 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4927 TRACE("(%p, %p)\n", This
, attr
);
4929 if (!attr
) return E_INVALIDARG
;
4931 *attr
= heap_alloc(sizeof(**attr
));
4932 if (!*attr
) return E_OUTOFMEMORY
;
4934 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4935 (*attr
)->lcid
= This
->set_lcid
;
4936 (*attr
)->syskind
= This
->syskind
;
4937 (*attr
)->wMajorVerNum
= This
->ver_major
;
4938 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4939 (*attr
)->wLibFlags
= This
->libflags
;
4944 /* ITypeLib::GetTypeComp
4946 * Enables a client compiler to bind to a library's types, variables,
4947 * constants, and global functions.
4950 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4952 ITypeComp
**ppTComp
)
4954 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4956 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4957 *ppTComp
= &This
->ITypeComp_iface
;
4958 ITypeComp_AddRef(*ppTComp
);
4963 /* ITypeLib::GetDocumentation
4965 * Retrieves the library's documentation string, the complete Help file name
4966 * and path, and the context identifier for the library Help topic in the Help
4969 * On a successful return all non-null BSTR pointers will have been set,
4972 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4976 BSTR
*pBstrDocString
,
4977 DWORD
*pdwHelpContext
,
4978 BSTR
*pBstrHelpFile
)
4980 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4981 HRESULT result
= E_INVALIDARG
;
4984 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4986 pBstrName
, pBstrDocString
,
4987 pdwHelpContext
, pBstrHelpFile
);
4991 /* documentation for the typelib */
4996 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
5004 if (This
->DocString
)
5006 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5010 *pBstrDocString
= NULL
;
5014 *pdwHelpContext
= This
->dwHelpContext
;
5020 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5024 *pBstrHelpFile
= NULL
;
5031 /* for a typeinfo */
5032 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5034 if(SUCCEEDED(result
))
5036 result
= ITypeInfo_GetDocumentation(pTInfo
,
5040 pdwHelpContext
, pBstrHelpFile
);
5042 ITypeInfo_Release(pTInfo
);
5047 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5049 if (pBstrName
) SysFreeString (*pBstrName
);
5051 return STG_E_INSUFFICIENTMEMORY
;
5056 * Indicates whether a passed-in string contains the name of a type or member
5057 * described in the library.
5060 static HRESULT WINAPI
ITypeLib2_fnIsName(
5066 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5068 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5070 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5074 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5075 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5076 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5077 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5078 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5080 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5081 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5082 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5083 goto ITypeLib2_fnIsName_exit
;
5086 for(vrc
= 0; vrc
< pTInfo
->cVars
; ++vrc
){
5087 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5088 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5094 ITypeLib2_fnIsName_exit
:
5095 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5096 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5101 /* ITypeLib::FindName
5103 * Finds occurrences of a type description in a type library. This may be used
5104 * to quickly verify that a name exists in a type library.
5107 static HRESULT WINAPI
ITypeLib2_fnFindName(
5111 ITypeInfo
**ppTInfo
,
5115 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5120 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5122 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5123 return E_INVALIDARG
;
5125 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5126 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5127 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5131 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5132 memid
[count
] = MEMBERID_NIL
;
5133 goto ITypeLib2_fnFindName_exit
;
5136 for(fdc
= 0; fdc
< pTInfo
->cFuncs
; ++fdc
) {
5137 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5139 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5140 memid
[count
] = func
->funcdesc
.memid
;
5141 goto ITypeLib2_fnFindName_exit
;
5145 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->cVars
, name
);
5147 memid
[count
] = var
->vardesc
.memid
;
5148 goto ITypeLib2_fnFindName_exit
;
5152 ITypeLib2_fnFindName_exit
:
5153 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5154 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5157 TRACE("found %d typeinfos\n", count
);
5164 /* ITypeLib::ReleaseTLibAttr
5166 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5169 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5171 TLIBATTR
*pTLibAttr
)
5173 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5174 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5175 heap_free(pTLibAttr
);
5178 /* ITypeLib2::GetCustData
5180 * gets the custom data
5182 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5187 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5188 TLBCustData
*pCData
;
5190 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5192 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5194 return TYPE_E_ELEMENTNOTFOUND
;
5196 VariantInit(pVarVal
);
5197 VariantCopy(pVarVal
, &pCData
->data
);
5202 /* ITypeLib2::GetLibStatistics
5204 * Returns statistics about a type library that are required for efficient
5205 * sizing of hash tables.
5208 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5210 ULONG
*pcUniqueNames
,
5211 ULONG
*pcchUniqueNames
)
5213 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5215 FIXME("(%p): stub!\n", This
);
5217 if(pcUniqueNames
) *pcUniqueNames
=1;
5218 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5222 /* ITypeLib2::GetDocumentation2
5224 * Retrieves the library's documentation string, the complete Help file name
5225 * and path, the localization context to use, and the context ID for the
5226 * library Help topic in the Help file.
5229 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5233 BSTR
*pbstrHelpString
,
5234 DWORD
*pdwHelpStringContext
,
5235 BSTR
*pbstrHelpStringDll
)
5237 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5241 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5243 /* the help string should be obtained from the helpstringdll,
5244 * using the _DLLGetDocumentation function, based on the supplied
5245 * lcid. Nice to do sometime...
5249 /* documentation for the typelib */
5251 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5252 if(pdwHelpStringContext
)
5253 *pdwHelpStringContext
=This
->dwHelpContext
;
5254 if(pbstrHelpStringDll
)
5255 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5261 /* for a typeinfo */
5262 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5264 if(SUCCEEDED(result
))
5266 ITypeInfo2
* pTInfo2
;
5267 result
= ITypeInfo_QueryInterface(pTInfo
,
5269 (LPVOID
*) &pTInfo2
);
5271 if(SUCCEEDED(result
))
5273 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5277 pdwHelpStringContext
,
5278 pbstrHelpStringDll
);
5280 ITypeInfo2_Release(pTInfo2
);
5283 ITypeInfo_Release(pTInfo
);
5289 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5291 TLBCustData
*pCData
;
5295 ct
= list_count(custdata_list
);
5297 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5298 if(!pCustData
->prgCustData
)
5299 return E_OUTOFMEMORY
;
5301 pCustData
->cCustData
= ct
;
5303 cdi
= pCustData
->prgCustData
;
5304 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5305 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5306 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5314 /* ITypeLib2::GetAllCustData
5316 * Gets all custom data items for the library.
5319 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5321 CUSTDATA
*pCustData
)
5323 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5324 TRACE("(%p)->(%p)\n", This
, pCustData
);
5325 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5328 static const ITypeLib2Vtbl tlbvt
= {
5329 ITypeLib2_fnQueryInterface
,
5331 ITypeLib2_fnRelease
,
5332 ITypeLib2_fnGetTypeInfoCount
,
5333 ITypeLib2_fnGetTypeInfo
,
5334 ITypeLib2_fnGetTypeInfoType
,
5335 ITypeLib2_fnGetTypeInfoOfGuid
,
5336 ITypeLib2_fnGetLibAttr
,
5337 ITypeLib2_fnGetTypeComp
,
5338 ITypeLib2_fnGetDocumentation
,
5340 ITypeLib2_fnFindName
,
5341 ITypeLib2_fnReleaseTLibAttr
,
5343 ITypeLib2_fnGetCustData
,
5344 ITypeLib2_fnGetLibStatistics
,
5345 ITypeLib2_fnGetDocumentation2
,
5346 ITypeLib2_fnGetAllCustData
5350 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5352 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5354 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5357 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5359 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5361 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5364 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5366 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5368 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5371 static HRESULT WINAPI
ITypeLibComp_fnBind(
5376 ITypeInfo
** ppTInfo
,
5377 DESCKIND
* pDescKind
,
5380 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5381 BOOL typemismatch
= FALSE
;
5384 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5386 *pDescKind
= DESCKIND_NONE
;
5387 pBindPtr
->lptcomp
= NULL
;
5390 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5391 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5392 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5394 /* FIXME: check wFlags here? */
5395 /* FIXME: we should use a hash table to look this info up using lHash
5396 * instead of an O(n) search */
5397 if ((pTypeInfo
->typekind
== TKIND_ENUM
) ||
5398 (pTypeInfo
->typekind
== TKIND_MODULE
))
5400 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
->str
, szName
))
5402 *pDescKind
= DESCKIND_TYPECOMP
;
5403 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5404 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5405 TRACE("module or enum: %s\n", debugstr_w(szName
));
5410 if ((pTypeInfo
->typekind
== TKIND_MODULE
) ||
5411 (pTypeInfo
->typekind
== TKIND_ENUM
))
5413 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5416 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5417 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5419 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5422 else if (hr
== TYPE_E_TYPEMISMATCH
)
5423 typemismatch
= TRUE
;
5426 if ((pTypeInfo
->typekind
== TKIND_COCLASS
) &&
5427 (pTypeInfo
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5429 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5431 ITypeInfo
*subtypeinfo
;
5433 DESCKIND subdesckind
;
5435 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5436 &subtypeinfo
, &subdesckind
, &subbindptr
);
5437 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5439 TYPEDESC tdesc_appobject
;
5440 const VARDESC vardesc_appobject
=
5443 NULL
, /* lpstrSchema */
5458 VAR_STATIC
/* varkind */
5461 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5462 tdesc_appobject
.vt
= VT_USERDEFINED
;
5464 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5466 /* cleanup things filled in by Bind call so we can put our
5467 * application object data in there instead */
5468 switch (subdesckind
)
5470 case DESCKIND_FUNCDESC
:
5471 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5473 case DESCKIND_VARDESC
:
5474 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5479 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5481 if (pTypeInfo
->hreftype
== -1)
5482 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5484 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5488 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5489 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5490 ITypeInfo_AddRef(*ppTInfo
);
5493 else if (hr
== TYPE_E_TYPEMISMATCH
)
5494 typemismatch
= TRUE
;
5500 TRACE("type mismatch %s\n", debugstr_w(szName
));
5501 return TYPE_E_TYPEMISMATCH
;
5505 TRACE("name not found %s\n", debugstr_w(szName
));
5510 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5514 ITypeInfo
** ppTInfo
,
5515 ITypeComp
** ppTComp
)
5517 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5518 ITypeInfoImpl
*info
;
5520 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5522 if(!szName
|| !ppTInfo
|| !ppTComp
)
5523 return E_INVALIDARG
;
5525 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5532 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5533 ITypeInfo_AddRef(*ppTInfo
);
5534 *ppTComp
= &info
->ITypeComp_iface
;
5535 ITypeComp_AddRef(*ppTComp
);
5540 static const ITypeCompVtbl tlbtcvt
=
5543 ITypeLibComp_fnQueryInterface
,
5544 ITypeLibComp_fnAddRef
,
5545 ITypeLibComp_fnRelease
,
5547 ITypeLibComp_fnBind
,
5548 ITypeLibComp_fnBindType
5551 /*================== ITypeInfo(2) Methods ===================================*/
5552 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5554 ITypeInfoImpl
*pTypeInfoImpl
;
5556 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5559 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5560 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5561 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5562 pTypeInfoImpl
->ref
= 0;
5563 pTypeInfoImpl
->hreftype
= -1;
5564 pTypeInfoImpl
->memidConstructor
= MEMBERID_NIL
;
5565 pTypeInfoImpl
->memidDestructor
= MEMBERID_NIL
;
5566 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5567 list_init(pTypeInfoImpl
->pcustdata_list
);
5569 TRACE("(%p)\n", pTypeInfoImpl
);
5570 return pTypeInfoImpl
;
5573 /* ITypeInfo::QueryInterface
5575 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5580 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5582 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5585 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5586 IsEqualIID(riid
,&IID_ITypeInfo
)||
5587 IsEqualIID(riid
,&IID_ITypeInfo2
))
5589 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5590 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5591 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5594 ITypeInfo2_AddRef(iface
);
5595 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5598 TRACE("-- Interface: E_NOINTERFACE\n");
5599 return E_NOINTERFACE
;
5602 /* ITypeInfo::AddRef
5604 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5606 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5607 ULONG ref
= InterlockedIncrement(&This
->ref
);
5609 TRACE("(%p)->ref is %u\n",This
, ref
);
5611 if (ref
== 1 /* incremented from 0 */)
5612 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5617 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5621 TRACE("destroying ITypeInfo(%p)\n",This
);
5623 for (i
= 0; i
< This
->cFuncs
; ++i
)
5626 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5627 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5629 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5630 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5631 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5632 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5634 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5635 heap_free(pFInfo
->pParamDesc
);
5636 TLB_FreeCustData(&pFInfo
->custdata_list
);
5638 heap_free(This
->funcdescs
);
5640 for(i
= 0; i
< This
->cVars
; ++i
)
5642 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5643 if (pVInfo
->vardesc_create
) {
5644 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5645 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5646 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5647 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5649 TLB_FreeCustData(&pVInfo
->custdata_list
);
5651 heap_free(This
->vardescs
);
5653 if(This
->impltypes
){
5654 for (i
= 0; i
< This
->cImplTypes
; ++i
){
5655 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5656 TLB_FreeCustData(&pImpl
->custdata_list
);
5658 heap_free(This
->impltypes
);
5661 TLB_FreeCustData(&This
->custdata_list
);
5666 /* ITypeInfo::Release
5668 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5670 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5671 ULONG ref
= InterlockedDecrement(&This
->ref
);
5673 TRACE("(%p)->(%u)\n",This
, ref
);
5677 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5678 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5679 if (not_attached_to_typelib
)
5681 /* otherwise This will be freed when typelib is freed */
5687 /* ITypeInfo::GetTypeAttr
5689 * Retrieves a TYPEATTR structure that contains the attributes of the type
5693 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5694 LPTYPEATTR
*ppTypeAttr
)
5696 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5699 TRACE("(%p)\n",This
);
5701 size
= sizeof(**ppTypeAttr
);
5702 if (This
->typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5703 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5705 *ppTypeAttr
= heap_alloc(size
);
5707 return E_OUTOFMEMORY
;
5709 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5710 (*ppTypeAttr
)->lcid
= This
->lcid
;
5711 (*ppTypeAttr
)->memidConstructor
= This
->memidConstructor
;
5712 (*ppTypeAttr
)->memidDestructor
= This
->memidDestructor
;
5713 (*ppTypeAttr
)->lpstrSchema
= This
->lpstrSchema
;
5714 (*ppTypeAttr
)->cbSizeInstance
= This
->cbSizeInstance
;
5715 (*ppTypeAttr
)->typekind
= This
->typekind
;
5716 (*ppTypeAttr
)->cFuncs
= This
->cFuncs
;
5717 (*ppTypeAttr
)->cVars
= This
->cVars
;
5718 (*ppTypeAttr
)->cImplTypes
= This
->cImplTypes
;
5719 (*ppTypeAttr
)->cbSizeVft
= This
->cbSizeVft
;
5720 (*ppTypeAttr
)->cbAlignment
= This
->cbAlignment
;
5721 (*ppTypeAttr
)->wTypeFlags
= This
->wTypeFlags
;
5722 (*ppTypeAttr
)->wMajorVerNum
= This
->wMajorVerNum
;
5723 (*ppTypeAttr
)->wMinorVerNum
= This
->wMinorVerNum
;
5724 (*ppTypeAttr
)->idldescType
= This
->idldescType
;
5726 if (This
->tdescAlias
)
5727 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5728 This
->tdescAlias
, *ppTypeAttr
+ 1);
5730 (*ppTypeAttr
)->tdescAlias
.vt
= VT_EMPTY
;
5731 (*ppTypeAttr
)->tdescAlias
.u
.lptdesc
= NULL
;
5734 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5735 /* This should include all the inherited funcs */
5736 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5737 /* This is always the size of IDispatch's vtbl */
5738 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5739 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5744 /* ITypeInfo::GetTypeComp
5746 * Retrieves the ITypeComp interface for the type description, which enables a
5747 * client compiler to bind to the type description's members.
5750 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5751 ITypeComp
* *ppTComp
)
5753 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5755 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5757 *ppTComp
= &This
->ITypeComp_iface
;
5758 ITypeComp_AddRef(*ppTComp
);
5762 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5764 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5765 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5766 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5770 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5773 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5774 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5776 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5777 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5778 *buffer
+= sizeof(PARAMDESCEX
);
5779 *pparamdescex_dest
= *pparamdescex_src
;
5780 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5781 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5782 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5783 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5786 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5790 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5792 UINT len
= SysStringLen(str
), i
;
5793 for (i
= 0; i
< len
; ++i
)
5799 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5801 if (V_VT(var
) == VT_INT
)
5802 return VariantChangeType(var
, var
, 0, VT_I4
);
5803 else if (V_VT(var
) == VT_UINT
)
5804 return VariantChangeType(var
, var
, 0, VT_UI4
);
5805 else if (V_VT(var
) == VT_BSTR
)
5806 return TLB_SanitizeBSTR(V_BSTR(var
));
5811 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5813 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5814 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5817 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5821 SIZE_T size
= sizeof(*src
);
5825 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5826 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5827 for (i
= 0; i
< src
->cParams
; i
++)
5829 size
+= sizeof(ELEMDESC
);
5830 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5833 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5834 if (!dest
) return E_OUTOFMEMORY
;
5837 if (dispinterface
) /* overwrite funckind */
5838 dest
->funckind
= FUNC_DISPATCH
;
5839 buffer
= (char *)(dest
+ 1);
5841 dest
->oVft
= dest
->oVft
& 0xFFFC;
5843 if (dest
->cScodes
) {
5844 dest
->lprgscode
= (SCODE
*)buffer
;
5845 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5846 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5848 dest
->lprgscode
= NULL
;
5850 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5853 SysFreeString((BSTR
)dest
);
5857 if (dest
->cParams
) {
5858 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5859 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5860 for (i
= 0; i
< src
->cParams
; i
++)
5862 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5868 /* undo the above actions */
5869 for (i
= i
- 1; i
>= 0; i
--)
5870 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5871 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5872 SysFreeString((BSTR
)dest
);
5876 dest
->lprgelemdescParam
= NULL
;
5878 /* special treatment for dispinterfaces: this makes functions appear
5879 * to return their [retval] value when it is really returning an
5881 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5883 if (dest
->cParams
&&
5884 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5886 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5887 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5889 ERR("elemdesc should have started with VT_PTR instead of:\n");
5891 dump_ELEMDESC(elemdesc
);
5892 return E_UNEXPECTED
;
5895 /* copy last parameter to the return value. we are using a flat
5896 * buffer so there is no danger of leaking memory in
5898 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5900 /* remove the last parameter */
5904 /* otherwise this function is made to appear to have no return
5906 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5914 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5916 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5917 if (var_desc
->varkind
== VAR_CONST
)
5918 VariantClear(var_desc
->u
.lpvarValue
);
5919 SysFreeString((BSTR
)var_desc
);
5922 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5924 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5926 if (index
>= This
->cFuncs
)
5927 return TYPE_E_ELEMENTNOTFOUND
;
5929 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5933 /* internal function to make the inherited interfaces' methods appear
5934 * part of the interface */
5935 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5936 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5938 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5940 UINT implemented_funcs
= 0;
5945 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5949 ITypeInfo
*pSubTypeInfo
;
5952 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5956 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5959 &sub_funcs
, hrefoffset
);
5960 implemented_funcs
+= sub_funcs
;
5961 ITypeInfo_Release(pSubTypeInfo
);
5964 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5968 *funcs
= implemented_funcs
+ This
->cFuncs
;
5972 if (index
< implemented_funcs
)
5973 return E_INVALIDARG
;
5974 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5978 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5980 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5983 switch (pTypeDesc
->vt
)
5985 case VT_USERDEFINED
:
5986 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5990 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5993 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
6001 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
6004 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
6005 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
6006 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
6009 /* ITypeInfo::GetFuncDesc
6011 * Retrieves the FUNCDESC structure that contains information about a
6012 * specified function.
6015 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
6016 LPFUNCDESC
*ppFuncDesc
)
6018 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6019 const FUNCDESC
*internal_funcdesc
;
6021 UINT hrefoffset
= 0;
6023 TRACE("(%p) index %d\n", This
, index
);
6026 return E_INVALIDARG
;
6028 if (This
->needs_layout
)
6029 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6031 if (This
->typekind
== TKIND_DISPATCH
)
6032 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
6033 &internal_funcdesc
, NULL
,
6036 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6037 &internal_funcdesc
);
6040 WARN("description for function %d not found\n", index
);
6044 hr
= TLB_AllocAndInitFuncDesc(
6047 This
->typekind
== TKIND_DISPATCH
);
6049 if ((This
->typekind
== TKIND_DISPATCH
) && hrefoffset
)
6050 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6052 TRACE("-- 0x%08x\n", hr
);
6056 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6060 SIZE_T size
= sizeof(*src
);
6063 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6064 if (src
->varkind
== VAR_CONST
)
6065 size
+= sizeof(VARIANT
);
6066 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6068 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6069 if (!dest
) return E_OUTOFMEMORY
;
6072 buffer
= (char *)(dest
+ 1);
6073 if (src
->lpstrSchema
)
6076 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6077 len
= strlenW(src
->lpstrSchema
);
6078 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6079 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6082 if (src
->varkind
== VAR_CONST
)
6086 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6087 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6088 buffer
+= sizeof(VARIANT
);
6089 VariantInit(dest
->u
.lpvarValue
);
6090 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6093 SysFreeString((BSTR
)dest
);
6097 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6100 if (src
->varkind
== VAR_CONST
)
6101 VariantClear(dest
->u
.lpvarValue
);
6102 SysFreeString((BSTR
)dest
);
6109 /* ITypeInfo::GetVarDesc
6111 * Retrieves a VARDESC structure that describes the specified variable.
6114 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6115 LPVARDESC
*ppVarDesc
)
6117 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6118 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6120 TRACE("(%p) index %d\n", This
, index
);
6122 if(index
>= This
->cVars
)
6123 return TYPE_E_ELEMENTNOTFOUND
;
6125 if (This
->needs_layout
)
6126 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6128 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6131 /* ITypeInfo_GetNames
6133 * Retrieves the variable with the specified member ID (or the name of the
6134 * property or method and its parameters) that correspond to the specified
6137 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6138 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6140 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6141 const TLBFuncDesc
*pFDesc
;
6142 const TLBVarDesc
*pVDesc
;
6144 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6147 return E_INVALIDARG
;
6151 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
6154 if(!cMaxNames
|| !pFDesc
->Name
)
6157 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6160 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6161 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6163 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6169 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
6172 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6177 if(This
->impltypes
&&
6178 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
6179 /* recursive search */
6182 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6183 if(SUCCEEDED(result
))
6185 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6186 ITypeInfo_Release(pTInfo
);
6189 WARN("Could not search inherited interface!\n");
6193 WARN("no names found\n");
6196 return TYPE_E_ELEMENTNOTFOUND
;
6202 /* ITypeInfo::GetRefTypeOfImplType
6204 * If a type description describes a COM class, it retrieves the type
6205 * description of the implemented interface types. For an interface,
6206 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6210 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6215 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6218 TRACE("(%p) index %d\n", This
, index
);
6219 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6223 /* only valid on dual interfaces;
6224 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6227 if (This
->wTypeFlags
& TYPEFLAG_FDUAL
)
6233 hr
= TYPE_E_ELEMENTNOTFOUND
;
6236 else if(index
== 0 && This
->typekind
== TKIND_DISPATCH
)
6238 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6239 *pRefType
= This
->pTypeLib
->dispatch_href
;
6243 if(index
>= This
->cImplTypes
)
6244 hr
= TYPE_E_ELEMENTNOTFOUND
;
6246 *pRefType
= This
->impltypes
[index
].hRef
;
6247 if(This
->typekind
== TKIND_INTERFACE
)
6255 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6257 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6263 /* ITypeInfo::GetImplTypeFlags
6265 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6266 * or base interface in a type description.
6268 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6269 UINT index
, INT
*pImplTypeFlags
)
6271 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6273 TRACE("(%p) index %d\n", This
, index
);
6276 return E_INVALIDARG
;
6278 if(This
->typekind
== TKIND_DISPATCH
&& index
== 0){
6279 *pImplTypeFlags
= 0;
6283 if(index
>= This
->cImplTypes
)
6284 return TYPE_E_ELEMENTNOTFOUND
;
6286 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6292 * Maps between member names and member IDs, and parameter names and
6295 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6296 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6298 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6299 const TLBVarDesc
*pVDesc
;
6303 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6306 /* init out parameters in case of failure */
6307 for (i
= 0; i
< cNames
; i
++)
6308 pMemId
[i
] = MEMBERID_NIL
;
6310 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
) {
6312 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6313 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6314 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6315 for(i
=1; i
< cNames
; i
++){
6316 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6317 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6319 if( j
<pFDesc
->funcdesc
.cParams
)
6322 ret
=DISP_E_UNKNOWNNAME
;
6324 TRACE("-- 0x%08x\n", ret
);
6328 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, *rgszNames
);
6331 *pMemId
= pVDesc
->vardesc
.memid
;
6334 /* not found, see if it can be found in an inherited interface */
6335 if(This
->impltypes
) {
6336 /* recursive search */
6338 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6340 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6341 ITypeInfo_Release(pTInfo
);
6344 WARN("Could not search inherited interface!\n");
6346 WARN("no names found\n");
6347 return DISP_E_UNKNOWNNAME
;
6353 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6354 __ASM_GLOBAL_FUNC( call_method
,
6356 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6357 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6358 "movl %esp,%ebp\n\t"
6359 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6361 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6363 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6364 "movl 12(%ebp),%edx\n\t"
6365 "movl %esp,%edi\n\t"
6368 "subl %edx,%edi\n\t"
6369 "andl $~15,%edi\n\t"
6370 "movl %edi,%esp\n\t"
6371 "movl 12(%ebp),%ecx\n\t"
6372 "movl 16(%ebp),%esi\n\t"
6375 "1:\tcall *8(%ebp)\n\t"
6376 "subl %esp,%edi\n\t"
6377 "movl 20(%ebp),%ecx\n\t"
6378 "movl %edi,(%ecx)\n\t"
6379 "leal -8(%ebp),%esp\n\t"
6381 __ASM_CFI(".cfi_same_value %edi\n\t")
6383 __ASM_CFI(".cfi_same_value %esi\n\t")
6385 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6386 __ASM_CFI(".cfi_same_value %ebp\n\t")
6389 /* same function but returning floating point */
6390 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
6392 /* ITypeInfo::Invoke
6394 * Invokes a method, or accesses a property of an object, that implements the
6395 * interface described by the type description.
6398 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
6402 if (TRACE_ON(ole
)) {
6404 TRACE("Calling %p(",func
);
6405 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
6406 if (nrargs
> 30) TRACE("...");
6413 res
= call_method( func
, nrargs
, args
, &stack_offset
);
6416 FIXME("unsupported calling convention %d\n",callconv
);
6420 TRACE("returns %08x\n",res
);
6424 #elif defined(__x86_64__)
6426 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6427 __ASM_GLOBAL_FUNC( call_method
,
6429 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6430 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6431 "movq %rsp,%rbp\n\t"
6432 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6434 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6436 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6437 "movq %rcx,%rax\n\t"
6440 "cmovgq %rdx,%rcx\n\t"
6441 "leaq 0(,%rcx,8),%rdx\n\t"
6442 "subq %rdx,%rsp\n\t"
6443 "andq $~15,%rsp\n\t"
6444 "movq %rsp,%rdi\n\t"
6447 "movq 0(%rsp),%rcx\n\t"
6448 "movq 8(%rsp),%rdx\n\t"
6449 "movq 16(%rsp),%r8\n\t"
6450 "movq 24(%rsp),%r9\n\t"
6451 "movq %rcx,%xmm0\n\t"
6452 "movq %rdx,%xmm1\n\t"
6453 "movq %r8,%xmm2\n\t"
6454 "movq %r9,%xmm3\n\t"
6456 "leaq -16(%rbp),%rsp\n\t"
6458 __ASM_CFI(".cfi_same_value %rdi\n\t")
6460 __ASM_CFI(".cfi_same_value %rsi\n\t")
6461 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6463 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6464 __ASM_CFI(".cfi_same_value %rbp\n\t")
6467 /* same function but returning floating point */
6468 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
6470 #endif /* __x86_64__ */
6472 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6475 ITypeInfo
*tinfo2
= NULL
;
6476 TYPEATTR
*tattr
= NULL
;
6478 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6481 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6483 tdesc
->u
.hreftype
, hr
);
6486 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6489 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6490 ITypeInfo_Release(tinfo2
);
6494 switch (tattr
->typekind
)
6501 tdesc
= &tattr
->tdescAlias
;
6502 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6505 case TKIND_INTERFACE
:
6506 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6512 case TKIND_DISPATCH
:
6521 FIXME("TKIND_RECORD unhandled.\n");
6526 FIXME("TKIND_UNION unhandled.\n");
6531 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6535 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6536 ITypeInfo_Release(tinfo2
);
6540 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6544 /* enforce only one level of pointer indirection */
6545 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6547 tdesc
= tdesc
->u
.lptdesc
;
6549 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6550 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6551 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6552 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6553 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6555 VARTYPE vt_userdefined
= 0;
6556 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6557 if (tdesc
->vt
== VT_PTR
)
6559 vt_userdefined
= VT_BYREF
;
6560 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6562 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6564 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6565 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6567 *vt
|= vt_userdefined
;
6579 case VT_USERDEFINED
:
6580 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6587 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6588 hr
= DISP_E_BADVARTYPE
;
6592 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6607 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6613 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6617 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6619 ITypeInfo_Release(tinfo2
);
6623 switch(tattr
->typekind
) {
6625 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6628 case TKIND_INTERFACE
:
6629 case TKIND_DISPATCH
:
6630 *guid
= tattr
->guid
;
6634 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6635 hres
= E_UNEXPECTED
;
6638 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6639 ITypeInfo_Release(tinfo2
);
6643 /***********************************************************************
6644 * DispCallFunc (OLEAUT32.@)
6646 * Invokes a function of the specified calling convention, passing the
6647 * specified arguments and returns the result.
6650 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6651 * oVft [I] The offset in the vtable. See notes.
6652 * cc [I] Calling convention of the function to call.
6653 * vtReturn [I] The return type of the function.
6654 * cActuals [I] Number of parameters.
6655 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6656 * prgpvarg [I] The arguments to pass.
6657 * pvargResult [O] The return value of the function. Can be NULL.
6661 * Failure: HRESULT code.
6664 * The HRESULT return value of this function is not affected by the return
6665 * value of the user supplied function, which is returned in pvargResult.
6667 * If pvInstance is NULL then a non-object function is to be called and oVft
6668 * is the address of the function to call.
6670 * The cc parameter can be one of the following values:
6683 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6684 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6687 int argspos
, stack_offset
;
6692 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6693 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6694 pvargResult
, V_VT(pvargResult
));
6696 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6698 FIXME("unsupported calling convention %d\n",cc
);
6699 return E_INVALIDARG
;
6702 /* maximum size for an argument is sizeof(VARIANT) */
6703 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6705 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6709 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6710 func
= vtable
[oVft
/sizeof(void *)];
6711 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6713 else func
= (void *)oVft
;
6715 for (i
= 0; i
< cActuals
; i
++)
6717 VARIANT
*arg
= prgpvarg
[i
];
6728 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6729 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6733 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6734 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6736 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6737 args
[argspos
++] = V_BOOL(arg
);
6740 args
[argspos
++] = V_UI4(arg
);
6743 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6749 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6752 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6756 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6760 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6761 call_method( func
, argspos
, args
, &stack_offset
);
6766 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6769 WARN("invalid return type %u\n", vtReturn
);
6771 return E_INVALIDARG
;
6773 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6777 if (stack_offset
&& cc
== CC_STDCALL
)
6779 WARN( "stack pointer off by %d\n", stack_offset
);
6780 return DISP_E_BADCALLEE
;
6782 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6783 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6786 #elif defined(__x86_64__)
6792 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6793 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6794 pvargResult
, V_VT(pvargResult
));
6796 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6798 FIXME("unsupported calling convention %d\n",cc
);
6799 return E_INVALIDARG
;
6802 /* maximum size for an argument is sizeof(DWORD_PTR) */
6803 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6805 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6809 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6810 func
= vtable
[oVft
/sizeof(void *)];
6811 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6813 else func
= (void *)oVft
;
6815 for (i
= 0; i
< cActuals
; i
++)
6817 VARIANT
*arg
= prgpvarg
[i
];
6823 args
[argspos
++] = (ULONG_PTR
)arg
;
6825 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6826 args
[argspos
++] = V_BOOL(arg
);
6829 args
[argspos
++] = V_UI8(arg
);
6832 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6838 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6842 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6846 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6847 call_method( func
, argspos
, args
);
6850 WARN("invalid return type %u\n", vtReturn
);
6852 return E_INVALIDARG
;
6854 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6858 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6859 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6863 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6864 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6869 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6871 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6874 #define INVBUF_ELEMENT_SIZE \
6875 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6876 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6877 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6878 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6879 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6880 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6881 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6882 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6884 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6889 DISPPARAMS
*pDispParams
,
6890 VARIANT
*pVarResult
,
6891 EXCEPINFO
*pExcepInfo
,
6894 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6896 unsigned int var_index
;
6899 const TLBFuncDesc
*pFuncInfo
;
6902 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6903 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6906 if( This
->wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6907 return DISP_E_MEMBERNOTFOUND
;
6911 ERR("NULL pDispParams not allowed\n");
6912 return E_INVALIDARG
;
6915 dump_DispParms(pDispParams
);
6917 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6919 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6920 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6921 return E_INVALIDARG
;
6924 /* we do this instead of using GetFuncDesc since it will return a fake
6925 * FUNCDESC for dispinterfaces and we want the real function description */
6926 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
6927 pFuncInfo
= &This
->funcdescs
[fdc
];
6928 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6929 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6930 !func_restricted( &pFuncInfo
->funcdesc
))
6934 if (fdc
< This
->cFuncs
) {
6935 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6939 TRACE("invoking:\n");
6940 dump_TLBFuncDescOne(pFuncInfo
);
6943 switch (func_desc
->funckind
) {
6944 case FUNC_PUREVIRTUAL
:
6945 case FUNC_VIRTUAL
: {
6946 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6948 VARIANT retval
; /* pointer for storing byref retvals in */
6949 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6950 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6951 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6952 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6953 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6954 UINT vargs_converted
=0;
6958 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6960 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6962 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6963 hres
= DISP_E_PARAMNOTFOUND
;
6968 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6970 ERR("functions with the vararg attribute do not support named arguments\n");
6971 hres
= DISP_E_NONAMEDARGS
;
6975 for (i
= 0; i
< func_desc
->cParams
; i
++)
6977 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6978 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6983 TRACE("changing args\n");
6984 for (i
= 0; i
< func_desc
->cParams
; i
++)
6986 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6987 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6988 VARIANTARG
*src_arg
;
6990 if (wParamFlags
& PARAMFLAG_FLCID
)
6993 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6995 V_I4(arg
) = This
->pTypeLib
->lcid
;
7004 for (j
= 0; j
< cNamedArgs
; j
++)
7005 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7007 src_arg
= &pDispParams
->rgvarg
[j
];
7012 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7014 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7018 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7020 /* under most conditions the caller is not allowed to
7021 * pass in a dispparam arg in the index of what would be
7022 * the retval parameter. however, there is an exception
7023 * where the extra parameter is used in an extra
7024 * IDispatch::Invoke below */
7025 if ((i
< pDispParams
->cArgs
) &&
7026 ((func_desc
->cParams
!= 1) || !pVarResult
||
7027 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7029 hres
= DISP_E_BADPARAMCOUNT
;
7033 /* note: this check is placed so that if the caller passes
7034 * in a VARIANTARG for the retval we just ignore it, like
7036 if (i
== func_desc
->cParams
- 1)
7039 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7040 memset(arg
, 0, sizeof(*arg
));
7041 V_VT(arg
) = rgvt
[i
];
7042 memset(&retval
, 0, sizeof(retval
));
7043 V_BYREF(arg
) = &retval
;
7047 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7048 hres
= E_UNEXPECTED
;
7054 TRACE("%s\n", debugstr_variant(src_arg
));
7056 if(rgvt
[i
]!=V_VT(src_arg
))
7058 if (rgvt
[i
] == VT_VARIANT
)
7059 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7060 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7062 if (rgvt
[i
] == V_VT(src_arg
))
7063 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7066 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7067 if (wParamFlags
& PARAMFLAG_FIN
)
7068 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7069 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7071 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7073 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
7076 SAFEARRAYBOUND bound
;
7080 bound
.cElements
= pDispParams
->cArgs
-i
;
7081 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7083 ERR("SafeArrayCreate failed\n");
7086 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7089 ERR("SafeArrayAccessData failed with %x\n", hres
);
7090 SafeArrayDestroy(a
);
7093 for (j
= 0; j
< bound
.cElements
; j
++)
7094 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7095 hres
= SafeArrayUnaccessData(a
);
7098 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7099 SafeArrayDestroy(a
);
7102 V_ARRAY(&rgvarg
[i
]) = a
;
7103 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7105 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7107 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7108 if (wParamFlags
& PARAMFLAG_FIN
)
7109 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7111 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7112 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7113 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7115 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7117 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7118 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7122 /* FIXME: this doesn't work for VT_BYREF arguments if
7123 * they are not the same type as in the paramdesc */
7124 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7125 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7126 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7131 ERR("failed to convert param %d to %s from %s\n", i
,
7132 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7135 prgpvarg
[i
] = &rgvarg
[i
];
7139 prgpvarg
[i
] = src_arg
;
7142 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7143 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7144 && V_UNKNOWN(prgpvarg
[i
])) {
7145 IUnknown
*userdefined_iface
;
7148 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
7152 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7154 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7158 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7159 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7162 else if (wParamFlags
& PARAMFLAG_FOPT
)
7165 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7166 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7168 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7174 VARIANTARG
*missing_arg
;
7175 /* if the function wants a pointer to a variant then
7176 * set that up, otherwise just pass the VT_ERROR in
7177 * the argument by value */
7178 if (rgvt
[i
] & VT_BYREF
)
7180 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7181 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7182 V_VARIANTREF(arg
) = missing_arg
;
7186 V_VT(missing_arg
) = VT_ERROR
;
7187 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7192 hres
= DISP_E_BADPARAMCOUNT
;
7196 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7198 /* VT_VOID is a special case for return types, so it is not
7199 * handled in the general function */
7200 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7201 V_VT(&varresult
) = VT_EMPTY
;
7204 V_VT(&varresult
) = 0;
7205 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7206 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7209 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7210 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7211 prgpvarg
, &varresult
);
7213 vargs_converted
= 0;
7215 for (i
= 0; i
< func_desc
->cParams
; i
++)
7217 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7218 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7220 if (wParamFlags
& PARAMFLAG_FLCID
)
7222 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7224 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7228 VariantInit(pVarResult
);
7229 /* deref return value */
7230 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7233 VARIANT_ClearInd(prgpvarg
[i
]);
7235 else if (vargs_converted
< pDispParams
->cArgs
)
7237 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7238 if (wParamFlags
& PARAMFLAG_FOUT
)
7240 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7242 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7246 ERR("failed to convert param %d to vt %d\n", i
,
7247 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7252 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7253 func_desc
->cParamsOpt
< 0 &&
7254 i
== func_desc
->cParams
-1)
7256 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7259 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7262 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7265 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7268 ERR("SafeArrayAccessData failed with %x\n", hres
);
7271 for (j
= 0; j
<= ubound
; j
++)
7272 VariantClear(&v
[j
]);
7273 hres
= SafeArrayUnaccessData(a
);
7276 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7280 VariantClear(&rgvarg
[i
]);
7283 else if (wParamFlags
& PARAMFLAG_FOPT
)
7285 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7286 VariantClear(&rgvarg
[i
]);
7289 VariantClear(&missing_arg
[i
]);
7292 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7294 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7295 hres
= DISP_E_EXCEPTION
;
7298 IErrorInfo
*pErrorInfo
;
7299 pExcepInfo
->scode
= V_ERROR(&varresult
);
7300 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7302 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7303 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7304 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7305 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7307 IErrorInfo_Release(pErrorInfo
);
7311 if (V_VT(&varresult
) != VT_ERROR
)
7313 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7317 VariantClear(pVarResult
);
7318 *pVarResult
= varresult
;
7321 VariantClear(&varresult
);
7324 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7325 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7326 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7327 (pDispParams
->cArgs
!= 0))
7329 if (V_VT(pVarResult
) == VT_DISPATCH
)
7331 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7332 /* Note: not VariantClear; we still need the dispatch
7333 * pointer to be valid */
7334 VariantInit(pVarResult
);
7335 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7336 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
7337 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7338 IDispatch_Release(pDispatch
);
7342 VariantClear(pVarResult
);
7343 hres
= DISP_E_NOTACOLLECTION
;
7351 case FUNC_DISPATCH
: {
7354 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7355 if (SUCCEEDED(hres
)) {
7356 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7357 hres
= IDispatch_Invoke(
7358 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7359 pVarResult
,pExcepInfo
,pArgErr
7362 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7363 IDispatch_Release(disp
);
7365 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7369 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7374 TRACE("-- 0x%08x\n", hres
);
7377 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7380 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7381 if(FAILED(hres
)) return hres
;
7383 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7384 dump_VARDESC(var_desc
);
7385 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7389 /* not found, look for it in inherited interfaces */
7390 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7391 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7392 if(This
->impltypes
) {
7393 /* recursive search */
7395 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7396 if(SUCCEEDED(hres
)){
7397 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7398 ITypeInfo_Release(pTInfo
);
7401 WARN("Could not search inherited interface!\n");
7404 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7405 return DISP_E_MEMBERNOTFOUND
;
7408 /* ITypeInfo::GetDocumentation
7410 * Retrieves the documentation string, the complete Help file name and path,
7411 * and the context ID for the Help topic for a specified type description.
7413 * (Can be tested by the Visual Basic Editor in Word for instance.)
7415 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7416 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7417 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7419 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7420 const TLBFuncDesc
*pFDesc
;
7421 const TLBVarDesc
*pVDesc
;
7422 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7423 " HelpContext(%p) HelpFile(%p)\n",
7424 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7425 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7427 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7429 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7431 *pdwHelpContext
=This
->dwHelpContext
;
7433 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7435 }else {/* for a member */
7436 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7439 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7441 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7443 *pdwHelpContext
=pFDesc
->helpcontext
;
7445 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7448 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
7451 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7453 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7455 *pdwHelpContext
=pVDesc
->HelpContext
;
7457 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7462 if(This
->impltypes
&&
7463 (This
->typekind
==TKIND_INTERFACE
|| This
->typekind
==TKIND_DISPATCH
)) {
7464 /* recursive search */
7467 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7468 if(SUCCEEDED(result
)) {
7469 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7470 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7471 ITypeInfo_Release(pTInfo
);
7474 WARN("Could not search inherited interface!\n");
7477 WARN("member %d not found\n", memid
);
7478 return TYPE_E_ELEMENTNOTFOUND
;
7481 /* ITypeInfo::GetDllEntry
7483 * Retrieves a description or specification of an entry point for a function
7486 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7487 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7490 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7491 const TLBFuncDesc
*pFDesc
;
7493 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7495 if (pBstrDllName
) *pBstrDllName
= NULL
;
7496 if (pBstrName
) *pBstrName
= NULL
;
7497 if (pwOrdinal
) *pwOrdinal
= 0;
7499 if (This
->typekind
!= TKIND_MODULE
)
7500 return TYPE_E_BADMODULEKIND
;
7502 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
7504 dump_TypeInfo(This
);
7506 dump_TLBFuncDescOne(pFDesc
);
7509 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7511 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7513 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7521 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7524 return TYPE_E_ELEMENTNOTFOUND
;
7527 /* internal function to make the inherited interfaces' methods appear
7528 * part of the interface */
7529 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7530 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7532 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7535 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7537 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7539 ITypeInfo
*pSubTypeInfo
;
7541 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7545 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7547 ITypeInfo_Release(pSubTypeInfo
);
7551 *hRefType
-= DISPATCH_HREF_OFFSET
;
7553 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7554 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7559 struct search_res_tlb_params
7565 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7567 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7568 static const WCHAR formatW
[] = {'\\','%','d',0};
7569 WCHAR szPath
[MAX_PATH
+1];
7570 ITypeLib
*pTLib
= NULL
;
7574 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7577 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7580 if (snprintfW(szPath
+ len
, sizeof(szPath
)/sizeof(WCHAR
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7583 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7586 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7587 if (IsEqualGUID(params
->guid
, impl
->guid
))
7589 params
->pTLib
= pTLib
;
7590 return FALSE
; /* stop enumeration */
7592 ITypeLib_Release(pTLib
);
7598 /* ITypeInfo::GetRefTypeInfo
7600 * If a type description references other type descriptions, it retrieves
7601 * the referenced type descriptions.
7603 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7606 ITypeInfo
**ppTInfo
)
7608 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7609 HRESULT result
= E_FAIL
;
7612 return E_INVALIDARG
;
7614 if ((INT
)hRefType
< 0) {
7615 ITypeInfoImpl
*pTypeInfoImpl
;
7617 if (!(This
->wTypeFlags
& TYPEFLAG_FDUAL
) ||
7618 !(This
->typekind
== TKIND_INTERFACE
||
7619 This
->typekind
== TKIND_DISPATCH
))
7620 return TYPE_E_ELEMENTNOTFOUND
;
7622 /* when we meet a DUAL typeinfo, we must create the alternate
7625 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7627 *pTypeInfoImpl
= *This
;
7628 pTypeInfoImpl
->ref
= 0;
7629 list_init(&pTypeInfoImpl
->custdata_list
);
7631 if (This
->typekind
== TKIND_INTERFACE
)
7632 pTypeInfoImpl
->typekind
= TKIND_DISPATCH
;
7634 pTypeInfoImpl
->typekind
= TKIND_INTERFACE
;
7636 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7637 /* the AddRef implicitly adds a reference to the parent typelib, which
7638 * stops the copied data from being destroyed until the new typeinfo's
7639 * refcount goes to zero, but we need to signal to the new instance to
7640 * not free its data structures when it is destroyed */
7641 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7643 ITypeInfo_AddRef(*ppTInfo
);
7646 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7647 (This
->typekind
== TKIND_DISPATCH
))
7649 HREFTYPE href_dispatch
= hRefType
;
7650 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7652 TLBRefType
*ref_type
;
7653 ITypeLib
*pTLib
= NULL
;
7656 if(!(hRefType
& 0x1)){
7657 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7659 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7662 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7663 ITypeInfo_AddRef(*ppTInfo
);
7669 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7671 if(ref_type
->reference
== (hRefType
& (~0x3)))
7674 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7676 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7680 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7682 TRACE("internal reference\n");
7683 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7685 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7686 TRACE("typeinfo in imported typelib that is already loaded\n");
7687 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7688 ITypeLib_AddRef(pTLib
);
7691 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7692 struct search_res_tlb_params params
;
7695 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7697 /* Search in resource table */
7698 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7699 params
.pTLib
= NULL
;
7700 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7701 pTLib
= params
.pTLib
;
7706 /* Search on disk */
7707 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7708 ref_type
->pImpTLInfo
->wVersionMajor
,
7709 ref_type
->pImpTLInfo
->wVersionMinor
,
7710 This
->pTypeLib
->syskind
,
7711 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7713 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7715 result
= LoadTypeLib(libnam
, &pTLib
);
7716 SysFreeString(libnam
);
7719 if(SUCCEEDED(result
)) {
7720 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7721 ITypeLib_AddRef(pTLib
);
7725 if(SUCCEEDED(result
)) {
7726 if(ref_type
->index
== TLB_REF_USE_GUID
)
7727 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7729 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7732 ITypeLib_Release(pTLib
);
7736 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7737 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7741 /* ITypeInfo::AddressOfMember
7743 * Retrieves the addresses of static functions or variables, such as those
7746 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7747 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7749 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7755 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7757 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7761 module
= LoadLibraryW(dll
);
7764 ERR("couldn't load %s\n", debugstr_w(dll
));
7766 SysFreeString(entry
);
7767 return STG_E_FILENOTFOUND
;
7769 /* FIXME: store library somewhere where we can free it */
7774 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7775 entryA
= heap_alloc(len
);
7776 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7778 *ppv
= GetProcAddress(module
, entryA
);
7780 ERR("function not found %s\n", debugstr_a(entryA
));
7786 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7788 ERR("function not found %d\n", ordinal
);
7792 SysFreeString(entry
);
7795 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7800 /* ITypeInfo::CreateInstance
7802 * Creates a new instance of a type that describes a component object class
7805 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7806 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7808 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7812 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7818 WARN("Not able to aggregate\n");
7819 return CLASS_E_NOAGGREGATION
;
7822 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7823 if(FAILED(hr
)) return hr
;
7825 if(pTA
->typekind
!= TKIND_COCLASS
)
7827 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7833 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7836 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7837 TRACE("GetActiveObject rets %08x\n", hr
);
7840 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7841 IUnknown_Release(pUnk
);
7846 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7847 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7851 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7855 /* ITypeInfo::GetMops
7857 * Retrieves marshalling information.
7859 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7862 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7863 FIXME("(%p %d) stub!\n", This
, memid
);
7868 /* ITypeInfo::GetContainingTypeLib
7870 * Retrieves the containing type library and the index of the type description
7871 * within that type library.
7873 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7874 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7876 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7878 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7880 *pIndex
=This
->index
;
7881 TRACE("returning pIndex=%d\n", *pIndex
);
7885 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7886 ITypeLib_AddRef(*ppTLib
);
7887 TRACE("returning ppTLib=%p\n", *ppTLib
);
7893 /* ITypeInfo::ReleaseTypeAttr
7895 * Releases a TYPEATTR previously returned by Get
7898 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7899 TYPEATTR
* pTypeAttr
)
7901 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7902 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7903 heap_free(pTypeAttr
);
7906 /* ITypeInfo::ReleaseFuncDesc
7908 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7910 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7912 FUNCDESC
*pFuncDesc
)
7914 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7917 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7919 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7920 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7921 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7923 SysFreeString((BSTR
)pFuncDesc
);
7926 /* ITypeInfo::ReleaseVarDesc
7928 * Releases a VARDESC previously returned by GetVarDesc.
7930 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7933 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7934 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7936 TLB_FreeVarDesc(pVarDesc
);
7939 /* ITypeInfo2::GetTypeKind
7941 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7944 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7945 TYPEKIND
*pTypeKind
)
7947 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7948 *pTypeKind
=This
->typekind
;
7949 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7953 /* ITypeInfo2::GetTypeFlags
7955 * Returns the type flags without any allocations. This returns a DWORD type
7956 * flag, which expands the type flags without growing the TYPEATTR (type
7960 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7962 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7963 *pTypeFlags
=This
->wTypeFlags
;
7964 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7968 /* ITypeInfo2::GetFuncIndexOfMemId
7969 * Binds to a specific member based on a known DISPID, where the member name
7970 * is not known (for example, when binding to a default member).
7973 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7974 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7976 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7980 for (fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
7981 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7982 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7985 if(fdc
< This
->cFuncs
) {
7989 result
= TYPE_E_ELEMENTNOTFOUND
;
7991 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7992 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7996 /* TypeInfo2::GetVarIndexOfMemId
7998 * Binds to a specific member based on a known DISPID, where the member name
7999 * is not known (for example, when binding to a default member).
8002 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8003 MEMBERID memid
, UINT
*pVarIndex
)
8005 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8006 TLBVarDesc
*pVarInfo
;
8008 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8010 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8012 return TYPE_E_ELEMENTNOTFOUND
;
8014 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8019 /* ITypeInfo2::GetCustData
8021 * Gets the custom data
8023 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8028 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8029 TLBCustData
*pCData
;
8031 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8033 if(!guid
|| !pVarVal
)
8034 return E_INVALIDARG
;
8036 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8038 VariantInit( pVarVal
);
8040 VariantCopy( pVarVal
, &pCData
->data
);
8042 VariantClear( pVarVal
);
8046 /* ITypeInfo2::GetFuncCustData
8048 * Gets the custom data
8050 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8056 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8057 TLBCustData
*pCData
;
8058 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8060 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8062 if(index
>= This
->cFuncs
)
8063 return TYPE_E_ELEMENTNOTFOUND
;
8065 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8067 return TYPE_E_ELEMENTNOTFOUND
;
8069 VariantInit(pVarVal
);
8070 VariantCopy(pVarVal
, &pCData
->data
);
8075 /* ITypeInfo2::GetParamCustData
8077 * Gets the custom data
8079 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8086 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8087 TLBCustData
*pCData
;
8088 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8090 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8091 debugstr_guid(guid
), pVarVal
);
8093 if(indexFunc
>= This
->cFuncs
)
8094 return TYPE_E_ELEMENTNOTFOUND
;
8096 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8097 return TYPE_E_ELEMENTNOTFOUND
;
8099 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8101 return TYPE_E_ELEMENTNOTFOUND
;
8103 VariantInit(pVarVal
);
8104 VariantCopy(pVarVal
, &pCData
->data
);
8109 /* ITypeInfo2::GetVarCustData
8111 * Gets the custom data
8113 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8119 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8120 TLBCustData
*pCData
;
8121 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8123 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8125 if(index
>= This
->cVars
)
8126 return TYPE_E_ELEMENTNOTFOUND
;
8128 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8130 return TYPE_E_ELEMENTNOTFOUND
;
8132 VariantInit(pVarVal
);
8133 VariantCopy(pVarVal
, &pCData
->data
);
8138 /* ITypeInfo2::GetImplCustData
8140 * Gets the custom data
8142 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8148 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8149 TLBCustData
*pCData
;
8150 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8152 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8154 if(index
>= This
->cImplTypes
)
8155 return TYPE_E_ELEMENTNOTFOUND
;
8157 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8159 return TYPE_E_ELEMENTNOTFOUND
;
8161 VariantInit(pVarVal
);
8162 VariantCopy(pVarVal
, &pCData
->data
);
8167 /* ITypeInfo2::GetDocumentation2
8169 * Retrieves the documentation string, the complete Help file name and path,
8170 * the localization context to use, and the context ID for the library Help
8171 * topic in the Help file.
8174 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8178 BSTR
*pbstrHelpString
,
8179 DWORD
*pdwHelpStringContext
,
8180 BSTR
*pbstrHelpStringDll
)
8182 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8183 const TLBFuncDesc
*pFDesc
;
8184 const TLBVarDesc
*pVDesc
;
8185 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8186 "HelpStringContext(%p) HelpStringDll(%p)\n",
8187 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8188 pbstrHelpStringDll
);
8189 /* the help string should be obtained from the helpstringdll,
8190 * using the _DLLGetDocumentation function, based on the supplied
8191 * lcid. Nice to do sometime...
8193 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8195 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8196 if(pdwHelpStringContext
)
8197 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8198 if(pbstrHelpStringDll
)
8199 *pbstrHelpStringDll
=
8200 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8202 }else {/* for a member */
8203 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->cFuncs
, memid
);
8206 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8207 if(pdwHelpStringContext
)
8208 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8209 if(pbstrHelpStringDll
)
8210 *pbstrHelpStringDll
=
8211 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8214 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->cVars
, memid
);
8217 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8218 if(pdwHelpStringContext
)
8219 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8220 if(pbstrHelpStringDll
)
8221 *pbstrHelpStringDll
=
8222 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8226 return TYPE_E_ELEMENTNOTFOUND
;
8229 /* ITypeInfo2::GetAllCustData
8231 * Gets all custom data items for the Type info.
8234 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8236 CUSTDATA
*pCustData
)
8238 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8240 TRACE("%p %p\n", This
, pCustData
);
8242 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8245 /* ITypeInfo2::GetAllFuncCustData
8247 * Gets all custom data items for the specified Function
8250 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8253 CUSTDATA
*pCustData
)
8255 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8256 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8258 TRACE("%p %u %p\n", This
, index
, pCustData
);
8260 if(index
>= This
->cFuncs
)
8261 return TYPE_E_ELEMENTNOTFOUND
;
8263 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8266 /* ITypeInfo2::GetAllParamCustData
8268 * Gets all custom data items for the Functions
8271 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8272 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8274 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8275 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8277 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8279 if(indexFunc
>= This
->cFuncs
)
8280 return TYPE_E_ELEMENTNOTFOUND
;
8282 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8283 return TYPE_E_ELEMENTNOTFOUND
;
8285 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8288 /* ITypeInfo2::GetAllVarCustData
8290 * Gets all custom data items for the specified Variable
8293 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8294 UINT index
, CUSTDATA
*pCustData
)
8296 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8297 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8299 TRACE("%p %u %p\n", This
, index
, pCustData
);
8301 if(index
>= This
->cVars
)
8302 return TYPE_E_ELEMENTNOTFOUND
;
8304 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8307 /* ITypeInfo2::GetAllImplCustData
8309 * Gets all custom data items for the specified implementation type
8312 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8315 CUSTDATA
*pCustData
)
8317 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8318 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8320 TRACE("%p %u %p\n", This
, index
, pCustData
);
8322 if(index
>= This
->cImplTypes
)
8323 return TYPE_E_ELEMENTNOTFOUND
;
8325 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8328 static const ITypeInfo2Vtbl tinfvt
=
8331 ITypeInfo_fnQueryInterface
,
8333 ITypeInfo_fnRelease
,
8335 ITypeInfo_fnGetTypeAttr
,
8336 ITypeInfo_fnGetTypeComp
,
8337 ITypeInfo_fnGetFuncDesc
,
8338 ITypeInfo_fnGetVarDesc
,
8339 ITypeInfo_fnGetNames
,
8340 ITypeInfo_fnGetRefTypeOfImplType
,
8341 ITypeInfo_fnGetImplTypeFlags
,
8342 ITypeInfo_fnGetIDsOfNames
,
8344 ITypeInfo_fnGetDocumentation
,
8345 ITypeInfo_fnGetDllEntry
,
8346 ITypeInfo_fnGetRefTypeInfo
,
8347 ITypeInfo_fnAddressOfMember
,
8348 ITypeInfo_fnCreateInstance
,
8349 ITypeInfo_fnGetMops
,
8350 ITypeInfo_fnGetContainingTypeLib
,
8351 ITypeInfo_fnReleaseTypeAttr
,
8352 ITypeInfo_fnReleaseFuncDesc
,
8353 ITypeInfo_fnReleaseVarDesc
,
8355 ITypeInfo2_fnGetTypeKind
,
8356 ITypeInfo2_fnGetTypeFlags
,
8357 ITypeInfo2_fnGetFuncIndexOfMemId
,
8358 ITypeInfo2_fnGetVarIndexOfMemId
,
8359 ITypeInfo2_fnGetCustData
,
8360 ITypeInfo2_fnGetFuncCustData
,
8361 ITypeInfo2_fnGetParamCustData
,
8362 ITypeInfo2_fnGetVarCustData
,
8363 ITypeInfo2_fnGetImplTypeCustData
,
8364 ITypeInfo2_fnGetDocumentation2
,
8365 ITypeInfo2_fnGetAllCustData
,
8366 ITypeInfo2_fnGetAllFuncCustData
,
8367 ITypeInfo2_fnGetAllParamCustData
,
8368 ITypeInfo2_fnGetAllVarCustData
,
8369 ITypeInfo2_fnGetAllImplTypeCustData
,
8372 /******************************************************************************
8373 * CreateDispTypeInfo [OLEAUT32.31]
8375 * Build type information for an object so it can be called through an
8376 * IDispatch interface.
8379 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8380 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8383 * This call allows an objects methods to be accessed through IDispatch, by
8384 * building an ITypeInfo object that IDispatch can use to call through.
8386 HRESULT WINAPI
CreateDispTypeInfo(
8387 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8388 LCID lcid
, /* [I] Locale Id */
8389 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8391 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8392 ITypeLibImpl
*pTypeLibImpl
;
8393 unsigned int param
, func
;
8394 TLBFuncDesc
*pFuncDesc
;
8398 pTypeLibImpl
= TypeLibImpl_Constructor();
8399 if (!pTypeLibImpl
) return E_FAIL
;
8401 pTypeLibImpl
->TypeInfoCount
= 2;
8402 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8404 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8405 pTIIface
->pTypeLib
= pTypeLibImpl
;
8406 pTIIface
->index
= 0;
8407 pTIIface
->Name
= NULL
;
8408 pTIIface
->dwHelpContext
= -1;
8409 pTIIface
->guid
= NULL
;
8410 pTIIface
->lcid
= lcid
;
8411 pTIIface
->typekind
= TKIND_INTERFACE
;
8412 pTIIface
->wMajorVerNum
= 0;
8413 pTIIface
->wMinorVerNum
= 0;
8414 pTIIface
->cbAlignment
= 2;
8415 pTIIface
->cbSizeInstance
= -1;
8416 pTIIface
->cbSizeVft
= -1;
8417 pTIIface
->cFuncs
= 0;
8418 pTIIface
->cImplTypes
= 0;
8419 pTIIface
->cVars
= 0;
8420 pTIIface
->wTypeFlags
= 0;
8421 pTIIface
->hreftype
= 0;
8423 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8424 pFuncDesc
= pTIIface
->funcdescs
;
8425 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8426 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8427 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8428 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8429 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8430 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8431 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8432 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8433 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8434 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8435 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8436 pFuncDesc
->funcdesc
.cScodes
= 0;
8437 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8438 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8439 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8440 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8441 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8442 md
->cArgs
* sizeof(ELEMDESC
));
8443 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8444 for(param
= 0; param
< md
->cArgs
; param
++) {
8445 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8446 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8448 pFuncDesc
->helpcontext
= 0;
8449 pFuncDesc
->HelpStringContext
= 0;
8450 pFuncDesc
->HelpString
= NULL
;
8451 pFuncDesc
->Entry
= NULL
;
8452 list_init(&pFuncDesc
->custdata_list
);
8457 dump_TypeInfo(pTIIface
);
8459 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8460 pTIClass
->pTypeLib
= pTypeLibImpl
;
8461 pTIClass
->index
= 1;
8462 pTIClass
->Name
= NULL
;
8463 pTIClass
->dwHelpContext
= -1;
8464 pTIClass
->guid
= NULL
;
8465 pTIClass
->lcid
= lcid
;
8466 pTIClass
->typekind
= TKIND_COCLASS
;
8467 pTIClass
->wMajorVerNum
= 0;
8468 pTIClass
->wMinorVerNum
= 0;
8469 pTIClass
->cbAlignment
= 2;
8470 pTIClass
->cbSizeInstance
= -1;
8471 pTIClass
->cbSizeVft
= -1;
8472 pTIClass
->cFuncs
= 0;
8473 pTIClass
->cImplTypes
= 1;
8474 pTIClass
->cVars
= 0;
8475 pTIClass
->wTypeFlags
= 0;
8476 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8478 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8480 ref
= heap_alloc_zero(sizeof(*ref
));
8481 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8482 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8484 dump_TypeInfo(pTIClass
);
8486 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8488 ITypeInfo_AddRef(*pptinfo
);
8489 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8495 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8497 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8499 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8502 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8504 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8506 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8509 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8511 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8513 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8516 static HRESULT WINAPI
ITypeComp_fnBind(
8521 ITypeInfo
** ppTInfo
,
8522 DESCKIND
* pDescKind
,
8525 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8526 const TLBFuncDesc
*pFDesc
;
8527 const TLBVarDesc
*pVDesc
;
8528 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8531 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8533 *pDescKind
= DESCKIND_NONE
;
8534 pBindPtr
->lpfuncdesc
= NULL
;
8537 for(fdc
= 0; fdc
< This
->cFuncs
; ++fdc
){
8538 pFDesc
= &This
->funcdescs
[fdc
];
8539 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8540 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8543 /* name found, but wrong flags */
8544 hr
= TYPE_E_TYPEMISMATCH
;
8548 if (fdc
< This
->cFuncs
)
8550 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8552 &pBindPtr
->lpfuncdesc
,
8553 This
->typekind
== TKIND_DISPATCH
);
8556 *pDescKind
= DESCKIND_FUNCDESC
;
8557 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8558 ITypeInfo_AddRef(*ppTInfo
);
8561 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->cVars
, szName
);
8563 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8566 *pDescKind
= DESCKIND_VARDESC
;
8567 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8568 ITypeInfo_AddRef(*ppTInfo
);
8573 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8574 /* recursive search */
8578 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8581 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8582 ITypeInfo_Release(pTInfo
);
8586 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8587 ITypeComp_Release(pTComp
);
8588 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8589 This
->typekind
== TKIND_DISPATCH
)
8591 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8592 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8593 SysFreeString((BSTR
)tmp
);
8597 WARN("Could not search inherited interface!\n");
8599 if (hr
== DISP_E_MEMBERNOTFOUND
)
8601 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8605 static HRESULT WINAPI
ITypeComp_fnBindType(
8609 ITypeInfo
** ppTInfo
,
8610 ITypeComp
** ppTComp
)
8612 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8614 /* strange behaviour (does nothing) but like the
8617 if (!ppTInfo
|| !ppTComp
)
8626 static const ITypeCompVtbl tcompvt
=
8629 ITypeComp_fnQueryInterface
,
8631 ITypeComp_fnRelease
,
8634 ITypeComp_fnBindType
8637 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8638 ICreateTypeLib2
** ppctlib
)
8643 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8645 if (!szFile
) return E_INVALIDARG
;
8647 This
= TypeLibImpl_Constructor();
8649 return E_OUTOFMEMORY
;
8651 This
->lcid
= GetSystemDefaultLCID();
8652 This
->syskind
= syskind
;
8653 This
->ptr_size
= get_ptr_size(syskind
);
8655 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8657 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8658 return E_OUTOFMEMORY
;
8660 lstrcpyW(This
->path
, szFile
);
8662 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8663 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8667 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8668 REFIID riid
, void **object
)
8670 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8672 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8675 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8677 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8679 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8682 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8684 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8686 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8689 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8690 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8692 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8693 ITypeInfoImpl
*info
;
8696 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8698 if (!ctinfo
|| !name
)
8699 return E_INVALIDARG
;
8701 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8703 return TYPE_E_NAMECONFLICT
;
8705 if (This
->typeinfos
)
8706 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8707 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8709 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8711 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8713 info
->pTypeLib
= This
;
8714 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8715 info
->index
= This
->TypeInfoCount
;
8716 info
->typekind
= kind
;
8717 info
->cbAlignment
= 4;
8719 switch(info
->typekind
) {
8721 case TKIND_INTERFACE
:
8722 case TKIND_DISPATCH
:
8724 info
->cbSizeInstance
= This
->ptr_size
;
8728 info
->cbSizeInstance
= 0;
8731 info
->cbSizeInstance
= 2;
8734 info
->cbSizeInstance
= -0x75;
8737 FIXME("unrecognized typekind %d\n", info
->typekind
);
8738 info
->cbSizeInstance
= 0xdeadbeef;
8742 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8743 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8745 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8749 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8751 ++This
->TypeInfoCount
;
8756 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8759 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8761 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8764 return E_INVALIDARG
;
8766 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8771 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8772 WORD majorVerNum
, WORD minorVerNum
)
8774 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8776 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8778 This
->ver_major
= majorVerNum
;
8779 This
->ver_minor
= minorVerNum
;
8784 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8787 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8789 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8791 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8796 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8799 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8801 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8804 return E_INVALIDARG
;
8806 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8811 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8812 LPOLESTR helpFileName
)
8814 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8816 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8819 return E_INVALIDARG
;
8821 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8826 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8829 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8831 TRACE("%p %d\n", This
, helpContext
);
8833 This
->dwHelpContext
= helpContext
;
8838 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
8841 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8843 TRACE("%p %x\n", This
, lcid
);
8845 This
->set_lcid
= lcid
;
8850 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
8853 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8855 TRACE("%p %x\n", This
, libFlags
);
8857 This
->libflags
= libFlags
;
8862 typedef struct tagWMSFT_SegContents
{
8865 } WMSFT_SegContents
;
8867 typedef struct tagWMSFT_TLBFile
{
8869 WMSFT_SegContents typeinfo_seg
;
8870 WMSFT_SegContents impfile_seg
;
8871 WMSFT_SegContents impinfo_seg
;
8872 WMSFT_SegContents ref_seg
;
8873 WMSFT_SegContents guidhash_seg
;
8874 WMSFT_SegContents guid_seg
;
8875 WMSFT_SegContents namehash_seg
;
8876 WMSFT_SegContents name_seg
;
8877 WMSFT_SegContents string_seg
;
8878 WMSFT_SegContents typdesc_seg
;
8879 WMSFT_SegContents arraydesc_seg
;
8880 WMSFT_SegContents custdata_seg
;
8881 WMSFT_SegContents cdguids_seg
;
8883 WMSFT_SegContents aux_seg
;
8886 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
8887 WMSFT_TLBFile
*file
)
8893 file
->string_seg
.len
= 0;
8894 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8897 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
), NULL
, 0, NULL
, NULL
);
8899 return E_UNEXPECTED
;
8901 size
+= sizeof(INT16
);
8903 size
= (size
+ 4) & ~0x3;
8907 file
->string_seg
.len
+= size
;
8909 /* temporarily use str->offset to store the length of the aligned,
8910 * converted string */
8914 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
8917 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
8920 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8921 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
8923 heap_free(file
->string_seg
.data
);
8924 return E_UNEXPECTED
;
8927 *((INT16
*)data
) = size
;
8929 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
8933 str
->offset
= last_offs
;
8940 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
8941 WMSFT_TLBFile
*file
)
8946 MSFT_NameIntro
*last_intro
= NULL
;
8948 file
->header
.nametablecount
= 0;
8949 file
->header
.nametablechars
= 0;
8951 file
->name_seg
.len
= 0;
8952 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8955 size
= strlenW(str
->str
);
8956 file
->header
.nametablechars
+= size
;
8957 file
->header
.nametablecount
++;
8959 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
8961 return E_UNEXPECTED
;
8963 size
+= sizeof(MSFT_NameIntro
);
8965 size
= (size
+ 4) & ~0x3;
8969 file
->name_seg
.len
+= size
;
8971 /* temporarily use str->offset to store the length of the aligned,
8972 * converted string */
8976 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8977 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
8980 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
8982 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
8984 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, strlenW(str
->str
),
8985 data
+ sizeof(MSFT_NameIntro
),
8986 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
8988 heap_free(file
->name_seg
.data
);
8989 return E_UNEXPECTED
;
8991 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
8993 intro
->hreftype
= -1; /* TODO? */
8994 intro
->namelen
= size
& 0xFF;
8995 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8996 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
8997 intro
->namelen
|= hash
<< 16;
8998 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
8999 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9001 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9002 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9004 /* update str->offset to actual value to use in other
9005 * compilation functions that require positions within
9006 * the string table */
9010 str
->offset
= last_offs
;
9015 last_intro
->hreftype
= 0; /* last one is 0? */
9020 static inline int hash_guid(GUID
*guid
)
9024 for (i
= 0; i
< 8; i
++)
9025 hash
^= ((const short *)guid
)[i
];
9030 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9033 MSFT_GuidEntry
*entry
;
9035 int hash_key
, *guidhashtab
;
9037 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9038 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9040 entry
= file
->guid_seg
.data
;
9042 guidhashtab
= file
->guidhash_seg
.data
;
9043 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9044 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9045 entry
->hreftype
= guid
->hreftype
;
9047 hash_key
= hash_guid(&guid
->guid
);
9048 entry
->next_hash
= guidhashtab
[hash_key
];
9049 guidhashtab
[hash_key
] = offs
;
9051 guid
->offset
= offs
;
9052 offs
+= sizeof(MSFT_GuidEntry
);
9059 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9062 VARTYPE arg_type
= V_VT(value
);
9065 DWORD ret
= file
->custdata_seg
.len
;
9067 if(arg_type
== VT_INT
)
9069 if(arg_type
== VT_UINT
)
9073 if(V_VT(value
) != arg_type
) {
9074 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9076 ERR("VariantChangeType failed: %08x\n", hres
);
9081 /* Check if default value can be stored in-place */
9086 if(V_UI4(&v
) > 0x3ffffff)
9099 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9102 /* have to allocate space in custdata_seg */
9111 /* Construct the data to be allocated */
9114 if(file
->custdata_seg
.data
){
9115 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9116 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9117 file
->custdata_seg
.len
+= sizeof(int) * 2;
9119 file
->custdata_seg
.len
= sizeof(int) * 2;
9120 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9123 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9124 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9126 /* TODO: Check if the encoded data is already present in custdata_seg */
9132 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9135 if(file
->custdata_seg
.data
){
9136 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9137 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9138 file
->custdata_seg
.len
+= len
;
9140 file
->custdata_seg
.len
= len
;
9141 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9144 *((unsigned short *)data
) = V_VT(value
);
9145 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9146 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9147 if(V_BSTR(&v
)[i
] <= 0x7f)
9148 data
[i
+6] = V_BSTR(&v
)[i
];
9152 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9153 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9156 /* TODO: Check if the encoded data is already present in custdata_seg */
9161 FIXME("Argument type not yet handled\n");
9166 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9168 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9170 DWORD offs
= file
->arraydesc_seg
.len
;
9174 /* TODO: we should check for duplicates, but that's harder because each
9175 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9176 * at the library-level) */
9178 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9179 if(!file
->arraydesc_seg
.data
)
9180 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9182 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9183 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9185 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9186 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9187 for(i
= 0; i
< desc
->cDims
; ++i
){
9188 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9189 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9195 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9201 VARTYPE vt
, subtype
;
9212 vt
= desc
->vt
& VT_TYPEMASK
;
9214 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9216 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9217 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9219 *out_size
+= 2 * sizeof(DWORD
);
9220 }else if(vt
== VT_CARRAY
){
9221 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9222 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9224 }else if(vt
== VT_USERDEFINED
){
9225 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9226 encoded
[1] = desc
->u
.hreftype
;
9227 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9229 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9247 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9250 data
= file
->typdesc_seg
.data
;
9251 while(offs
< file
->typdesc_seg
.len
){
9252 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9254 offs
+= sizeof(encoded
);
9257 file
->typdesc_seg
.len
+= sizeof(encoded
);
9258 if(!file
->typdesc_seg
.data
)
9259 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9261 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9263 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9268 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9270 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9271 DWORD ret
= cdguids_seg
->len
, offs
;
9272 MSFT_CDGuid
*cdguid
= cdguids_seg
->data
;
9275 if(list_empty(custdata_list
))
9278 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9279 if(!cdguids_seg
->data
){
9280 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9282 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9284 offs
= ret
+ sizeof(MSFT_CDGuid
);
9285 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9286 cdguid
->GuidOffset
= cd
->guid
->offset
;
9287 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9288 cdguid
->next
= offs
;
9289 offs
+= sizeof(MSFT_CDGuid
);
9299 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9300 WMSFT_TLBFile
*file
)
9302 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9303 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9304 MSFT_VarRecord
*varrecord
;
9305 MSFT_FuncRecord
*funcrecord
;
9307 DWORD
*name
, *offsets
, offs
;
9309 for(i
= 0; i
< info
->cFuncs
; ++i
){
9310 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9312 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9314 /* optional fields */
9315 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9316 if(!list_empty(&desc
->custdata_list
))
9317 recorded_size
+= 7 * sizeof(INT
);
9318 else if(desc
->HelpStringContext
!= 0)
9319 recorded_size
+= 6 * sizeof(INT
);
9321 else if(desc
->Entry
)
9322 recorded_size
+= 3 * sizeof(INT
);
9323 else if(desc
->HelpString
)
9324 recorded_size
+= 2 * sizeof(INT
);
9325 else if(desc
->helpcontext
)
9326 recorded_size
+= sizeof(INT
);
9328 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9330 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9331 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9332 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9337 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9340 for(i
= 0; i
< info
->cVars
; ++i
){
9341 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9343 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9345 /* optional fields */
9346 if(desc
->HelpStringContext
!= 0)
9347 recorded_size
+= 5 * sizeof(INT
);
9348 else if(!list_empty(&desc
->custdata_list
))
9349 recorded_size
+= 4 * sizeof(INT
);
9351 else if(desc
->HelpString
)
9352 recorded_size
+= 2 * sizeof(INT
);
9353 else if(desc
->HelpContext
!= 0)
9354 recorded_size
+= sizeof(INT
);
9356 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9359 if(!recorded_size
&& !extra_size
)
9362 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9364 aux_seg
->len
+= recorded_size
+ extra_size
;
9366 aux_seg
->len
+= sizeof(INT
) * (info
->cVars
+ info
->cFuncs
); /* offsets at the end */
9369 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9371 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9373 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9375 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9378 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9379 for(i
= 0; i
< info
->cFuncs
; ++i
){
9380 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9381 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9383 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9384 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9385 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9386 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9389 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9394 * ^has_param_defaults
9395 * ^oEntry_is_intresource
9397 funcrecord
->FKCCIC
=
9398 desc
->funcdesc
.funckind
|
9399 (desc
->funcdesc
.invkind
<< 3) |
9400 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9401 (desc
->funcdesc
.callconv
<< 8);
9403 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9404 funcrecord
->FKCCIC
|= 0x2000;
9406 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9407 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9408 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9409 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9412 if(paramdefault_size
> 0)
9413 funcrecord
->FKCCIC
|= 0x1000;
9415 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9416 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9418 /* optional fields */
9420 if(!list_empty(&desc
->custdata_list
)){
9421 size
+= 7 * sizeof(INT
);
9422 funcrecord
->HelpContext
= desc
->helpcontext
;
9423 if(desc
->HelpString
)
9424 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9426 funcrecord
->oHelpString
= -1;
9428 funcrecord
->oEntry
= -1;
9429 else if(IS_INTRESOURCE(desc
->Entry
))
9430 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9432 funcrecord
->oEntry
= desc
->Entry
->offset
;
9433 funcrecord
->res9
= -1;
9434 funcrecord
->resA
= -1;
9435 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9436 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9437 }else if(desc
->HelpStringContext
!= 0){
9438 size
+= 6 * sizeof(INT
);
9439 funcrecord
->HelpContext
= desc
->helpcontext
;
9440 if(desc
->HelpString
)
9441 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9443 funcrecord
->oHelpString
= -1;
9445 funcrecord
->oEntry
= -1;
9446 else if(IS_INTRESOURCE(desc
->Entry
))
9447 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9449 funcrecord
->oEntry
= desc
->Entry
->offset
;
9450 funcrecord
->res9
= -1;
9451 funcrecord
->resA
= -1;
9452 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9453 }else if(desc
->Entry
){
9454 size
+= 3 * sizeof(INT
);
9455 funcrecord
->HelpContext
= desc
->helpcontext
;
9456 if(desc
->HelpString
)
9457 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9459 funcrecord
->oHelpString
= -1;
9461 funcrecord
->oEntry
= -1;
9462 else if(IS_INTRESOURCE(desc
->Entry
))
9463 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9465 funcrecord
->oEntry
= desc
->Entry
->offset
;
9466 }else if(desc
->HelpString
){
9467 size
+= 2 * sizeof(INT
);
9468 funcrecord
->HelpContext
= desc
->helpcontext
;
9469 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9470 }else if(desc
->helpcontext
){
9471 size
+= sizeof(INT
);
9472 funcrecord
->HelpContext
= desc
->helpcontext
;
9475 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9476 size
+= paramdefault_size
;
9478 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9479 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9481 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9482 if(desc
->pParamDesc
[j
].Name
)
9483 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9486 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9488 if(paramdefault_size
){
9489 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9490 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9491 else if(paramdefault_size
)
9496 size
+= sizeof(MSFT_ParameterInfo
);
9499 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9505 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9508 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9509 for(i
= 0; i
< info
->cVars
; ++i
){
9510 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9511 DWORD size
= 5 * sizeof(INT
);
9513 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9514 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9515 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9516 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9518 if(desc
->vardesc
.varkind
== VAR_CONST
){
9519 varrecord
->vardescsize
+= sizeof(VARIANT
);
9520 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9522 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9525 if(desc
->HelpStringContext
!= 0){
9526 size
+= 5 * sizeof(INT
);
9527 varrecord
->HelpContext
= desc
->HelpContext
;
9528 if(desc
->HelpString
)
9529 varrecord
->HelpString
= desc
->HelpString
->offset
;
9531 varrecord
->HelpString
= -1;
9532 varrecord
->res9
= -1;
9533 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9534 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9535 }else if(!list_empty(&desc
->custdata_list
)){
9536 size
+= 4 * sizeof(INT
);
9537 varrecord
->HelpContext
= desc
->HelpContext
;
9538 if(desc
->HelpString
)
9539 varrecord
->HelpString
= desc
->HelpString
->offset
;
9541 varrecord
->HelpString
= -1;
9542 varrecord
->res9
= -1;
9543 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9544 }else if(desc
->HelpString
){
9545 size
+= 2 * sizeof(INT
);
9546 varrecord
->HelpContext
= desc
->HelpContext
;
9547 if(desc
->HelpString
)
9548 varrecord
->HelpString
= desc
->HelpString
->offset
;
9550 varrecord
->HelpString
= -1;
9551 }else if(desc
->HelpContext
!= 0){
9552 size
+= sizeof(INT
);
9553 varrecord
->HelpContext
= desc
->HelpContext
;
9556 varrecord
->Info
= size
| (i
<< 16);
9562 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9565 memid
= (MEMBERID
*)varrecord
;
9566 for(i
= 0; i
< info
->cFuncs
; ++i
){
9567 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9568 *memid
= desc
->funcdesc
.memid
;
9571 for(i
= 0; i
< info
->cVars
; ++i
){
9572 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9573 *memid
= desc
->vardesc
.memid
;
9577 name
= (UINT
*)memid
;
9578 for(i
= 0; i
< info
->cFuncs
; ++i
){
9579 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9581 *name
= desc
->Name
->offset
;
9586 for(i
= 0; i
< info
->cVars
; ++i
){
9587 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9589 *name
= desc
->Name
->offset
;
9598 typedef struct tagWMSFT_RefChunk
{
9605 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9607 DWORD offs
= file
->ref_seg
.len
, i
;
9608 WMSFT_RefChunk
*chunk
;
9610 file
->ref_seg
.len
+= info
->cImplTypes
* sizeof(WMSFT_RefChunk
);
9611 if(!file
->ref_seg
.data
)
9612 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9614 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9616 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9618 for(i
= 0; i
< info
->cImplTypes
; ++i
){
9619 chunk
->href
= info
->impltypes
[i
].hRef
;
9620 chunk
->res04
= info
->impltypes
[i
].implflags
;
9622 if(i
< info
->cImplTypes
- 1)
9623 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9632 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9636 size
= sizeof(MSFT_TypeInfoBase
);
9639 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9640 if(info
->wTypeFlags
& TYPEFLAG_FDUAL
)
9641 base
->typekind
= TKIND_DISPATCH
;
9643 base
->typekind
= info
->typekind
;
9644 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9645 base
->typekind
|= (info
->cbAlignment
<< 11) | (info
->cbAlignment
<< 6);
9646 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9651 base
->cElement
= (info
->cVars
<< 16) | info
->cFuncs
;
9657 base
->posguid
= info
->guid
->offset
;
9660 base
->flags
= info
->wTypeFlags
;
9662 base
->NameOffset
= info
->Name
->offset
;
9664 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9665 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9667 base
->NameOffset
= -1;
9669 base
->version
= (info
->wMinorVerNum
<< 16) | info
->wMajorVerNum
;
9671 base
->docstringoffs
= info
->DocString
->offset
;
9673 base
->docstringoffs
= -1;
9674 base
->helpstringcontext
= info
->dwHelpStringContext
;
9675 base
->helpcontext
= info
->dwHelpContext
;
9676 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9677 base
->cImplTypes
= info
->cImplTypes
;
9678 base
->cbSizeVft
= info
->cbSizeVft
;
9679 base
->size
= info
->cbSizeInstance
;
9680 if(info
->typekind
== TKIND_COCLASS
){
9681 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9682 }else if(info
->typekind
== TKIND_ALIAS
){
9683 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9684 }else if(info
->typekind
== TKIND_MODULE
){
9686 base
->datatype1
= info
->DllName
->offset
;
9688 base
->datatype1
= -1;
9690 if(info
->cImplTypes
> 0)
9691 base
->datatype1
= info
->impltypes
[0].hRef
;
9693 base
->datatype1
= -1;
9695 base
->datatype2
= index
; /* FIXME: i think there's more here */
9703 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9707 file
->typeinfo_seg
.len
= 0;
9708 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9709 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9710 *junk
= file
->typeinfo_seg
.len
;
9712 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9715 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9716 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9718 file
->aux_seg
.len
= 0;
9719 file
->aux_seg
.data
= NULL
;
9721 file
->typeinfo_seg
.len
= 0;
9722 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9723 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9724 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9725 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9729 typedef struct tagWMSFT_ImpFile
{
9735 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9738 WMSFT_ImpFile
*impfile
;
9740 DWORD last_offs
= 0;
9742 file
->impfile_seg
.len
= 0;
9743 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9747 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9751 path
= implib
->name
;
9752 size
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
), NULL
, 0, NULL
, NULL
);
9754 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9757 size
+= sizeof(INT16
);
9759 size
= (size
+ 4) & ~0x3;
9763 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9766 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9768 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9769 int strlen
= 0, size
;
9771 impfile
= (WMSFT_ImpFile
*)data
;
9772 impfile
->guid_offs
= implib
->guid
->offset
;
9773 impfile
->lcid
= implib
->lcid
;
9774 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9776 data
+= sizeof(WMSFT_ImpFile
);
9779 WCHAR
*path
= strrchrW(implib
->name
, '\\');
9783 path
= implib
->name
;
9784 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, strlenW(path
),
9785 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9787 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9790 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9792 size
= strlen
+ sizeof(INT16
);
9794 size
= (size
+ 4) & ~0x3;
9797 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9800 implib
->offset
= last_offs
;
9801 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9805 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9808 TLBRefType
*ref_type
;
9811 WMSFT_compile_impfile(This
, file
);
9813 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9814 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
9816 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9817 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9818 if(ref_type
->index
== TLB_REF_USE_GUID
){
9819 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9820 info
->oGuid
= ref_type
->guid
->offset
;
9822 info
->oGuid
= ref_type
->index
;
9823 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9829 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9831 file
->guidhash_seg
.len
= 0x80;
9832 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
9833 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9836 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9838 file
->namehash_seg
.len
= 0x200;
9839 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
9840 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9843 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9845 if(contents
&& contents
->len
){
9846 segdir
->offset
= *running_offset
;
9847 segdir
->length
= contents
->len
;
9848 *running_offset
+= segdir
->length
;
9850 segdir
->offset
= -1;
9854 /* TODO: do these ever change? */
9856 segdir
->res0c
= 0xf;
9859 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
9863 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
9866 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
9870 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
9872 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9873 base
->memoffset
+= file_len
;
9880 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
9882 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
9883 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
9884 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
9885 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
9886 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
9887 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
9888 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
9889 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
9890 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
9891 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
9892 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
9893 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
9894 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
9895 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
9898 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
9900 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9902 DWORD written
, junk_size
, junk_offs
, running_offset
;
9909 TRACE("%p\n", This
);
9911 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
9912 if(This
->typeinfos
[i
]->needs_layout
)
9913 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
9915 memset(&file
, 0, sizeof(file
));
9917 file
.header
.magic1
= 0x5446534D;
9918 file
.header
.magic2
= 0x00010002;
9919 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
9920 file
.header
.lcid2
= This
->set_lcid
;
9921 file
.header
.varflags
= 0x40 | This
->syskind
;
9923 file
.header
.varflags
|= 0x10;
9924 if (This
->HelpStringDll
)
9925 file
.header
.varflags
|= HELPDLLFLAG
;
9926 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
9927 file
.header
.flags
= This
->libflags
;
9928 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
9929 file
.header
.helpcontext
= This
->dwHelpContext
;
9930 file
.header
.res44
= 0x20;
9931 file
.header
.res48
= 0x80;
9932 file
.header
.dispatchpos
= This
->dispatch_href
;
9934 WMSFT_compile_namehash(This
, &file
);
9935 /* do name and string compilation to get offsets for other compilations */
9936 hres
= WMSFT_compile_names(This
, &file
);
9938 WMSFT_free_file(&file
);
9942 hres
= WMSFT_compile_strings(This
, &file
);
9944 WMSFT_free_file(&file
);
9948 WMSFT_compile_guidhash(This
, &file
);
9949 hres
= WMSFT_compile_guids(This
, &file
);
9951 WMSFT_free_file(&file
);
9956 file
.header
.helpfile
= This
->HelpFile
->offset
;
9958 file
.header
.helpfile
= -1;
9961 file
.header
.helpstring
= This
->DocString
->offset
;
9963 file
.header
.helpstring
= -1;
9965 /* do some more segment compilation */
9966 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
9967 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
9970 file
.header
.NameOffset
= This
->Name
->offset
;
9972 file
.header
.NameOffset
= -1;
9974 file
.header
.CustomDataOffset
= -1; /* TODO SetCustData not impl yet */
9977 file
.header
.posguid
= This
->guid
->offset
;
9979 file
.header
.posguid
= -1;
9981 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
9982 if(file
.header
.varflags
& HELPDLLFLAG
)
9983 junk_size
+= sizeof(DWORD
);
9985 junk
= heap_alloc_zero(junk_size
);
9986 if(file
.header
.varflags
& HELPDLLFLAG
){
9987 *junk
= This
->HelpStringDll
->offset
;
9996 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
9997 WMSFT_compile_impinfo(This
, &file
);
10001 TRACE("header at: 0x%x\n", running_offset
);
10002 running_offset
+= sizeof(file
.header
);
10004 TRACE("junk at: 0x%x\n", running_offset
);
10005 running_offset
+= junk_size
;
10007 TRACE("segdir at: 0x%x\n", running_offset
);
10008 running_offset
+= sizeof(file
.segdir
);
10010 TRACE("typeinfo at: 0x%x\n", running_offset
);
10011 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10013 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10014 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10016 TRACE("guidtab at: 0x%x\n", running_offset
);
10017 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10019 TRACE("reftab at: 0x%x\n", running_offset
);
10020 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10022 TRACE("impinfo at: 0x%x\n", running_offset
);
10023 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10025 TRACE("impfiles at: 0x%x\n", running_offset
);
10026 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10028 TRACE("namehashtab at: 0x%x\n", running_offset
);
10029 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10031 TRACE("nametab at: 0x%x\n", running_offset
);
10032 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10034 TRACE("stringtab at: 0x%x\n", running_offset
);
10035 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10037 TRACE("typdesc at: 0x%x\n", running_offset
);
10038 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10040 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10041 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10043 TRACE("custdata at: 0x%x\n", running_offset
);
10044 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10046 TRACE("cdguids at: 0x%x\n", running_offset
);
10047 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10049 TRACE("res0e at: 0x%x\n", running_offset
);
10050 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10052 TRACE("res0f at: 0x%x\n", running_offset
);
10053 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10055 TRACE("aux_seg at: 0x%x\n", running_offset
);
10057 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10059 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10060 FILE_ATTRIBUTE_NORMAL
, 0);
10061 if (outfile
== INVALID_HANDLE_VALUE
){
10062 WMSFT_free_file(&file
);
10064 return TYPE_E_IOERROR
;
10067 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10069 WMSFT_free_file(&file
);
10070 CloseHandle(outfile
);
10072 return TYPE_E_IOERROR
;
10075 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10078 WMSFT_free_file(&file
);
10079 CloseHandle(outfile
);
10080 return TYPE_E_IOERROR
;
10083 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10085 WMSFT_free_file(&file
);
10086 CloseHandle(outfile
);
10087 return TYPE_E_IOERROR
;
10090 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10091 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10092 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10093 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10094 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10095 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10096 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10097 WMSFT_write_segment(outfile
, &file
.name_seg
);
10098 WMSFT_write_segment(outfile
, &file
.string_seg
);
10099 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10100 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10101 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10102 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10103 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10105 WMSFT_free_file(&file
);
10107 CloseHandle(outfile
);
10112 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10115 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10116 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10120 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10121 REFGUID guid
, VARIANT
*varVal
)
10123 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10124 FIXME("%p %s %p - stub\n", This
, debugstr_guid(guid
), varVal
);
10128 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10129 ULONG helpStringContext
)
10131 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10132 FIXME("%p %u - stub\n", This
, helpStringContext
);
10136 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10139 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10140 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10143 return E_INVALIDARG
;
10145 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10150 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10151 ICreateTypeLib2_fnQueryInterface
,
10152 ICreateTypeLib2_fnAddRef
,
10153 ICreateTypeLib2_fnRelease
,
10154 ICreateTypeLib2_fnCreateTypeInfo
,
10155 ICreateTypeLib2_fnSetName
,
10156 ICreateTypeLib2_fnSetVersion
,
10157 ICreateTypeLib2_fnSetGuid
,
10158 ICreateTypeLib2_fnSetDocString
,
10159 ICreateTypeLib2_fnSetHelpFileName
,
10160 ICreateTypeLib2_fnSetHelpContext
,
10161 ICreateTypeLib2_fnSetLcid
,
10162 ICreateTypeLib2_fnSetLibFlags
,
10163 ICreateTypeLib2_fnSaveAllChanges
,
10164 ICreateTypeLib2_fnDeleteTypeInfo
,
10165 ICreateTypeLib2_fnSetCustData
,
10166 ICreateTypeLib2_fnSetHelpStringContext
,
10167 ICreateTypeLib2_fnSetHelpStringDll
10170 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10171 REFIID riid
, void **object
)
10173 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10175 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10178 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10180 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10182 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10185 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10187 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10189 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10192 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10195 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10197 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10199 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10204 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10207 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10211 TRACE("%p %x\n", This
, typeFlags
);
10213 if (typeFlags
& TYPEFLAG_FDUAL
) {
10214 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10216 ITypeInfo
*dispatch
;
10220 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10224 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10225 ITypeLib_Release(stdole
);
10229 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10230 ITypeInfo_Release(dispatch
);
10235 old_flags
= This
->wTypeFlags
;
10236 This
->wTypeFlags
= typeFlags
;
10238 hres
= ICreateTypeInfo2_LayOut(iface
);
10239 if (FAILED(hres
)) {
10240 This
->wTypeFlags
= old_flags
;
10247 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10250 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10252 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10255 return E_INVALIDARG
;
10257 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10262 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10265 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10267 TRACE("%p %d\n", This
, helpContext
);
10269 This
->dwHelpContext
= helpContext
;
10274 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10275 WORD majorVerNum
, WORD minorVerNum
)
10277 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10279 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10281 This
->wMajorVerNum
= majorVerNum
;
10282 This
->wMinorVerNum
= minorVerNum
;
10287 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10288 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10290 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10292 ITypeLib
*container
;
10293 TLBRefType
*ref_type
;
10295 TYPEATTR
*typeattr
;
10299 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10301 if (!typeInfo
|| !refType
)
10302 return E_INVALIDARG
;
10304 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10308 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10309 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10311 ITypeLib_Release(container
);
10313 *refType
= target
->hreftype
;
10318 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10319 if (FAILED(hres
)) {
10320 ITypeLib_Release(container
);
10324 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10325 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10326 implib
->lcid
== libattr
->lcid
&&
10327 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10328 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10332 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10333 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10335 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10336 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10337 implib
->name
= SysAllocString(our_container
->path
);
10339 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10340 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10342 implib
->name
= NULL
;
10343 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10347 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10348 implib
->lcid
= libattr
->lcid
;
10349 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10350 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10352 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10355 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10356 ITypeLib_Release(container
);
10358 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10363 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10364 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10365 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10366 ref_type
->tkind
== typeattr
->typekind
)
10371 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10372 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10374 ref_type
->tkind
= typeattr
->typekind
;
10375 ref_type
->pImpTLInfo
= implib
;
10376 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10378 ref_type
->index
= TLB_REF_USE_GUID
;
10380 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10382 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10385 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10387 *refType
= ref_type
->reference
| 0x1;
10389 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10390 This
->pTypeLib
->dispatch_href
= *refType
;
10395 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10396 UINT index
, FUNCDESC
*funcDesc
)
10398 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10399 TLBFuncDesc tmp_func_desc
, *func_desc
;
10404 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10406 if (!funcDesc
|| funcDesc
->oVft
& 3)
10407 return E_INVALIDARG
;
10409 switch (This
->typekind
) {
10411 if (funcDesc
->funckind
!= FUNC_STATIC
)
10412 return TYPE_E_BADMODULEKIND
;
10414 case TKIND_DISPATCH
:
10415 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10416 return TYPE_E_BADMODULEKIND
;
10419 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10420 return TYPE_E_BADMODULEKIND
;
10423 if (index
> This
->cFuncs
)
10424 return TYPE_E_ELEMENTNOTFOUND
;
10426 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10427 !funcDesc
->cParams
)
10428 return TYPE_E_INCONSISTENTPROPFUNCS
;
10431 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10432 funcDesc
->oVft
% 8 != 0)
10433 return E_INVALIDARG
;
10436 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10437 TLBFuncDesc_Constructor(&tmp_func_desc
);
10439 tmp_func_desc
.funcdesc
= *funcDesc
;
10441 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10442 tmp_func_desc
.funcdesc
.oVft
|= 1;
10444 if (funcDesc
->cScodes
) {
10445 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10446 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10448 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10450 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10451 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10452 buf_size
+= sizeof(ELEMDESC
);
10453 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10455 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10456 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10458 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10459 if (FAILED(hres
)) {
10460 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10461 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10465 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10466 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10467 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10468 if (FAILED(hres
)) {
10469 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10470 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10473 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10474 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10475 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10476 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10477 if (FAILED(hres
)) {
10478 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10479 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10485 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10487 if (This
->funcdescs
) {
10488 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10489 sizeof(TLBFuncDesc
) * (This
->cFuncs
+ 1));
10491 if (index
< This
->cFuncs
) {
10492 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10493 (This
->cFuncs
- index
) * sizeof(TLBFuncDesc
));
10494 func_desc
= This
->funcdescs
+ index
;
10496 func_desc
= This
->funcdescs
+ This
->cFuncs
;
10498 /* move custdata lists to the new memory location */
10499 for(i
= 0; i
< This
->cFuncs
+ 1; ++i
){
10501 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10502 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10503 list_init(&fd
->custdata_list
);
10505 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10506 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10511 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10513 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10514 list_init(&func_desc
->custdata_list
);
10518 This
->needs_layout
= TRUE
;
10523 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10524 UINT index
, HREFTYPE refType
)
10526 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10527 TLBImplType
*impl_type
;
10530 TRACE("%p %u %d\n", This
, index
, refType
);
10532 switch(This
->typekind
){
10533 case TKIND_COCLASS
: {
10535 FIXME("Unhandled index: -1\n");
10539 if(index
!= This
->cImplTypes
)
10540 return TYPE_E_ELEMENTNOTFOUND
;
10544 case TKIND_INTERFACE
:
10545 case TKIND_DISPATCH
:
10546 if (index
!= 0 || This
->cImplTypes
)
10547 return TYPE_E_ELEMENTNOTFOUND
;
10550 FIXME("Unimplemented typekind: %d\n", This
->typekind
);
10554 if (This
->impltypes
){
10557 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10558 sizeof(TLBImplType
) * (This
->cImplTypes
+ 1));
10560 if (index
< This
->cImplTypes
) {
10561 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10562 (This
->cImplTypes
- index
) * sizeof(TLBImplType
));
10563 impl_type
= This
->impltypes
+ index
;
10565 impl_type
= This
->impltypes
+ This
->cImplTypes
;
10567 /* move custdata lists to the new memory location */
10568 for(i
= 0; i
< This
->cImplTypes
+ 1; ++i
){
10570 TLBImplType
*it
= &This
->impltypes
[i
];
10571 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10572 list_init(&it
->custdata_list
);
10574 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10575 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10580 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10582 memset(impl_type
, 0, sizeof(TLBImplType
));
10583 TLBImplType_Constructor(impl_type
);
10584 impl_type
->hRef
= refType
;
10586 ++This
->cImplTypes
;
10588 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10589 This
->wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10591 hres
= ICreateTypeInfo2_LayOut(iface
);
10598 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10599 UINT index
, INT implTypeFlags
)
10601 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10602 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10604 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10606 if (This
->typekind
!= TKIND_COCLASS
)
10607 return TYPE_E_BADMODULEKIND
;
10609 if (index
>= This
->cImplTypes
)
10610 return TYPE_E_ELEMENTNOTFOUND
;
10612 impl_type
->implflags
= implTypeFlags
;
10617 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10620 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10622 TRACE("%p %d\n", This
, alignment
);
10624 This
->cbAlignment
= alignment
;
10629 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10632 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10634 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10637 return E_INVALIDARG
;
10639 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10641 This
->lpstrSchema
= This
->Schema
->str
;
10646 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10647 UINT index
, VARDESC
*varDesc
)
10649 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10650 TLBVarDesc
*var_desc
;
10652 TRACE("%p %u %p\n", This
, index
, varDesc
);
10654 if (This
->vardescs
){
10657 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10658 sizeof(TLBVarDesc
) * (This
->cVars
+ 1));
10660 if (index
< This
->cVars
) {
10661 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10662 (This
->cVars
- index
) * sizeof(TLBVarDesc
));
10663 var_desc
= This
->vardescs
+ index
;
10665 var_desc
= This
->vardescs
+ This
->cVars
;
10667 /* move custdata lists to the new memory location */
10668 for(i
= 0; i
< This
->cVars
+ 1; ++i
){
10670 TLBVarDesc
*var
= &This
->vardescs
[i
];
10671 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10672 list_init(&var
->custdata_list
);
10674 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10675 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10680 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10682 TLBVarDesc_Constructor(var_desc
);
10683 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10684 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10688 This
->needs_layout
= TRUE
;
10693 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10694 UINT index
, LPOLESTR
*names
, UINT numNames
)
10696 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10697 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10700 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10703 return E_INVALIDARG
;
10705 if (index
>= This
->cFuncs
|| numNames
== 0)
10706 return TYPE_E_ELEMENTNOTFOUND
;
10708 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10709 if(numNames
> func_desc
->funcdesc
.cParams
)
10710 return TYPE_E_ELEMENTNOTFOUND
;
10712 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10713 return TYPE_E_ELEMENTNOTFOUND
;
10715 for(i
= 0; i
< This
->cFuncs
; ++i
) {
10716 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10717 if (iter
->Name
&& !strcmpW(TLB_get_bstr(iter
->Name
), *names
)) {
10718 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10719 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10720 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10722 return TYPE_E_AMBIGUOUSNAME
;
10726 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10728 for (i
= 1; i
< numNames
; ++i
) {
10729 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10730 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10736 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10737 UINT index
, LPOLESTR name
)
10739 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10741 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10744 return E_INVALIDARG
;
10746 if(index
>= This
->cVars
)
10747 return TYPE_E_ELEMENTNOTFOUND
;
10749 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10753 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10754 TYPEDESC
*tdescAlias
)
10756 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10759 TRACE("%p %p\n", This
, tdescAlias
);
10762 return E_INVALIDARG
;
10764 if(This
->typekind
!= TKIND_ALIAS
)
10765 return TYPE_E_BADMODULEKIND
;
10767 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->cbSizeInstance
, &This
->cbAlignment
);
10771 heap_free(This
->tdescAlias
);
10772 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10773 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10778 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10779 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10781 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10782 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10786 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10787 UINT index
, LPOLESTR docString
)
10789 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10790 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10792 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10795 return E_INVALIDARG
;
10797 if(index
>= This
->cFuncs
)
10798 return TYPE_E_ELEMENTNOTFOUND
;
10800 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10805 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10806 UINT index
, LPOLESTR docString
)
10808 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10809 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10811 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10814 return E_INVALIDARG
;
10816 if(index
>= This
->cVars
)
10817 return TYPE_E_ELEMENTNOTFOUND
;
10819 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10824 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10825 UINT index
, DWORD helpContext
)
10827 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10828 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10830 TRACE("%p %u %d\n", This
, index
, helpContext
);
10832 if(index
>= This
->cFuncs
)
10833 return TYPE_E_ELEMENTNOTFOUND
;
10835 func_desc
->helpcontext
= helpContext
;
10840 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10841 UINT index
, DWORD helpContext
)
10843 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10844 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10846 TRACE("%p %u %d\n", This
, index
, helpContext
);
10848 if(index
>= This
->cVars
)
10849 return TYPE_E_ELEMENTNOTFOUND
;
10851 var_desc
->HelpContext
= helpContext
;
10856 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10857 UINT index
, BSTR bstrMops
)
10859 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10860 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10864 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10867 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10869 TRACE("%p %p\n", This
, idlDesc
);
10872 return E_INVALIDARG
;
10874 This
->idldescType
.dwReserved
= idlDesc
->dwReserved
;
10875 This
->idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
10880 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
10882 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10884 TLBFuncDesc
*func_desc
;
10885 UINT user_vft
= 0, i
, depth
= 0;
10886 HRESULT hres
= S_OK
;
10888 TRACE("%p\n", This
);
10890 This
->needs_layout
= FALSE
;
10892 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
10896 if (This
->typekind
== TKIND_INTERFACE
) {
10901 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
10903 if (SUCCEEDED(hres
)) {
10904 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
10906 if (SUCCEEDED(hres
)) {
10907 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
10908 if (FAILED(hres
)) {
10909 ITypeInfo_Release(inh
);
10910 ITypeInfo_Release(tinfo
);
10913 This
->cbSizeVft
= attr
->cbSizeVft
;
10914 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
10918 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
10919 if(SUCCEEDED(hres
)){
10921 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
10922 if(SUCCEEDED(hres
)){
10923 ITypeInfo_Release(inh
);
10927 }while(SUCCEEDED(hres
));
10930 ITypeInfo_Release(inh
);
10931 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10932 This
->cbSizeVft
= 0;
10935 ITypeInfo_Release(tinfo
);
10938 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
10939 This
->cbSizeVft
= 0;
10942 ITypeInfo_Release(tinfo
);
10945 } else if (This
->typekind
== TKIND_DISPATCH
)
10946 This
->cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
10948 This
->cbSizeVft
= 0;
10950 func_desc
= This
->funcdescs
;
10952 while (i
< This
->cFuncs
) {
10953 if (!(func_desc
->funcdesc
.oVft
& 0x1))
10954 func_desc
->funcdesc
.oVft
= This
->cbSizeVft
;
10956 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
10957 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
10959 This
->cbSizeVft
+= This
->pTypeLib
->ptr_size
;
10961 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
10964 BOOL reset
= FALSE
;
10966 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
10968 iter
= This
->funcdescs
;
10969 while (j
< This
->cFuncs
) {
10970 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
10972 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->cFuncs
;
10975 ++func_desc
->funcdesc
.memid
;
10976 iter
= This
->funcdescs
;
10989 if (user_vft
> This
->cbSizeVft
)
10990 This
->cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
10992 for(i
= 0; i
< This
->cVars
; ++i
){
10993 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
10994 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
10996 BOOL reset
= FALSE
;
10999 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11001 iter
= This
->vardescs
;
11002 while (j
< This
->cVars
) {
11003 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11005 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->cVars
;
11008 ++var_desc
->vardesc
.memid
;
11009 iter
= This
->vardescs
;
11019 ITypeInfo_Release(tinfo
);
11023 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11026 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11027 FIXME("%p %u - stub\n", This
, index
);
11031 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11032 MEMBERID memid
, INVOKEKIND invKind
)
11034 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11035 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11039 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11042 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11043 FIXME("%p %u - stub\n", This
, index
);
11047 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11050 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11051 FIXME("%p %x - stub\n", This
, memid
);
11055 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11058 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11059 FIXME("%p %u - stub\n", This
, index
);
11063 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11064 REFGUID guid
, VARIANT
*varVal
)
11068 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11070 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11072 if (!guid
|| !varVal
)
11073 return E_INVALIDARG
;
11075 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11077 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11080 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11081 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11083 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11084 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11088 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11089 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11091 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11092 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11096 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11097 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11099 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11100 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11104 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11105 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11107 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11108 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11112 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11113 ULONG helpStringContext
)
11115 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11117 TRACE("%p %u\n", This
, helpStringContext
);
11119 This
->dwHelpStringContext
= helpStringContext
;
11124 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11125 UINT index
, ULONG helpStringContext
)
11127 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11128 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11132 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11133 UINT index
, ULONG helpStringContext
)
11135 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11136 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11140 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11142 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11143 FIXME("%p - stub\n", This
);
11147 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11150 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11152 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11155 return E_INVALIDARG
;
11157 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11162 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11163 ICreateTypeInfo2_fnQueryInterface
,
11164 ICreateTypeInfo2_fnAddRef
,
11165 ICreateTypeInfo2_fnRelease
,
11166 ICreateTypeInfo2_fnSetGuid
,
11167 ICreateTypeInfo2_fnSetTypeFlags
,
11168 ICreateTypeInfo2_fnSetDocString
,
11169 ICreateTypeInfo2_fnSetHelpContext
,
11170 ICreateTypeInfo2_fnSetVersion
,
11171 ICreateTypeInfo2_fnAddRefTypeInfo
,
11172 ICreateTypeInfo2_fnAddFuncDesc
,
11173 ICreateTypeInfo2_fnAddImplType
,
11174 ICreateTypeInfo2_fnSetImplTypeFlags
,
11175 ICreateTypeInfo2_fnSetAlignment
,
11176 ICreateTypeInfo2_fnSetSchema
,
11177 ICreateTypeInfo2_fnAddVarDesc
,
11178 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11179 ICreateTypeInfo2_fnSetVarName
,
11180 ICreateTypeInfo2_fnSetTypeDescAlias
,
11181 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11182 ICreateTypeInfo2_fnSetFuncDocString
,
11183 ICreateTypeInfo2_fnSetVarDocString
,
11184 ICreateTypeInfo2_fnSetFuncHelpContext
,
11185 ICreateTypeInfo2_fnSetVarHelpContext
,
11186 ICreateTypeInfo2_fnSetMops
,
11187 ICreateTypeInfo2_fnSetTypeIdldesc
,
11188 ICreateTypeInfo2_fnLayOut
,
11189 ICreateTypeInfo2_fnDeleteFuncDesc
,
11190 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11191 ICreateTypeInfo2_fnDeleteVarDesc
,
11192 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11193 ICreateTypeInfo2_fnDeleteImplType
,
11194 ICreateTypeInfo2_fnSetCustData
,
11195 ICreateTypeInfo2_fnSetFuncCustData
,
11196 ICreateTypeInfo2_fnSetParamCustData
,
11197 ICreateTypeInfo2_fnSetVarCustData
,
11198 ICreateTypeInfo2_fnSetImplTypeCustData
,
11199 ICreateTypeInfo2_fnSetHelpStringContext
,
11200 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11201 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11202 ICreateTypeInfo2_fnInvalidate
,
11203 ICreateTypeInfo2_fnSetName
11206 /******************************************************************************
11207 * ClearCustData (OLEAUT32.171)
11209 * Clear a custom data type's data.
11212 * lpCust [I] The custom data type instance
11217 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11219 if (lpCust
&& lpCust
->cCustData
)
11221 if (lpCust
->prgCustData
)
11225 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11226 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11228 CoTaskMemFree(lpCust
->prgCustData
);
11229 lpCust
->prgCustData
= NULL
;
11231 lpCust
->cCustData
= 0;