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
57 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
58 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
62 #define STATUS_SUCCESS ((NTSTATUS)0x00000000)
63 static BOOL WINAPI
GetFileInformationByHandleEx( HANDLE handle
, FILE_INFO_BY_HANDLE_CLASS
class,
64 LPVOID info
, DWORD size
)
72 case FileStandardInfo
:
74 case FileDispositionInfo
:
75 case FileAllocationInfo
:
76 case FileEndOfFileInfo
:
78 case FileCompressionInfo
:
79 case FileAttributeTagInfo
:
80 case FileIoPriorityHintInfo
:
81 case FileRemoteProtocolInfo
:
82 case FileFullDirectoryInfo
:
83 case FileFullDirectoryRestartInfo
:
85 case FileAlignmentInfo
:
87 case FileIdExtdDirectoryInfo
:
88 case FileIdExtdDirectoryRestartInfo
:
89 FIXME( "%p, %u, %p, %u\n", handle
, class, info
, size
);
90 SetLastError( ERROR_CALL_NOT_IMPLEMENTED
);
94 status
= NtQueryInformationFile( handle
, &io
, info
, size
, FileNameInformation
);
95 if (status
!= STATUS_SUCCESS
)
97 SetLastError( RtlNtStatusToDosError( status
) );
102 case FileIdBothDirectoryRestartInfo
:
103 case FileIdBothDirectoryInfo
:
104 status
= NtQueryDirectoryFile( handle
, NULL
, NULL
, NULL
, &io
, info
, size
,
105 FileIdBothDirectoryInformation
, FALSE
, NULL
,
106 (class == FileIdBothDirectoryRestartInfo
) );
107 if (status
!= STATUS_SUCCESS
)
109 SetLastError( RtlNtStatusToDosError( status
) );
115 SetLastError( ERROR_INVALID_PARAMETER
);
133 WORD type_id
; /* Type identifier */
134 WORD count
; /* Number of resources of this type */
135 DWORD resloader
; /* SetResourceHandler() */
141 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
142 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
143 static void TLB_FreeVarDesc(VARDESC
*);
145 /****************************************************************************
148 * Takes p_iVal (which is in little endian) and returns it
149 * in the host machine's byte order.
151 #ifdef WORDS_BIGENDIAN
152 static WORD
FromLEWord(WORD p_iVal
)
154 return (((p_iVal
& 0x00FF) << 8) |
155 ((p_iVal
& 0xFF00) >> 8));
159 static DWORD
FromLEDWord(DWORD p_iVal
)
161 return (((p_iVal
& 0x000000FF) << 24) |
162 ((p_iVal
& 0x0000FF00) << 8) |
163 ((p_iVal
& 0x00FF0000) >> 8) |
164 ((p_iVal
& 0xFF000000) >> 24));
167 #define FromLEWord(X) (X)
168 #define FromLEDWord(X) (X)
171 #define DISPATCH_HREF_OFFSET 0x01000000
172 #define DISPATCH_HREF_MASK 0xff000000
174 /****************************************************************************
177 * Fix byte order in any structure if necessary
179 #ifdef WORDS_BIGENDIAN
180 static void FromLEWords(void *p_Val
, int p_iSize
)
184 p_iSize
/= sizeof(WORD
);
187 *Val
= FromLEWord(*Val
);
194 static void FromLEDWords(void *p_Val
, int p_iSize
)
198 p_iSize
/= sizeof(DWORD
);
201 *Val
= FromLEDWord(*Val
);
207 #define FromLEWords(X,Y) /*nothing*/
208 #define FromLEDWords(X,Y) /*nothing*/
212 * Find a typelib key which matches a requested maj.min version.
214 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
216 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
220 INT best_maj
= -1, best_min
= -1;
223 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
224 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
226 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
229 len
= sizeof(key_name
);
231 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
235 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
237 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
239 if (*wMaj
== 0xffff && *wMin
== 0xffff)
241 if (v_maj
> best_maj
) best_maj
= v_maj
;
242 if (v_min
> best_min
) best_min
= v_min
;
244 else if (*wMaj
== v_maj
)
251 break; /* exact match */
253 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
256 len
= sizeof(key_name
);
260 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
262 if (*wMaj
== 0xffff && *wMin
== 0xffff)
264 if (best_maj
>= 0 && best_min
>= 0)
272 if (*wMaj
== best_maj
&& best_min
>= 0)
280 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
281 /* buffer must be at least 60 characters long */
282 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
284 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
285 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
287 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
288 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
289 sprintfW( buffer
+ strlenW(buffer
), VersionFormatW
, wMaj
, wMin
);
293 /* get the path of an interface key, in the form "Interface\\<guid>" */
294 /* buffer must be at least 50 characters long */
295 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
297 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
299 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
300 StringFromGUID2( guid
, buffer
+ strlenW(buffer
), 40 );
304 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
305 /* buffer must be at least 16 characters long */
306 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
308 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
309 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
310 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
311 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
313 sprintfW( buffer
, LcidFormatW
, lcid
);
316 case SYS_WIN16
: strcatW( buffer
, win16W
); break;
317 case SYS_WIN32
: strcatW( buffer
, win32W
); break;
318 case SYS_WIN64
: strcatW( buffer
, win64W
); break;
320 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
326 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
328 struct tlibredirect_data
342 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
343 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
344 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
346 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
350 WCHAR Path
[MAX_PATH
];
353 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
357 ACTCTX_SECTION_KEYED_DATA data
;
359 data
.cbSize
= sizeof(data
);
360 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
362 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
366 if (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
)
367 return TYPE_E_LIBNOTREGISTERED
;
369 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
370 len
= SearchPathW( NULL
, nameW
, NULL
, sizeof(Path
)/sizeof(WCHAR
), Path
, NULL
);
371 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
373 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
374 *path
= SysAllocString( Path
);
379 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
380 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
382 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
383 if (res
== ERROR_FILE_NOT_FOUND
)
385 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
386 return TYPE_E_LIBNOTREGISTERED
;
388 else if (res
!= ERROR_SUCCESS
)
390 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
391 return TYPE_E_REGISTRYACCESS
;
396 LONG dwPathLen
= sizeof(Path
);
398 get_lcid_subkey( myLCID
, syskind
, buffer
);
400 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
404 else if (myLCID
== lcid
)
406 /* try with sub-langid */
407 myLCID
= SUBLANGID(lcid
);
409 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
411 /* try with system langid */
421 *path
= SysAllocString( Path
);
426 TRACE_(typelib
)("-- 0x%08x\n", hr
);
430 /****************************************************************************
431 * QueryPathOfRegTypeLib [OLEAUT32.164]
433 * Gets the path to a registered type library.
436 * guid [I] referenced guid
437 * wMaj [I] major version
438 * wMin [I] minor version
440 * path [O] path of typelib
444 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
445 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
448 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
452 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
457 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
460 /******************************************************************************
461 * CreateTypeLib [OLEAUT32.160] creates a typelib
467 HRESULT WINAPI
CreateTypeLib(
468 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
470 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
474 /******************************************************************************
475 * LoadTypeLib [OLEAUT32.161]
477 * Loads a type library
480 * szFile [I] Name of file to load from.
481 * pptLib [O] Pointer that receives ITypeLib object on success.
488 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
490 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
492 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
493 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
496 /******************************************************************************
497 * LoadTypeLibEx [OLEAUT32.183]
499 * Loads and optionally registers a type library
505 HRESULT WINAPI
LoadTypeLibEx(
506 LPCOLESTR szFile
, /* [in] Name of file to load from */
507 REGKIND regkind
, /* [in] Specify kind of registration */
508 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
510 WCHAR szPath
[MAX_PATH
+1];
513 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
517 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
522 case REGKIND_DEFAULT
:
523 /* don't register typelibs supplied with full path. Experimentation confirms the following */
524 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
525 (szFile
[0] && (szFile
[1] == ':'))) break;
526 /* else fall-through */
528 case REGKIND_REGISTER
:
529 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
531 ITypeLib_Release(*pptLib
);
539 TRACE(" returns %08x\n",res
);
543 /******************************************************************************
544 * LoadRegTypeLib [OLEAUT32.162]
546 * Loads a registered type library.
549 * rguid [I] GUID of the registered type library.
550 * wVerMajor [I] major version.
551 * wVerMinor [I] minor version.
552 * lcid [I] locale ID.
553 * ppTLib [O] pointer that receives an ITypeLib object on success.
557 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
560 HRESULT WINAPI
LoadRegTypeLib(
572 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
576 res
= LoadTypeLib(bstr
, ppTLib
);
583 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
586 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
587 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
591 ITypeLib_Release(*ppTLib
);
593 res
= TYPE_E_LIBNOTREGISTERED
;
599 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
605 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
606 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
607 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
608 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
609 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
610 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
612 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
617 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
618 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
619 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
621 get_interface_key( &tattr
->guid
, keyName
);
622 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
623 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
626 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
627 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
629 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
630 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
631 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
632 (const BYTE
*)PSOA
, sizeof PSOA
);
636 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
637 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
638 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
639 (const BYTE
*)PSOA
, sizeof PSOA
);
643 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
644 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
647 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
648 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
650 StringFromGUID2(&libattr
->guid
, buffer
, 40);
651 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
652 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
653 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
654 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
655 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
663 /******************************************************************************
664 * RegisterTypeLib [OLEAUT32.163]
665 * Adds information about a type library to the System Registry
667 * Docs: ITypeLib FAR * ptlib
668 * Docs: OLECHAR FAR* szFullPath
669 * Docs: OLECHAR FAR* szHelpDir
675 HRESULT WINAPI
RegisterTypeLib(
676 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
677 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
678 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
690 if (ptlib
== NULL
|| szFullPath
== NULL
)
693 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
697 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
700 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
703 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
704 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
708 /* Set the human-readable name of the typelib */
709 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
713 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
714 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
720 /* Make up the name of the typelib path subkey */
721 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
723 /* Create the typelib path subkey */
724 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
725 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
727 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
728 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
736 /* Create the flags subkey */
737 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
738 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
740 /* FIXME: is %u correct? */
741 static const WCHAR formatW
[] = {'%','u',0};
743 sprintfW(buf
, formatW
, attr
->wLibFlags
);
744 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
745 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
753 /* create the helpdir subkey */
754 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
755 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
757 BOOL freeHelpDir
= FALSE
;
760 /* if we created a new key, and helpDir was null, set the helpdir
761 to the directory which contains the typelib. However,
762 if we just opened an existing key, we leave the helpdir alone */
763 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
764 szHelpDir
= SysAllocString(szFullPath
);
765 pIndexStr
= strrchrW(szHelpDir
, '\\');
772 /* if we have an szHelpDir, set it! */
773 if (szHelpDir
!= NULL
) {
774 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
775 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
781 if (freeHelpDir
) SysFreeString(szHelpDir
);
793 /* register OLE Automation-compatible interfaces for this typelib */
794 types
= ITypeLib_GetTypeInfoCount(ptlib
);
795 for (tidx
=0; tidx
<types
; tidx
++) {
796 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
797 LPOLESTR name
= NULL
;
798 ITypeInfo
*tinfo
= NULL
;
800 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
803 case TKIND_INTERFACE
:
804 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
805 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
809 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
810 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
814 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
819 TYPEATTR
*tattr
= NULL
;
820 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
823 TRACE_(typelib
)("guid=%s, flags=%04x (",
824 debugstr_guid(&tattr
->guid
),
827 if (TRACE_ON(typelib
)) {
828 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
848 /* Register all dispinterfaces (which includes dual interfaces) and
849 oleautomation interfaces */
850 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
851 kind
== TKIND_DISPATCH
)
854 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
856 /* register interface<->typelib coupling */
857 TLB_register_interface(attr
, name
, tattr
, 0);
859 /* register TLBs into the opposite registry view, too */
860 if(opposite
== KEY_WOW64_32KEY
||
861 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
862 TLB_register_interface(attr
, name
, tattr
, opposite
);
865 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
868 ITypeInfo_Release(tinfo
);
875 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
880 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
882 WCHAR subKeyName
[50];
885 /* the path to the type */
886 get_interface_key( guid
, subKeyName
);
888 /* Delete its bits */
889 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
892 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
893 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
894 RegDeleteKeyW(subKey
, TypeLibW
);
896 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
899 /******************************************************************************
900 * UnRegisterTypeLib [OLEAUT32.186]
901 * Removes information about a type library from the System Registry
908 HRESULT WINAPI
UnRegisterTypeLib(
909 REFGUID libid
, /* [in] Guid of the library */
910 WORD wVerMajor
, /* [in] major version */
911 WORD wVerMinor
, /* [in] minor version */
912 LCID lcid
, /* [in] locale id */
915 BSTR tlibPath
= NULL
;
918 WCHAR subKeyName
[50];
921 BOOL deleteOtherStuff
;
923 TYPEATTR
* typeAttr
= NULL
;
925 ITypeInfo
* typeInfo
= NULL
;
926 ITypeLib
* typeLib
= NULL
;
929 TRACE("(IID: %s)\n",debugstr_guid(libid
));
931 /* Create the path to the key */
932 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
934 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
936 TRACE("Unsupported syskind %i\n", syskind
);
937 result
= E_INVALIDARG
;
941 /* get the path to the typelib on disk */
942 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
943 result
= E_INVALIDARG
;
947 /* Try and open the key to the type library. */
948 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
949 result
= E_INVALIDARG
;
953 /* Try and load the type library */
954 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
955 result
= TYPE_E_INVALIDSTATE
;
959 /* remove any types registered with this typelib */
960 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
961 for (i
=0; i
<numTypes
; i
++) {
962 /* get the kind of type */
963 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
967 /* skip non-interfaces, and get type info for the type */
968 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
971 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
974 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
978 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
979 kind
== TKIND_DISPATCH
)
982 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
984 TLB_unregister_interface(&typeAttr
->guid
, 0);
986 /* unregister TLBs into the opposite registry view, too */
987 if(opposite
== KEY_WOW64_32KEY
||
988 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
989 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
994 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
996 if (typeInfo
) ITypeInfo_Release(typeInfo
);
1000 /* Now, delete the type library path subkey */
1001 get_lcid_subkey( lcid
, syskind
, subKeyName
);
1002 RegDeleteKeyW(key
, subKeyName
);
1003 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
1004 RegDeleteKeyW(key
, subKeyName
);
1006 /* check if there is anything besides the FLAGS/HELPDIR keys.
1007 If there is, we don't delete them */
1008 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
1009 deleteOtherStuff
= TRUE
;
1011 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
1012 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
1014 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
1015 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
1016 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
1017 deleteOtherStuff
= FALSE
;
1021 /* only delete the other parts of the key if we're absolutely sure */
1022 if (deleteOtherStuff
) {
1023 RegDeleteKeyW(key
, FLAGSW
);
1024 RegDeleteKeyW(key
, HELPDIRW
);
1028 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1029 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
1030 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1034 SysFreeString(tlibPath
);
1035 if (typeLib
) ITypeLib_Release(typeLib
);
1036 if (key
) RegCloseKey(key
);
1040 /******************************************************************************
1041 * RegisterTypeLibForUser [OLEAUT32.442]
1042 * Adds information about a type library to the user registry
1044 * Docs: ITypeLib FAR * ptlib
1045 * Docs: OLECHAR FAR* szFullPath
1046 * Docs: OLECHAR FAR* szHelpDir
1052 HRESULT WINAPI
RegisterTypeLibForUser(
1053 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1054 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1055 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1058 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1059 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1060 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1063 /******************************************************************************
1064 * UnRegisterTypeLibForUser [OLEAUT32.443]
1065 * Removes information about a type library from the user registry
1071 HRESULT WINAPI
UnRegisterTypeLibForUser(
1072 REFGUID libid
, /* [in] GUID of the library */
1073 WORD wVerMajor
, /* [in] major version */
1074 WORD wVerMinor
, /* [in] minor version */
1075 LCID lcid
, /* [in] locale id */
1078 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1079 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1080 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1083 /*======================= ITypeLib implementation =======================*/
1085 typedef struct tagTLBGuid
{
1092 typedef struct tagTLBCustData
1099 /* data structure for import typelibs */
1100 typedef struct tagTLBImpLib
1102 int offset
; /* offset in the file (MSFT)
1103 offset in nametable (SLTG)
1104 just used to identify library while reading
1106 TLBGuid
*guid
; /* libid */
1107 BSTR name
; /* name */
1109 LCID lcid
; /* lcid of imported typelib */
1111 WORD wVersionMajor
; /* major version number */
1112 WORD wVersionMinor
; /* minor version number */
1114 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1115 NULL if not yet loaded */
1119 typedef struct tagTLBString
{
1125 /* internal ITypeLib data */
1126 typedef struct tagITypeLibImpl
1128 ITypeLib2 ITypeLib2_iface
;
1129 ITypeComp ITypeComp_iface
;
1130 ICreateTypeLib2 ICreateTypeLib2_iface
;
1141 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1142 * exported to the application as a UNICODE string.
1144 struct list string_list
;
1145 struct list name_list
;
1146 struct list guid_list
;
1148 const TLBString
*Name
;
1149 const TLBString
*DocString
;
1150 const TLBString
*HelpFile
;
1151 const TLBString
*HelpStringDll
;
1152 DWORD dwHelpContext
;
1153 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1154 struct tagITypeInfoImpl
**typeinfos
;
1155 struct list custdata_list
;
1156 struct list implib_list
;
1157 int ctTypeDesc
; /* number of items in type desc array */
1158 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1159 library. Only used while reading MSFT
1161 struct list ref_list
; /* list of ref types in this typelib */
1162 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1165 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1171 static const ITypeLib2Vtbl tlbvt
;
1172 static const ITypeCompVtbl tlbtcvt
;
1173 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1175 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1177 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1180 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1182 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1185 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1187 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1190 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1192 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1195 /* ITypeLib methods */
1196 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1197 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1199 /*======================= ITypeInfo implementation =======================*/
1201 /* data for referenced types */
1202 typedef struct tagTLBRefType
1204 INT index
; /* Type index for internal ref or for external ref
1205 it the format is SLTG. -2 indicates to
1209 TLBGuid
*guid
; /* guid of the referenced type */
1210 /* if index == TLB_REF_USE_GUID */
1212 HREFTYPE reference
; /* The href of this ref */
1213 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1214 TLB_REF_INTERNAL for internal refs
1215 TLB_REF_NOT_FOUND for broken refs */
1220 #define TLB_REF_USE_GUID -2
1222 #define TLB_REF_INTERNAL (void*)-2
1223 #define TLB_REF_NOT_FOUND (void*)-1
1225 /* internal Parameter data */
1226 typedef struct tagTLBParDesc
1228 const TLBString
*Name
;
1229 struct list custdata_list
;
1232 /* internal Function data */
1233 typedef struct tagTLBFuncDesc
1235 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1236 const TLBString
*Name
; /* the name of this function */
1237 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1239 int HelpStringContext
;
1240 const TLBString
*HelpString
;
1241 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1242 struct list custdata_list
;
1245 /* internal Variable data */
1246 typedef struct tagTLBVarDesc
1248 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1249 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1250 const TLBString
*Name
; /* the name of this variable */
1252 int HelpStringContext
;
1253 const TLBString
*HelpString
;
1254 struct list custdata_list
;
1257 /* internal implemented interface data */
1258 typedef struct tagTLBImplType
1260 HREFTYPE hRef
; /* hRef of interface */
1261 int implflags
; /* IMPLFLAG_*s */
1262 struct list custdata_list
;
1265 /* internal TypeInfo data */
1266 typedef struct tagITypeInfoImpl
1268 ITypeInfo2 ITypeInfo2_iface
;
1269 ITypeComp ITypeComp_iface
;
1270 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1272 BOOL not_attached_to_typelib
;
1277 MEMBERID memidConstructor
;
1278 MEMBERID memidDestructor
;
1279 LPOLESTR lpstrSchema
;
1280 ULONG cbSizeInstance
;
1290 TYPEDESC
*tdescAlias
;
1291 IDLDESC idldescType
;
1293 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1294 int index
; /* index in this typelib; */
1295 HREFTYPE hreftype
; /* hreftype for app object binding */
1296 /* type libs seem to store the doc strings in ascii
1297 * so why should we do it in unicode?
1299 const TLBString
*Name
;
1300 const TLBString
*DocString
;
1301 const TLBString
*DllName
;
1302 const TLBString
*Schema
;
1303 DWORD dwHelpContext
;
1304 DWORD dwHelpStringContext
;
1307 TLBFuncDesc
*funcdescs
;
1310 TLBVarDesc
*vardescs
;
1312 /* Implemented Interfaces */
1313 TLBImplType
*impltypes
;
1315 struct list
*pcustdata_list
;
1316 struct list custdata_list
;
1319 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1321 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1324 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1326 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1329 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1331 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1334 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1336 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1339 static const ITypeInfo2Vtbl tinfvt
;
1340 static const ITypeCompVtbl tcompvt
;
1341 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1343 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1344 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1346 typedef struct tagTLBContext
1348 unsigned int oStart
; /* start of TLB in file */
1349 unsigned int pos
; /* current pos */
1350 unsigned int length
; /* total length */
1351 void *mapping
; /* memory mapping */
1352 MSFT_SegDir
* pTblDir
;
1353 ITypeLibImpl
* pLibInfo
;
1357 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1359 return str
!= NULL
? str
->str
: NULL
;
1362 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1366 return memcmp(left
, str
->str
, len
);
1369 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1371 return guid
!= NULL
? &guid
->guid
: NULL
;
1374 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1376 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1379 static int get_ptr_size(SYSKIND syskind
)
1389 WARN("Unhandled syskind: 0x%x\n", syskind
);
1396 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1397 if (pTD
->vt
& VT_RESERVED
)
1398 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1399 if (pTD
->vt
& VT_BYREF
)
1400 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1401 if (pTD
->vt
& VT_ARRAY
)
1402 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1403 if (pTD
->vt
& VT_VECTOR
)
1404 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1405 switch(pTD
->vt
& VT_TYPEMASK
) {
1406 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1407 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1408 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1409 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1410 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1411 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1412 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1413 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1414 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1415 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1416 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1417 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1418 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1419 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1420 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1421 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1422 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1423 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1424 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1425 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1426 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1427 pTD
->u
.hreftype
); break;
1428 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1429 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1430 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1431 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1433 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1434 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1436 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1437 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1438 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1441 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1445 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1447 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1448 dump_TypeDesc(&edesc
->tdesc
,buf
);
1449 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1450 MESSAGE("\t\tu.paramdesc.wParamFlags");
1451 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1452 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1453 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1454 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1455 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1456 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1457 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1458 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1459 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1461 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1463 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1464 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1465 MESSAGE("Param %d:\n",i
);
1466 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1468 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1469 switch (funcdesc
->funckind
) {
1470 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1471 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1472 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1473 case FUNC_STATIC
: MESSAGE("static");break;
1474 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1475 default: MESSAGE("unknown");break;
1477 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1478 switch (funcdesc
->invkind
) {
1479 case INVOKE_FUNC
: MESSAGE("func");break;
1480 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1481 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1482 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1484 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1485 switch (funcdesc
->callconv
) {
1486 case CC_CDECL
: MESSAGE("cdecl");break;
1487 case CC_PASCAL
: MESSAGE("pascal");break;
1488 case CC_STDCALL
: MESSAGE("stdcall");break;
1489 case CC_SYSCALL
: MESSAGE("syscall");break;
1492 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1493 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1494 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1496 MESSAGE("\telemdescFunc (return value type):\n");
1497 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1500 static const char * const typekind_desc
[] =
1513 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1516 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1517 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1518 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1521 dump_FUNCDESC(&(pfd
->funcdesc
));
1523 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1524 if(pfd
->Entry
== NULL
)
1525 MESSAGE("\tentry: (null)\n");
1526 else if(pfd
->Entry
== (void*)-1)
1527 MESSAGE("\tentry: invalid\n");
1528 else if(IS_INTRESOURCE(pfd
->Entry
))
1529 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1531 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1533 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1537 dump_TLBFuncDescOne(pfd
);
1542 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1546 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1552 static void dump_TLBImpLib(const TLBImpLib
*import
)
1554 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1555 debugstr_w(import
->name
));
1556 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1557 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1560 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1564 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1566 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1567 if(ref
->index
== -1)
1568 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1570 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1572 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1574 TRACE_(typelib
)("in lib\n");
1575 dump_TLBImpLib(ref
->pImpTLInfo
);
1580 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1585 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1586 impl
->hRef
, impl
->implflags
);
1592 static void dump_DispParms(const DISPPARAMS
* pdp
)
1596 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1598 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1600 TRACE("named args:\n");
1601 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1602 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1605 if (pdp
->cArgs
&& pdp
->rgvarg
)
1608 for (index
= 0; index
< pdp
->cArgs
; index
++)
1609 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1613 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1615 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1616 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1617 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1618 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1619 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1620 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1621 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1622 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1624 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1625 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1626 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1629 static void dump_VARDESC(const VARDESC
*v
)
1631 MESSAGE("memid %d\n",v
->memid
);
1632 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1633 MESSAGE("oInst %d\n",v
->u
.oInst
);
1634 dump_ELEMDESC(&(v
->elemdescVar
));
1635 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1636 MESSAGE("varkind %d\n",v
->varkind
);
1639 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1641 /* VT_LPWSTR is largest type that, may appear in type description */
1642 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1643 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1644 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1645 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1646 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1647 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1648 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1649 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1652 static void TLB_abort(void)
1657 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1659 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1660 if (!ret
) ERR("cannot allocate memory\n");
1664 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1666 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1667 if (!ret
) ERR("cannot allocate memory\n");
1671 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1673 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1676 void heap_free(void *ptr
)
1678 HeapFree(GetProcessHeap(), 0, ptr
);
1681 /* returns the size required for a deep copy of a typedesc into a
1683 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1687 if (alloc_initial_space
)
1688 size
+= sizeof(TYPEDESC
);
1694 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1697 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1698 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1704 /* deep copy a typedesc into a flat buffer */
1705 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1710 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1719 dest
->u
.lptdesc
= buffer
;
1720 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1723 dest
->u
.lpadesc
= buffer
;
1724 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1725 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1726 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1732 /* free custom data allocated by MSFT_CustData */
1733 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1735 TLBCustData
*cd
, *cdn
;
1736 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1738 list_remove(&cd
->entry
);
1739 VariantClear(&cd
->data
);
1744 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1749 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1750 ret
= SysAllocStringLen(NULL
, len
- 1);
1751 if (!ret
) return ret
;
1752 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1756 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1757 UINT n
, MEMBERID memid
)
1760 if(funcdescs
->funcdesc
.memid
== memid
)
1768 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1769 UINT n
, MEMBERID memid
)
1772 if(vardescs
->vardesc
.memid
== memid
)
1780 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1781 UINT n
, const OLECHAR
*name
)
1784 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1792 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1794 TLBCustData
*cust_data
;
1795 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1796 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1801 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1802 UINT n
, const OLECHAR
*name
)
1805 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1813 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1815 list_init(&var_desc
->custdata_list
);
1818 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1822 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1827 TLBVarDesc_Constructor(&ret
[n
-1]);
1834 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1838 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1843 list_init(&ret
[n
-1].custdata_list
);
1850 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1852 list_init(&func_desc
->custdata_list
);
1855 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1859 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1864 TLBFuncDesc_Constructor(&ret
[n
-1]);
1871 static void TLBImplType_Constructor(TLBImplType
*impl
)
1873 list_init(&impl
->custdata_list
);
1876 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1880 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1885 TLBImplType_Constructor(&ret
[n
-1]);
1892 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1893 const GUID
*new_guid
, HREFTYPE hreftype
)
1897 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1898 if (IsEqualGUID(&guid
->guid
, new_guid
))
1902 guid
= heap_alloc(sizeof(TLBGuid
));
1906 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1907 guid
->hreftype
= hreftype
;
1909 list_add_tail(guid_list
, &guid
->entry
);
1914 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1916 TLBCustData
*cust_data
;
1928 return DISP_E_BADVARTYPE
;
1931 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1934 cust_data
= heap_alloc(sizeof(TLBCustData
));
1936 return E_OUTOFMEMORY
;
1938 cust_data
->guid
= tlbguid
;
1939 VariantInit(&cust_data
->data
);
1941 list_add_tail(custdata_list
, &cust_data
->entry
);
1943 VariantClear(&cust_data
->data
);
1945 return VariantCopy(&cust_data
->data
, var
);
1948 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1955 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1956 if (strcmpW(str
->str
, new_str
) == 0)
1960 str
= heap_alloc(sizeof(TLBString
));
1964 str
->str
= SysAllocString(new_str
);
1970 list_add_tail(string_list
, &str
->entry
);
1975 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1976 ULONG
*size
, WORD
*align
)
1982 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1986 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1988 ITypeInfo_Release(other
);
1993 *size
= attr
->cbSizeInstance
;
1995 *align
= attr
->cbAlignment
;
1997 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1998 ITypeInfo_Release(other
);
2003 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
2004 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
2006 ULONG i
, sub
, ptr_size
;
2009 ptr_size
= get_ptr_size(sys
);
2048 *size
= sizeof(DATE
);
2051 *size
= sizeof(VARIANT
);
2053 if(sys
== SYS_WIN32
)
2054 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2058 *size
= sizeof(DECIMAL
);
2065 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2066 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2067 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2072 case VT_USERDEFINED
:
2073 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2075 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2089 /**********************************************************************
2091 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2094 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2096 if (where
!= DO_NOT_SEEK
)
2098 where
+= pcx
->oStart
;
2099 if (where
> pcx
->length
)
2102 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2110 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2112 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2113 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2115 MSFT_Seek(pcx
, where
);
2116 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2117 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2122 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2127 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2128 FromLEDWords(buffer
, ret
);
2133 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2138 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2139 FromLEWords(buffer
, ret
);
2144 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2147 MSFT_GuidEntry entry
;
2150 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2152 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2155 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2157 guid
= heap_alloc(sizeof(TLBGuid
));
2159 guid
->offset
= offs
;
2160 guid
->guid
= entry
.guid
;
2161 guid
->hreftype
= entry
.hreftype
;
2163 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2165 offs
+= sizeof(MSFT_GuidEntry
);
2169 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2173 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2174 if(ret
->offset
== offset
){
2175 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2183 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2185 MSFT_NameIntro niName
;
2189 ERR_(typelib
)("bad offset %d\n", offset
);
2193 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2194 pcx
->pTblDir
->pNametab
.offset
+offset
);
2196 return niName
.hreftype
;
2199 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2202 MSFT_NameIntro intro
;
2204 int offs
= 0, lengthInChars
;
2206 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2210 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2213 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2214 intro
.namelen
&= 0xFF;
2215 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2217 len_piece
= (len_piece
+ 4) & ~0x3;
2221 string
= heap_alloc(len_piece
+ 1);
2222 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2223 string
[intro
.namelen
] = '\0';
2225 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2226 string
, -1, NULL
, 0);
2227 if (!lengthInChars
) {
2229 return E_UNEXPECTED
;
2232 tlbstr
= heap_alloc(sizeof(TLBString
));
2234 tlbstr
->offset
= offs
;
2235 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2236 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2240 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2246 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2250 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2251 if (tlbstr
->offset
== offset
) {
2252 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2260 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2264 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2265 if (tlbstr
->offset
== offset
) {
2266 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2275 * read a value and fill a VARIANT structure
2277 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2281 TRACE_(typelib
)("\n");
2283 if(offset
<0) { /* data are packed in here */
2284 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2285 V_I4(pVar
) = offset
& 0x3ffffff;
2288 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2289 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2290 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2291 switch (V_VT(pVar
)){
2292 case VT_EMPTY
: /* FIXME: is this right? */
2293 case VT_NULL
: /* FIXME: is this right? */
2294 case VT_I2
: /* this should not happen */
2305 case VT_VOID
: /* FIXME: is this right? */
2313 case VT_DECIMAL
: /* FIXME: is this right? */
2316 /* pointer types with known behaviour */
2319 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2321 V_BSTR(pVar
) = NULL
;
2323 ptr
= heap_alloc_zero(size
);
2324 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2325 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2326 /* FIXME: do we need a AtoW conversion here? */
2327 V_UNION(pVar
, bstrVal
[size
])='\0';
2328 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2333 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2340 case VT_USERDEFINED
:
2346 case VT_STREAMED_OBJECT
:
2347 case VT_STORED_OBJECT
:
2348 case VT_BLOB_OBJECT
:
2353 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2357 if(size
>0) /* (big|small) endian correct? */
2358 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2362 * create a linked list with custom data
2364 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2370 TRACE_(typelib
)("\n");
2372 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2376 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2377 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2378 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2379 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2380 list_add_head(custdata_list
, &pNew
->entry
);
2381 offset
= entry
.next
;
2386 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2389 pTd
->vt
=type
& VT_TYPEMASK
;
2391 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2393 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2396 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2398 return (invkind
== INVOKE_PROPERTYGET
||
2399 invkind
== INVOKE_PROPERTYPUT
||
2400 invkind
== INVOKE_PROPERTYPUTREF
);
2404 MSFT_DoFuncs(TLBContext
* pcx
,
2409 TLBFuncDesc
** pptfd
)
2412 * member information is stored in a data structure at offset
2413 * indicated by the memoffset field of the typeinfo structure
2414 * There are several distinctive parts.
2415 * The first part starts with a field that holds the total length
2416 * of this (first) part excluding this field. Then follow the records,
2417 * for each member there is one record.
2419 * The first entry is always the length of the record (including this
2421 * The rest of the record depends on the type of the member. If there is
2422 * a field indicating the member type (function, variable, interface, etc)
2423 * I have not found it yet. At this time we depend on the information
2424 * in the type info and the usual order how things are stored.
2426 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2429 * Third is an equal sized array with file offsets to the name entry
2432 * The fourth and last (?) part is an array with offsets to the records
2433 * in the first part of this file segment.
2436 int infolen
, nameoffset
, reclength
, i
;
2437 int recoffset
= offset
+ sizeof(INT
);
2439 char *recbuf
= heap_alloc(0xffff);
2440 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2441 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2443 TRACE_(typelib
)("\n");
2445 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2447 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2449 for ( i
= 0; i
< cFuncs
; i
++ )
2453 /* name, eventually add to a hash table */
2454 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2455 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2457 /* read the function information record */
2458 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2460 reclength
&= 0xffff;
2462 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2464 /* size without argument data */
2465 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2466 if (pFuncRec
->FKCCIC
& 0x1000)
2467 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2469 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2470 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2472 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2473 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2475 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2477 if (pFuncRec
->FKCCIC
& 0x2000 )
2479 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2480 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2481 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2484 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2487 ptfd
->Entry
= (TLBString
*)-1;
2489 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2490 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2492 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2493 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2495 /* fill the FuncDesc Structure */
2496 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2497 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2499 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2500 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2501 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2502 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2503 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2504 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2505 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2507 /* nameoffset is sometimes -1 on the second half of a propget/propput
2508 * pair of functions */
2509 if ((nameoffset
== -1) && (i
> 0) &&
2510 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2511 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2512 ptfd
->Name
= ptfd_prev
->Name
;
2514 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2518 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2520 /* do the parameters/arguments */
2521 if(pFuncRec
->nrargs
)
2524 MSFT_ParameterInfo paraminfo
;
2526 ptfd
->funcdesc
.lprgelemdescParam
=
2527 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2529 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2531 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2532 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2534 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2536 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2542 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2545 if (paraminfo
.oName
!= -1)
2546 ptfd
->pParamDesc
[j
].Name
=
2547 MSFT_ReadName( pcx
, paraminfo
.oName
);
2548 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2551 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2552 (pFuncRec
->FKCCIC
& 0x1000) )
2554 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2556 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2558 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2560 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2561 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2563 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2567 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2570 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2571 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2572 pFuncRec
->FKCCIC
& 0x80 )
2575 pFuncRec
->oArgCustData
[j
],
2576 &ptfd
->pParamDesc
[j
].custdata_list
);
2579 /* SEEK value = jump to offset,
2580 * from there jump to the end of record,
2581 * go back by (j-1) arguments
2583 MSFT_ReadLEDWords( ¶minfo
,
2584 sizeof(MSFT_ParameterInfo
), pcx
,
2585 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2586 * sizeof(MSFT_ParameterInfo
)));
2590 /* scode is not used: archaic win16 stuff FIXME: right? */
2591 ptfd
->funcdesc
.cScodes
= 0 ;
2592 ptfd
->funcdesc
.lprgscode
= NULL
;
2596 recoffset
+= reclength
;
2601 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2602 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2604 int infolen
, nameoffset
, reclength
;
2606 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2611 TRACE_(typelib
)("\n");
2613 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2614 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2615 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2616 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2617 recoffset
+= offset
+sizeof(INT
);
2618 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2619 /* name, eventually add to a hash table */
2620 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2621 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2622 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2623 /* read the variable information record */
2624 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2626 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2629 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2630 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2632 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2633 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2635 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2636 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2638 /* fill the VarDesc Structure */
2639 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2640 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2641 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2642 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2643 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2644 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2645 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2646 if(pVarRec
->VarKind
== VAR_CONST
){
2647 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2648 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2649 pVarRec
->OffsValue
, pcx
);
2651 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2652 recoffset
+= reclength
;
2656 /* process Implemented Interfaces of a com class */
2657 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2661 MSFT_RefRecord refrec
;
2664 TRACE_(typelib
)("\n");
2666 pTI
->impltypes
= TLBImplType_Alloc(count
);
2667 pImpl
= pTI
->impltypes
;
2668 for(i
=0;i
<count
;i
++){
2669 if(offset
<0) break; /* paranoia */
2670 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2671 pImpl
->hRef
= refrec
.reftype
;
2672 pImpl
->implflags
=refrec
.flags
;
2673 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2674 offset
=refrec
.onext
;
2680 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2681 * and some structures, and fix the alignment */
2682 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2684 if(info
->typekind
== TKIND_ALIAS
){
2685 switch(info
->tdescAlias
->vt
){
2693 info
->cbSizeInstance
= sizeof(void*);
2694 info
->cbAlignment
= sizeof(void*);
2697 case VT_USERDEFINED
:
2698 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2701 info
->cbSizeInstance
= sizeof(VARIANT
);
2702 info
->cbAlignment
= 8;
2704 if(info
->cbSizeInstance
< sizeof(void*))
2705 info
->cbAlignment
= info
->cbSizeInstance
;
2707 info
->cbAlignment
= sizeof(void*);
2710 }else if(info
->typekind
== TKIND_INTERFACE
||
2711 info
->typekind
== TKIND_DISPATCH
||
2712 info
->typekind
== TKIND_COCLASS
){
2713 info
->cbSizeInstance
= sizeof(void*);
2714 info
->cbAlignment
= sizeof(void*);
2720 * process a typeinfo record
2722 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2725 ITypeLibImpl
* pLibInfo
)
2727 MSFT_TypeInfoBase tiBase
;
2728 ITypeInfoImpl
*ptiRet
;
2730 TRACE_(typelib
)("count=%u\n", count
);
2732 ptiRet
= ITypeInfoImpl_Constructor();
2733 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2734 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2736 /* this is where we are coming from */
2737 ptiRet
->pTypeLib
= pLibInfo
;
2738 ptiRet
->index
=count
;
2740 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2741 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2742 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2743 ptiRet
->cbSizeInstance
=tiBase
.size
;
2744 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2745 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2746 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2747 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2748 ptiRet
->wTypeFlags
=tiBase
.flags
;
2749 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2750 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2751 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2752 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2753 if(ptiRet
->typekind
== TKIND_ALIAS
){
2755 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2756 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2757 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2761 /* IDLDESC idldescType; *//* never saw this one != zero */
2763 /* name, eventually add to a hash table */
2764 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2765 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2766 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2768 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2769 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2770 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2772 if (ptiRet
->typekind
== TKIND_MODULE
)
2773 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2775 /* note: InfoType's Help file and HelpStringDll come from the containing
2776 * library. Further HelpString and Docstring appear to be the same thing :(
2779 if(ptiRet
->cFuncs
>0 )
2780 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2782 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2784 if(ptiRet
->cVars
>0 )
2785 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2787 tiBase
.memoffset
, &ptiRet
->vardescs
);
2788 if(ptiRet
->cImplTypes
>0 ) {
2789 switch(ptiRet
->typekind
)
2792 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2795 case TKIND_DISPATCH
:
2796 /* This is not -1 when the interface is a non-base dual interface or
2797 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2798 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2802 if (tiBase
.datatype1
!= -1)
2804 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2805 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2809 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2810 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2814 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2816 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2817 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2818 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2819 typekind_desc
[ptiRet
->typekind
]);
2820 if (TRACE_ON(typelib
))
2821 dump_TypeInfo(ptiRet
);
2826 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2829 INT16 len_str
, len_piece
;
2830 int offs
= 0, lengthInChars
;
2832 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2836 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2839 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2840 len_piece
= len_str
+ sizeof(INT16
);
2842 len_piece
= (len_piece
+ 4) & ~0x3;
2846 string
= heap_alloc(len_piece
+ 1);
2847 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2848 string
[len_str
] = '\0';
2850 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2851 string
, -1, NULL
, 0);
2852 if (!lengthInChars
) {
2854 return E_UNEXPECTED
;
2857 tlbstr
= heap_alloc(sizeof(TLBString
));
2859 tlbstr
->offset
= offs
;
2860 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2861 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2865 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2871 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2876 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2877 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2878 MSFT_ImpInfo impinfo
;
2881 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2883 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2884 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2886 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2887 if(pImpLib
->offset
==impinfo
.oImpFile
)
2890 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2891 ref
->reference
= offs
;
2892 ref
->pImpTLInfo
= pImpLib
;
2893 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2894 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2895 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2896 ref
->index
= TLB_REF_USE_GUID
;
2898 ref
->index
= impinfo
.oGuid
;
2900 ERR("Cannot find a reference\n");
2901 ref
->reference
= -1;
2902 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2905 offs
+= sizeof(impinfo
);
2911 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2912 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2913 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2916 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2917 static CRITICAL_SECTION cache_section
;
2918 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2920 0, 0, &cache_section
,
2921 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2922 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2924 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2927 typedef struct TLB_PEFile
2929 IUnknown IUnknown_iface
;
2932 HRSRC typelib_resource
;
2933 HGLOBAL typelib_global
;
2934 LPVOID typelib_base
;
2937 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2939 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2942 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2944 if (IsEqualIID(riid
, &IID_IUnknown
))
2947 IUnknown_AddRef(iface
);
2951 return E_NOINTERFACE
;
2954 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2956 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2957 return InterlockedIncrement(&This
->refs
);
2960 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2962 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2963 ULONG refs
= InterlockedDecrement(&This
->refs
);
2966 if (This
->typelib_global
)
2967 FreeResource(This
->typelib_global
);
2969 FreeLibrary(This
->dll
);
2975 static const IUnknownVtbl TLB_PEFile_Vtable
=
2977 TLB_PEFile_QueryInterface
,
2982 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2985 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2987 This
= heap_alloc(sizeof(TLB_PEFile
));
2989 return E_OUTOFMEMORY
;
2991 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2994 This
->typelib_resource
= NULL
;
2995 This
->typelib_global
= NULL
;
2996 This
->typelib_base
= NULL
;
2998 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2999 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
3003 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
3004 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
3005 if (This
->typelib_resource
)
3007 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
3008 if (This
->typelib_global
)
3010 This
->typelib_base
= LockResource(This
->typelib_global
);
3012 if (This
->typelib_base
)
3014 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
3015 *ppBase
= This
->typelib_base
;
3016 *ppFile
= &This
->IUnknown_iface
;
3022 TRACE("No TYPELIB resource found\n");
3026 TLB_PEFile_Release(&This
->IUnknown_iface
);
3030 typedef struct TLB_NEFile
3032 IUnknown IUnknown_iface
;
3034 LPVOID typelib_base
;
3037 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
3039 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
3042 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3044 if (IsEqualIID(riid
, &IID_IUnknown
))
3047 IUnknown_AddRef(iface
);
3051 return E_NOINTERFACE
;
3054 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3056 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3057 return InterlockedIncrement(&This
->refs
);
3060 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3062 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3063 ULONG refs
= InterlockedDecrement(&This
->refs
);
3066 heap_free(This
->typelib_base
);
3072 static const IUnknownVtbl TLB_NEFile_Vtable
=
3074 TLB_NEFile_QueryInterface
,
3079 /***********************************************************************
3080 * read_xx_header [internal]
3082 static int read_xx_header( HFILE lzfd
)
3084 IMAGE_DOS_HEADER mzh
;
3087 LZSeek( lzfd
, 0, SEEK_SET
);
3088 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3090 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3093 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3094 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3097 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3099 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3100 return IMAGE_OS2_SIGNATURE
;
3101 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3102 return IMAGE_NT_SIGNATURE
;
3105 WARN("Can't handle %s files.\n", magic
);
3110 /***********************************************************************
3111 * find_ne_resource [internal]
3113 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3114 DWORD
*resLen
, DWORD
*resOff
)
3116 IMAGE_OS2_HEADER nehd
;
3117 NE_TYPEINFO
*typeInfo
;
3118 NE_NAMEINFO
*nameInfo
;
3124 /* Read in NE header */
3125 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3126 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3128 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3131 TRACE("No resources in NE dll\n" );
3135 /* Read in resource table */
3136 resTab
= heap_alloc( resTabSize
);
3137 if ( !resTab
) return FALSE
;
3139 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3140 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3142 heap_free( resTab
);
3147 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3149 if (!IS_INTRESOURCE(typeid)) /* named type */
3151 BYTE len
= strlen( typeid );
3152 while (typeInfo
->type_id
)
3154 if (!(typeInfo
->type_id
& 0x8000))
3156 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3157 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
3159 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3160 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3163 else /* numeric type id */
3165 WORD id
= LOWORD(typeid) | 0x8000;
3166 while (typeInfo
->type_id
)
3168 if (typeInfo
->type_id
== id
) goto found_type
;
3169 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3170 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3173 TRACE("No typeid entry found for %p\n", typeid );
3174 heap_free( resTab
);
3178 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3180 if (!IS_INTRESOURCE(resid
)) /* named resource */
3182 BYTE len
= strlen( resid
);
3183 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3185 BYTE
*p
= resTab
+ nameInfo
->id
;
3186 if (nameInfo
->id
& 0x8000) continue;
3187 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
3190 else /* numeric resource id */
3192 WORD id
= LOWORD(resid
) | 0x8000;
3193 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3194 if (nameInfo
->id
== id
) goto found_name
;
3196 TRACE("No resid entry found for %p\n", typeid );
3197 heap_free( resTab
);
3201 /* Return resource data */
3202 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3203 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3205 heap_free( resTab
);
3209 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3213 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3216 This
= heap_alloc(sizeof(TLB_NEFile
));
3217 if (!This
) return E_OUTOFMEMORY
;
3219 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3221 This
->typelib_base
= NULL
;
3223 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3224 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3226 DWORD reslen
, offset
;
3227 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3229 This
->typelib_base
= heap_alloc(reslen
);
3230 if( !This
->typelib_base
)
3234 LZSeek( lzfd
, offset
, SEEK_SET
);
3235 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3237 *ppBase
= This
->typelib_base
;
3238 *pdwTLBLength
= reslen
;
3239 *ppFile
= &This
->IUnknown_iface
;
3245 if( lzfd
>= 0) LZClose( lzfd
);
3246 TLB_NEFile_Release(&This
->IUnknown_iface
);
3250 typedef struct TLB_Mapping
3252 IUnknown IUnknown_iface
;
3256 LPVOID typelib_base
;
3259 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3261 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3264 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3266 if (IsEqualIID(riid
, &IID_IUnknown
))
3269 IUnknown_AddRef(iface
);
3273 return E_NOINTERFACE
;
3276 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3278 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3279 return InterlockedIncrement(&This
->refs
);
3282 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3284 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3285 ULONG refs
= InterlockedDecrement(&This
->refs
);
3288 if (This
->typelib_base
)
3289 UnmapViewOfFile(This
->typelib_base
);
3291 CloseHandle(This
->mapping
);
3292 if (This
->file
!= INVALID_HANDLE_VALUE
)
3293 CloseHandle(This
->file
);
3299 static const IUnknownVtbl TLB_Mapping_Vtable
=
3301 TLB_Mapping_QueryInterface
,
3306 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3310 This
= heap_alloc(sizeof(TLB_Mapping
));
3312 return E_OUTOFMEMORY
;
3314 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3316 This
->file
= INVALID_HANDLE_VALUE
;
3317 This
->mapping
= NULL
;
3318 This
->typelib_base
= NULL
;
3320 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3321 if (INVALID_HANDLE_VALUE
!= This
->file
)
3323 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3326 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3327 if(This
->typelib_base
)
3329 /* retrieve file size */
3330 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3331 *ppBase
= This
->typelib_base
;
3332 *ppFile
= &This
->IUnknown_iface
;
3338 IUnknown_Release(&This
->IUnknown_iface
);
3339 return TYPE_E_CANTLOADLIBRARY
;
3342 /****************************************************************************
3345 * find the type of the typelib file and map the typelib resource into
3349 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3350 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3352 ITypeLibImpl
*entry
;
3355 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3356 LPVOID pBase
= NULL
;
3357 DWORD dwTLBLength
= 0;
3358 IUnknown
*pFile
= NULL
;
3363 index_str
= strrchrW(pszFileName
, '\\');
3364 if(index_str
&& *++index_str
!= '\0')
3367 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
3368 if(*end_ptr
== '\0')
3370 int str_len
= index_str
- pszFileName
- 1;
3372 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3373 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3378 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3380 if(strchrW(file
, '\\'))
3382 lstrcpyW(pszPath
, file
);
3386 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3387 pszPath
[len
] = '\\';
3388 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
3392 if(file
!= pszFileName
) heap_free(file
);
3394 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3395 if(h
!= INVALID_HANDLE_VALUE
){
3396 FILE_NAME_INFORMATION size_info
;
3399 /* GetFileInformationByHandleEx returns the path of the file without
3400 * WOW64 redirection */
3401 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3402 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3403 FILE_NAME_INFORMATION
*info
;
3404 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3406 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3408 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3410 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3411 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3414 HeapFree(GetProcessHeap(), 0, info
);
3420 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3422 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3423 EnterCriticalSection(&cache_section
);
3424 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3426 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
3428 TRACE("cache hit\n");
3429 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3430 ITypeLib2_AddRef(*ppTypeLib
);
3431 LeaveCriticalSection(&cache_section
);
3435 LeaveCriticalSection(&cache_section
);
3437 /* now actually load and parse the typelib */
3439 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3440 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3441 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3442 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3443 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3446 if (dwTLBLength
>= 4)
3448 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3449 if (dwSignature
== MSFT_SIGNATURE
)
3450 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3451 else if (dwSignature
== SLTG_SIGNATURE
)
3452 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3455 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3456 ret
= TYPE_E_CANTLOADLIBRARY
;
3460 ret
= TYPE_E_CANTLOADLIBRARY
;
3461 IUnknown_Release(pFile
);
3465 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3467 TRACE("adding to cache\n");
3468 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
3469 lstrcpyW(impl
->path
, pszPath
);
3470 /* We should really canonicalise the path here. */
3471 impl
->index
= index
;
3473 /* FIXME: check if it has added already in the meantime */
3474 EnterCriticalSection(&cache_section
);
3475 list_add_head(&tlb_cache
, &impl
->entry
);
3476 LeaveCriticalSection(&cache_section
);
3482 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3484 ret
= TYPE_E_CANTLOADLIBRARY
;
3491 /*================== ITypeLib(2) Methods ===================================*/
3493 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3495 ITypeLibImpl
* pTypeLibImpl
;
3497 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3498 if (!pTypeLibImpl
) return NULL
;
3500 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3501 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3502 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3503 pTypeLibImpl
->ref
= 1;
3505 list_init(&pTypeLibImpl
->implib_list
);
3506 list_init(&pTypeLibImpl
->custdata_list
);
3507 list_init(&pTypeLibImpl
->name_list
);