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
);
584 if (res
== S_OK
&& (attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
))
586 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
587 ITypeLib_Release(*ppTLib
);
589 res
= TYPE_E_LIBNOTREGISTERED
;
594 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
600 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
601 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
602 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
603 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
604 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
605 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
607 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
612 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
613 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
614 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
616 get_interface_key( &tattr
->guid
, keyName
);
617 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
618 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
621 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
622 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
624 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
625 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
626 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
627 (const BYTE
*)PSOA
, sizeof PSOA
);
631 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
632 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
633 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
634 (const BYTE
*)PSOA
, sizeof PSOA
);
638 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
639 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
642 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
643 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
645 StringFromGUID2(&libattr
->guid
, buffer
, 40);
646 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
647 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
648 sprintfW(buffer
, fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
649 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
650 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
658 /******************************************************************************
659 * RegisterTypeLib [OLEAUT32.163]
660 * Adds information about a type library to the System Registry
662 * Docs: ITypeLib FAR * ptlib
663 * Docs: OLECHAR FAR* szFullPath
664 * Docs: OLECHAR FAR* szHelpDir
670 HRESULT WINAPI
RegisterTypeLib(
671 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
672 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
673 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
685 if (ptlib
== NULL
|| szFullPath
== NULL
)
688 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
692 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
695 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
699 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
703 /* Set the human-readable name of the typelib */
704 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
708 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
709 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
715 /* Make up the name of the typelib path subkey */
716 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
718 /* Create the typelib path subkey */
719 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
720 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
722 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
723 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
731 /* Create the flags subkey */
732 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
733 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
735 /* FIXME: is %u correct? */
736 static const WCHAR formatW
[] = {'%','u',0};
738 sprintfW(buf
, formatW
, attr
->wLibFlags
);
739 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
740 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
748 /* create the helpdir subkey */
749 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
750 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
752 BOOL freeHelpDir
= FALSE
;
755 /* if we created a new key, and helpDir was null, set the helpdir
756 to the directory which contains the typelib. However,
757 if we just opened an existing key, we leave the helpdir alone */
758 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
759 szHelpDir
= SysAllocString(szFullPath
);
760 pIndexStr
= strrchrW(szHelpDir
, '\\');
767 /* if we have an szHelpDir, set it! */
768 if (szHelpDir
!= NULL
) {
769 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
770 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
776 if (freeHelpDir
) SysFreeString(szHelpDir
);
788 /* register OLE Automation-compatible interfaces for this typelib */
789 types
= ITypeLib_GetTypeInfoCount(ptlib
);
790 for (tidx
=0; tidx
<types
; tidx
++) {
791 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
792 LPOLESTR name
= NULL
;
793 ITypeInfo
*tinfo
= NULL
;
795 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
798 case TKIND_INTERFACE
:
799 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
800 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
804 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
805 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
809 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
814 TYPEATTR
*tattr
= NULL
;
815 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
818 TRACE_(typelib
)("guid=%s, flags=%04x (",
819 debugstr_guid(&tattr
->guid
),
822 if (TRACE_ON(typelib
)) {
823 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
843 /* Register all dispinterfaces (which includes dual interfaces) and
844 oleautomation interfaces */
845 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
846 kind
== TKIND_DISPATCH
)
849 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
851 /* register interface<->typelib coupling */
852 TLB_register_interface(attr
, name
, tattr
, 0);
854 /* register TLBs into the opposite registry view, too */
855 if(opposite
== KEY_WOW64_32KEY
||
856 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
857 TLB_register_interface(attr
, name
, tattr
, opposite
);
860 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
863 ITypeInfo_Release(tinfo
);
870 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
876 /******************************************************************************
877 * UnRegisterTypeLib [OLEAUT32.186]
878 * Removes information about a type library from the System Registry
885 HRESULT WINAPI
UnRegisterTypeLib(
886 REFGUID libid
, /* [in] Guid of the library */
887 WORD wVerMajor
, /* [in] major version */
888 WORD wVerMinor
, /* [in] minor version */
889 LCID lcid
, /* [in] locale id */
892 BSTR tlibPath
= NULL
;
895 WCHAR subKeyName
[50];
898 BOOL deleteOtherStuff
;
901 TYPEATTR
* typeAttr
= NULL
;
903 ITypeInfo
* typeInfo
= NULL
;
904 ITypeLib
* typeLib
= NULL
;
907 TRACE("(IID: %s)\n",debugstr_guid(libid
));
909 /* Create the path to the key */
910 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
912 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
914 TRACE("Unsupported syskind %i\n", syskind
);
915 result
= E_INVALIDARG
;
919 /* get the path to the typelib on disk */
920 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
921 result
= E_INVALIDARG
;
925 /* Try and open the key to the type library. */
926 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
927 result
= E_INVALIDARG
;
931 /* Try and load the type library */
932 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
933 result
= TYPE_E_INVALIDSTATE
;
937 /* remove any types registered with this typelib */
938 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
939 for (i
=0; i
<numTypes
; i
++) {
940 /* get the kind of type */
941 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
945 /* skip non-interfaces, and get type info for the type */
946 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
949 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
952 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
956 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
957 kind
== TKIND_DISPATCH
)
959 /* the path to the type */
960 get_interface_key( &typeAttr
->guid
, subKeyName
);
962 /* Delete its bits */
963 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
)
966 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
967 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
968 RegDeleteKeyW(subKey
, TypeLibW
);
971 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
975 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
977 if (typeInfo
) ITypeInfo_Release(typeInfo
);
981 /* Now, delete the type library path subkey */
982 get_lcid_subkey( lcid
, syskind
, subKeyName
);
983 RegDeleteKeyW(key
, subKeyName
);
984 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
985 RegDeleteKeyW(key
, subKeyName
);
987 /* check if there is anything besides the FLAGS/HELPDIR keys.
988 If there is, we don't delete them */
989 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
990 deleteOtherStuff
= TRUE
;
992 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
993 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
995 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
996 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
997 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
998 deleteOtherStuff
= FALSE
;
1002 /* only delete the other parts of the key if we're absolutely sure */
1003 if (deleteOtherStuff
) {
1004 RegDeleteKeyW(key
, FLAGSW
);
1005 RegDeleteKeyW(key
, HELPDIRW
);
1009 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1010 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
1011 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1015 SysFreeString(tlibPath
);
1016 if (typeLib
) ITypeLib_Release(typeLib
);
1017 if (subKey
) RegCloseKey(subKey
);
1018 if (key
) RegCloseKey(key
);
1022 /******************************************************************************
1023 * RegisterTypeLibForUser [OLEAUT32.442]
1024 * Adds information about a type library to the user registry
1026 * Docs: ITypeLib FAR * ptlib
1027 * Docs: OLECHAR FAR* szFullPath
1028 * Docs: OLECHAR FAR* szHelpDir
1034 HRESULT WINAPI
RegisterTypeLibForUser(
1035 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1036 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1037 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1040 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1041 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1042 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1045 /******************************************************************************
1046 * UnRegisterTypeLibForUser [OLEAUT32.443]
1047 * Removes information about a type library from the user registry
1053 HRESULT WINAPI
UnRegisterTypeLibForUser(
1054 REFGUID libid
, /* [in] GUID of the library */
1055 WORD wVerMajor
, /* [in] major version */
1056 WORD wVerMinor
, /* [in] minor version */
1057 LCID lcid
, /* [in] locale id */
1060 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1061 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1062 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1065 /*======================= ITypeLib implementation =======================*/
1067 typedef struct tagTLBGuid
{
1074 typedef struct tagTLBCustData
1081 /* data structure for import typelibs */
1082 typedef struct tagTLBImpLib
1084 int offset
; /* offset in the file (MSFT)
1085 offset in nametable (SLTG)
1086 just used to identify library while reading
1088 TLBGuid
*guid
; /* libid */
1089 BSTR name
; /* name */
1091 LCID lcid
; /* lcid of imported typelib */
1093 WORD wVersionMajor
; /* major version number */
1094 WORD wVersionMinor
; /* minor version number */
1096 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1097 NULL if not yet loaded */
1101 typedef struct tagTLBString
{
1107 /* internal ITypeLib data */
1108 typedef struct tagITypeLibImpl
1110 ITypeLib2 ITypeLib2_iface
;
1111 ITypeComp ITypeComp_iface
;
1112 ICreateTypeLib2 ICreateTypeLib2_iface
;
1123 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1124 * exported to the application as a UNICODE string.
1126 struct list string_list
;
1127 struct list name_list
;
1128 struct list guid_list
;
1130 const TLBString
*Name
;
1131 const TLBString
*DocString
;
1132 const TLBString
*HelpFile
;
1133 const TLBString
*HelpStringDll
;
1134 DWORD dwHelpContext
;
1135 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1136 struct tagITypeInfoImpl
**typeinfos
;
1137 struct list custdata_list
;
1138 struct list implib_list
;
1139 int ctTypeDesc
; /* number of items in type desc array */
1140 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1141 library. Only used while reading MSFT
1143 struct list ref_list
; /* list of ref types in this typelib */
1144 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1147 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1153 static const ITypeLib2Vtbl tlbvt
;
1154 static const ITypeCompVtbl tlbtcvt
;
1155 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1157 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1159 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1162 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1164 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1167 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1169 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1172 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1174 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1177 /* ITypeLib methods */
1178 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1179 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1181 /*======================= ITypeInfo implementation =======================*/
1183 /* data for referenced types */
1184 typedef struct tagTLBRefType
1186 INT index
; /* Type index for internal ref or for external ref
1187 it the format is SLTG. -2 indicates to
1191 TLBGuid
*guid
; /* guid of the referenced type */
1192 /* if index == TLB_REF_USE_GUID */
1194 HREFTYPE reference
; /* The href of this ref */
1195 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1196 TLB_REF_INTERNAL for internal refs
1197 TLB_REF_NOT_FOUND for broken refs */
1202 #define TLB_REF_USE_GUID -2
1204 #define TLB_REF_INTERNAL (void*)-2
1205 #define TLB_REF_NOT_FOUND (void*)-1
1207 /* internal Parameter data */
1208 typedef struct tagTLBParDesc
1210 const TLBString
*Name
;
1211 struct list custdata_list
;
1214 /* internal Function data */
1215 typedef struct tagTLBFuncDesc
1217 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1218 const TLBString
*Name
; /* the name of this function */
1219 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1221 int HelpStringContext
;
1222 const TLBString
*HelpString
;
1223 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1224 struct list custdata_list
;
1227 /* internal Variable data */
1228 typedef struct tagTLBVarDesc
1230 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1231 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1232 const TLBString
*Name
; /* the name of this variable */
1234 int HelpStringContext
;
1235 const TLBString
*HelpString
;
1236 struct list custdata_list
;
1239 /* internal implemented interface data */
1240 typedef struct tagTLBImplType
1242 HREFTYPE hRef
; /* hRef of interface */
1243 int implflags
; /* IMPLFLAG_*s */
1244 struct list custdata_list
;
1247 /* internal TypeInfo data */
1248 typedef struct tagITypeInfoImpl
1250 ITypeInfo2 ITypeInfo2_iface
;
1251 ITypeComp ITypeComp_iface
;
1252 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1254 BOOL not_attached_to_typelib
;
1259 MEMBERID memidConstructor
;
1260 MEMBERID memidDestructor
;
1261 LPOLESTR lpstrSchema
;
1262 ULONG cbSizeInstance
;
1272 TYPEDESC
*tdescAlias
;
1273 IDLDESC idldescType
;
1275 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1276 int index
; /* index in this typelib; */
1277 HREFTYPE hreftype
; /* hreftype for app object binding */
1278 /* type libs seem to store the doc strings in ascii
1279 * so why should we do it in unicode?
1281 const TLBString
*Name
;
1282 const TLBString
*DocString
;
1283 const TLBString
*DllName
;
1284 const TLBString
*Schema
;
1285 DWORD dwHelpContext
;
1286 DWORD dwHelpStringContext
;
1289 TLBFuncDesc
*funcdescs
;
1292 TLBVarDesc
*vardescs
;
1294 /* Implemented Interfaces */
1295 TLBImplType
*impltypes
;
1297 struct list
*pcustdata_list
;
1298 struct list custdata_list
;
1301 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1303 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1306 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1308 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1311 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1313 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1316 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1318 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1321 static const ITypeInfo2Vtbl tinfvt
;
1322 static const ITypeCompVtbl tcompvt
;
1323 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1325 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1326 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1328 typedef struct tagTLBContext
1330 unsigned int oStart
; /* start of TLB in file */
1331 unsigned int pos
; /* current pos */
1332 unsigned int length
; /* total length */
1333 void *mapping
; /* memory mapping */
1334 MSFT_SegDir
* pTblDir
;
1335 ITypeLibImpl
* pLibInfo
;
1339 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1341 return str
!= NULL
? str
->str
: NULL
;
1344 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1348 return memcmp(left
, str
->str
, len
);
1351 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1353 return guid
!= NULL
? &guid
->guid
: NULL
;
1356 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1358 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1361 static int get_ptr_size(SYSKIND syskind
)
1371 WARN("Unhandled syskind: 0x%x\n", syskind
);
1378 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1379 if (pTD
->vt
& VT_RESERVED
)
1380 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1381 if (pTD
->vt
& VT_BYREF
)
1382 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1383 if (pTD
->vt
& VT_ARRAY
)
1384 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1385 if (pTD
->vt
& VT_VECTOR
)
1386 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1387 switch(pTD
->vt
& VT_TYPEMASK
) {
1388 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1389 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1390 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1391 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1392 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1393 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1394 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1395 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1396 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1397 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1398 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1399 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1400 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1401 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1402 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1403 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1404 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1405 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1406 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1407 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1408 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1409 pTD
->u
.hreftype
); break;
1410 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1411 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1412 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1413 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1415 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1416 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1418 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1419 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1420 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1423 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1427 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1429 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1430 dump_TypeDesc(&edesc
->tdesc
,buf
);
1431 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1432 MESSAGE("\t\tu.paramdesc.wParamFlags");
1433 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1434 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1435 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1436 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1437 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1438 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1439 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1440 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1441 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1443 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1445 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1446 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1447 MESSAGE("Param %d:\n",i
);
1448 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1450 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1451 switch (funcdesc
->funckind
) {
1452 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1453 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1454 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1455 case FUNC_STATIC
: MESSAGE("static");break;
1456 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1457 default: MESSAGE("unknown");break;
1459 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1460 switch (funcdesc
->invkind
) {
1461 case INVOKE_FUNC
: MESSAGE("func");break;
1462 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1463 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1464 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1466 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1467 switch (funcdesc
->callconv
) {
1468 case CC_CDECL
: MESSAGE("cdecl");break;
1469 case CC_PASCAL
: MESSAGE("pascal");break;
1470 case CC_STDCALL
: MESSAGE("stdcall");break;
1471 case CC_SYSCALL
: MESSAGE("syscall");break;
1474 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1475 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1476 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1478 MESSAGE("\telemdescFunc (return value type):\n");
1479 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1482 static const char * const typekind_desc
[] =
1495 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1498 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1499 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1500 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1503 dump_FUNCDESC(&(pfd
->funcdesc
));
1505 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1506 if(pfd
->Entry
== NULL
)
1507 MESSAGE("\tentry: (null)\n");
1508 else if(pfd
->Entry
== (void*)-1)
1509 MESSAGE("\tentry: invalid\n");
1510 else if(IS_INTRESOURCE(pfd
->Entry
))
1511 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1513 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1515 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1519 dump_TLBFuncDescOne(pfd
);
1524 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1528 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1534 static void dump_TLBImpLib(const TLBImpLib
*import
)
1536 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1537 debugstr_w(import
->name
));
1538 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1539 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1542 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1546 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1548 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1549 if(ref
->index
== -1)
1550 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1552 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1554 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1556 TRACE_(typelib
)("in lib\n");
1557 dump_TLBImpLib(ref
->pImpTLInfo
);
1562 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1567 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1568 impl
->hRef
, impl
->implflags
);
1574 static void dump_Variant(const VARIANT
* pvar
)
1578 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1582 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1583 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1585 TRACE(",%p", V_BYREF(pvar
));
1587 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1589 TRACE(",%p", V_ARRAY(pvar
));
1591 else switch (V_TYPE(pvar
))
1593 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1594 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1595 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1596 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1598 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1600 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1601 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1602 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1603 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1604 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1605 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1606 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1607 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1608 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1609 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1610 V_CY(pvar
).s
.Lo
); break;
1612 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1613 TRACE(",<invalid>");
1615 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1616 st
.wHour
, st
.wMinute
, st
.wSecond
);
1620 case VT_USERDEFINED
:
1622 case VT_NULL
: break;
1623 default: TRACE(",?"); break;
1629 static void dump_DispParms(const DISPPARAMS
* pdp
)
1633 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1635 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1637 TRACE("named args:\n");
1638 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1639 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1642 if (pdp
->cArgs
&& pdp
->rgvarg
)
1645 for (index
= 0; index
< pdp
->cArgs
; index
++)
1646 dump_Variant( &pdp
->rgvarg
[index
] );
1650 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1652 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1653 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1654 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1655 TRACE("kind:%s\n", typekind_desc
[pty
->typekind
]);
1656 TRACE("fct:%u var:%u impl:%u\n", pty
->cFuncs
, pty
->cVars
, pty
->cImplTypes
);
1657 TRACE("wTypeFlags: 0x%04x\n", pty
->wTypeFlags
);
1658 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1659 if (pty
->typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1661 dump_TLBFuncDesc(pty
->funcdescs
, pty
->cFuncs
);
1662 dump_TLBVarDesc(pty
->vardescs
, pty
->cVars
);
1663 dump_TLBImplType(pty
->impltypes
, pty
->cImplTypes
);
1666 static void dump_VARDESC(const VARDESC
*v
)
1668 MESSAGE("memid %d\n",v
->memid
);
1669 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1670 MESSAGE("oInst %d\n",v
->u
.oInst
);
1671 dump_ELEMDESC(&(v
->elemdescVar
));
1672 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1673 MESSAGE("varkind %d\n",v
->varkind
);
1676 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1678 /* VT_LPWSTR is largest type that, may appear in type description */
1679 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1680 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1681 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1682 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1683 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1684 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1685 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1686 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1689 static void TLB_abort(void)
1694 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1696 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1697 if (!ret
) ERR("cannot allocate memory\n");
1701 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1703 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1704 if (!ret
) ERR("cannot allocate memory\n");
1708 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1710 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1713 void heap_free(void *ptr
)
1715 HeapFree(GetProcessHeap(), 0, ptr
);
1718 /* returns the size required for a deep copy of a typedesc into a
1720 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1724 if (alloc_initial_space
)
1725 size
+= sizeof(TYPEDESC
);
1731 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1734 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1735 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1741 /* deep copy a typedesc into a flat buffer */
1742 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1747 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1756 dest
->u
.lptdesc
= buffer
;
1757 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1760 dest
->u
.lpadesc
= buffer
;
1761 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1762 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1763 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1769 /* free custom data allocated by MSFT_CustData */
1770 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1772 TLBCustData
*cd
, *cdn
;
1773 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1775 list_remove(&cd
->entry
);
1776 VariantClear(&cd
->data
);
1781 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1786 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1787 ret
= SysAllocStringLen(NULL
, len
- 1);
1788 if (!ret
) return ret
;
1789 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1793 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1794 UINT n
, MEMBERID memid
)
1797 if(funcdescs
->funcdesc
.memid
== memid
)
1805 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1806 UINT n
, const OLECHAR
*name
)
1809 if(!lstrcmpiW(TLB_get_bstr(funcdescs
->Name
), name
))
1817 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1818 UINT n
, MEMBERID memid
)
1821 if(vardescs
->vardesc
.memid
== memid
)
1829 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1830 UINT n
, const OLECHAR
*name
)
1833 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1841 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1843 TLBCustData
*cust_data
;
1844 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1845 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1850 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1851 UINT n
, const OLECHAR
*name
)
1854 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1862 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1864 list_init(&var_desc
->custdata_list
);
1867 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1871 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1876 TLBVarDesc_Constructor(&ret
[n
-1]);
1883 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1887 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1892 list_init(&ret
[n
-1].custdata_list
);
1899 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1901 list_init(&func_desc
->custdata_list
);
1904 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1908 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1913 TLBFuncDesc_Constructor(&ret
[n
-1]);
1920 static void TLBImplType_Constructor(TLBImplType
*impl
)
1922 list_init(&impl
->custdata_list
);
1925 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1929 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1934 TLBImplType_Constructor(&ret
[n
-1]);
1941 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1942 const GUID
*new_guid
, HREFTYPE hreftype
)
1946 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1947 if (IsEqualGUID(&guid
->guid
, new_guid
))
1951 guid
= heap_alloc(sizeof(TLBGuid
));
1955 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1956 guid
->hreftype
= hreftype
;
1958 list_add_tail(guid_list
, &guid
->entry
);
1963 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1965 TLBCustData
*cust_data
;
1977 return DISP_E_BADVARTYPE
;
1980 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1983 cust_data
= heap_alloc(sizeof(TLBCustData
));
1985 return E_OUTOFMEMORY
;
1987 cust_data
->guid
= tlbguid
;
1988 VariantInit(&cust_data
->data
);
1990 list_add_tail(custdata_list
, &cust_data
->entry
);
1992 VariantClear(&cust_data
->data
);
1994 return VariantCopy(&cust_data
->data
, var
);
1997 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
2004 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
2005 if (strcmpW(str
->str
, new_str
) == 0)
2009 str
= heap_alloc(sizeof(TLBString
));
2013 str
->str
= SysAllocString(new_str
);
2019 list_add_tail(string_list
, &str
->entry
);
2024 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
2025 ULONG
*size
, WORD
*align
)
2031 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
2035 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
2037 ITypeInfo_Release(other
);
2042 *size
= attr
->cbSizeInstance
;
2044 *align
= attr
->cbAlignment
;
2046 ITypeInfo_ReleaseTypeAttr(other
, attr
);
2047 ITypeInfo_Release(other
);
2052 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
2053 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
2055 ULONG i
, sub
, ptr_size
;
2058 ptr_size
= get_ptr_size(sys
);
2097 *size
= sizeof(DATE
);
2100 *size
= sizeof(VARIANT
);
2102 if(sys
== SYS_WIN32
)
2103 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2107 *size
= sizeof(DECIMAL
);
2114 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2115 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2116 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2121 case VT_USERDEFINED
:
2122 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2124 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2138 /**********************************************************************
2140 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2142 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
2147 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2149 if (where
!= DO_NOT_SEEK
)
2151 where
+= pcx
->oStart
;
2152 if (where
> pcx
->length
)
2155 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2163 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2165 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2166 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2168 MSFT_Seek(pcx
, where
);
2169 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2170 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2175 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2180 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2181 FromLEDWords(buffer
, ret
);
2186 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2191 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2192 FromLEWords(buffer
, ret
);
2197 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2200 MSFT_GuidEntry entry
;
2203 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2205 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2208 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2210 guid
= heap_alloc(sizeof(TLBGuid
));
2212 guid
->offset
= offs
;
2213 guid
->guid
= entry
.guid
;
2214 guid
->hreftype
= entry
.hreftype
;
2216 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2218 offs
+= sizeof(MSFT_GuidEntry
);
2222 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2226 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2227 if(ret
->offset
== offset
){
2228 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2236 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2238 MSFT_NameIntro niName
;
2242 ERR_(typelib
)("bad offset %d\n", offset
);
2246 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2247 pcx
->pTblDir
->pNametab
.offset
+offset
);
2249 return niName
.hreftype
;
2252 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2255 MSFT_NameIntro intro
;
2257 int offs
= 0, lengthInChars
;
2259 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2263 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2266 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2267 intro
.namelen
&= 0xFF;
2268 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2270 len_piece
= (len_piece
+ 4) & ~0x3;
2274 string
= heap_alloc(len_piece
+ 1);
2275 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2276 string
[intro
.namelen
] = '\0';
2278 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2279 string
, -1, NULL
, 0);
2280 if (!lengthInChars
) {
2282 return E_UNEXPECTED
;
2285 tlbstr
= heap_alloc(sizeof(TLBString
));
2287 tlbstr
->offset
= offs
;
2288 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2289 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2293 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2299 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2303 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2304 if (tlbstr
->offset
== offset
) {
2305 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2313 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2317 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2318 if (tlbstr
->offset
== offset
) {
2319 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2328 * read a value and fill a VARIANT structure
2330 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2334 TRACE_(typelib
)("\n");
2336 if(offset
<0) { /* data are packed in here */
2337 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2338 V_I4(pVar
) = offset
& 0x3ffffff;
2341 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2342 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2343 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2344 switch (V_VT(pVar
)){
2345 case VT_EMPTY
: /* FIXME: is this right? */
2346 case VT_NULL
: /* FIXME: is this right? */
2347 case VT_I2
: /* this should not happen */
2358 case VT_VOID
: /* FIXME: is this right? */
2366 case VT_DECIMAL
: /* FIXME: is this right? */
2369 /* pointer types with known behaviour */
2372 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2374 V_BSTR(pVar
) = NULL
;
2376 ptr
= heap_alloc_zero(size
);
2377 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2378 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2379 /* FIXME: do we need a AtoW conversion here? */
2380 V_UNION(pVar
, bstrVal
[size
])='\0';
2381 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2386 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2393 case VT_USERDEFINED
:
2399 case VT_STREAMED_OBJECT
:
2400 case VT_STORED_OBJECT
:
2401 case VT_BLOB_OBJECT
:
2406 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2410 if(size
>0) /* (big|small) endian correct? */
2411 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2415 * create a linked list with custom data
2417 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2423 TRACE_(typelib
)("\n");
2425 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2429 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2430 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2431 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2432 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2433 list_add_head(custdata_list
, &pNew
->entry
);
2434 offset
= entry
.next
;
2439 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2442 pTd
->vt
=type
& VT_TYPEMASK
;
2444 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2446 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2449 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2451 return (invkind
== INVOKE_PROPERTYGET
||
2452 invkind
== INVOKE_PROPERTYPUT
||
2453 invkind
== INVOKE_PROPERTYPUTREF
);
2457 MSFT_DoFuncs(TLBContext
* pcx
,
2462 TLBFuncDesc
** pptfd
)
2465 * member information is stored in a data structure at offset
2466 * indicated by the memoffset field of the typeinfo structure
2467 * There are several distinctive parts.
2468 * The first part starts with a field that holds the total length
2469 * of this (first) part excluding this field. Then follow the records,
2470 * for each member there is one record.
2472 * The first entry is always the length of the record (including this
2474 * The rest of the record depends on the type of the member. If there is
2475 * a field indicating the member type (function, variable, interface, etc)
2476 * I have not found it yet. At this time we depend on the information
2477 * in the type info and the usual order how things are stored.
2479 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2482 * Third is an equal sized array with file offsets to the name entry
2485 * The fourth and last (?) part is an array with offsets to the records
2486 * in the first part of this file segment.
2489 int infolen
, nameoffset
, reclength
, i
;
2490 int recoffset
= offset
+ sizeof(INT
);
2492 char *recbuf
= heap_alloc(0xffff);
2493 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2494 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2496 TRACE_(typelib
)("\n");
2498 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2500 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2502 for ( i
= 0; i
< cFuncs
; i
++ )
2506 /* name, eventually add to a hash table */
2507 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2508 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2510 /* read the function information record */
2511 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2513 reclength
&= 0xffff;
2515 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2517 /* size without argument data */
2518 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2519 if (pFuncRec
->FKCCIC
& 0x1000)
2520 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2522 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2523 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2525 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2526 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2528 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2530 if (pFuncRec
->FKCCIC
& 0x2000 )
2532 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2533 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2534 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2537 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2540 ptfd
->Entry
= (TLBString
*)-1;
2542 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2543 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2545 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2546 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2548 /* fill the FuncDesc Structure */
2549 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2550 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2552 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2553 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2554 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2555 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2556 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2557 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2558 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2560 /* nameoffset is sometimes -1 on the second half of a propget/propput
2561 * pair of functions */
2562 if ((nameoffset
== -1) && (i
> 0) &&
2563 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2564 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2565 ptfd
->Name
= ptfd_prev
->Name
;
2567 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2571 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2573 /* do the parameters/arguments */
2574 if(pFuncRec
->nrargs
)
2577 MSFT_ParameterInfo paraminfo
;
2579 ptfd
->funcdesc
.lprgelemdescParam
=
2580 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2582 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2584 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2585 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2587 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2589 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2595 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2598 if (paraminfo
.oName
!= -1)
2599 ptfd
->pParamDesc
[j
].Name
=
2600 MSFT_ReadName( pcx
, paraminfo
.oName
);
2601 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2604 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2605 (pFuncRec
->FKCCIC
& 0x1000) )
2607 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2609 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2611 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2613 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2614 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2616 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2620 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2623 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2624 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2625 pFuncRec
->FKCCIC
& 0x80 )
2628 pFuncRec
->oArgCustData
[j
],
2629 &ptfd
->pParamDesc
[j
].custdata_list
);
2632 /* SEEK value = jump to offset,
2633 * from there jump to the end of record,
2634 * go back by (j-1) arguments
2636 MSFT_ReadLEDWords( ¶minfo
,
2637 sizeof(MSFT_ParameterInfo
), pcx
,
2638 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2639 * sizeof(MSFT_ParameterInfo
)));
2643 /* scode is not used: archaic win16 stuff FIXME: right? */
2644 ptfd
->funcdesc
.cScodes
= 0 ;
2645 ptfd
->funcdesc
.lprgscode
= NULL
;
2649 recoffset
+= reclength
;
2654 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2655 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2657 int infolen
, nameoffset
, reclength
;
2659 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2664 TRACE_(typelib
)("\n");
2666 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2667 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2668 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2669 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2670 recoffset
+= offset
+sizeof(INT
);
2671 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2672 /* name, eventually add to a hash table */
2673 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2674 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2675 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2676 /* read the variable information record */
2677 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2679 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2682 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2683 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2685 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2686 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2688 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2689 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2691 /* fill the VarDesc Structure */
2692 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2693 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2694 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2695 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2696 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2697 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2698 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2699 if(pVarRec
->VarKind
== VAR_CONST
){
2700 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2701 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2702 pVarRec
->OffsValue
, pcx
);
2704 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2705 recoffset
+= reclength
;
2709 /* process Implemented Interfaces of a com class */
2710 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2714 MSFT_RefRecord refrec
;
2717 TRACE_(typelib
)("\n");
2719 pTI
->impltypes
= TLBImplType_Alloc(count
);
2720 pImpl
= pTI
->impltypes
;
2721 for(i
=0;i
<count
;i
++){
2722 if(offset
<0) break; /* paranoia */
2723 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2724 pImpl
->hRef
= refrec
.reftype
;
2725 pImpl
->implflags
=refrec
.flags
;
2726 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2727 offset
=refrec
.onext
;
2733 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2734 * and some structures, and fix the alignment */
2735 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2737 if(info
->typekind
== TKIND_ALIAS
){
2738 switch(info
->tdescAlias
->vt
){
2746 info
->cbSizeInstance
= sizeof(void*);
2747 info
->cbAlignment
= sizeof(void*);
2750 case VT_USERDEFINED
:
2751 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->cbSizeInstance
, &info
->cbAlignment
);
2754 info
->cbSizeInstance
= sizeof(VARIANT
);
2755 info
->cbAlignment
= 8;
2757 if(info
->cbSizeInstance
< sizeof(void*))
2758 info
->cbAlignment
= info
->cbSizeInstance
;
2760 info
->cbAlignment
= sizeof(void*);
2763 }else if(info
->typekind
== TKIND_INTERFACE
||
2764 info
->typekind
== TKIND_DISPATCH
||
2765 info
->typekind
== TKIND_COCLASS
){
2766 info
->cbSizeInstance
= sizeof(void*);
2767 info
->cbAlignment
= sizeof(void*);
2773 * process a typeinfo record
2775 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2778 ITypeLibImpl
* pLibInfo
)
2780 MSFT_TypeInfoBase tiBase
;
2781 ITypeInfoImpl
*ptiRet
;
2783 TRACE_(typelib
)("count=%u\n", count
);
2785 ptiRet
= ITypeInfoImpl_Constructor();
2786 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2787 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2789 /* this is where we are coming from */
2790 ptiRet
->pTypeLib
= pLibInfo
;
2791 ptiRet
->index
=count
;
2793 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2794 ptiRet
->lcid
=pLibInfo
->set_lcid
; /* FIXME: correct? */
2795 ptiRet
->lpstrSchema
=NULL
; /* reserved */
2796 ptiRet
->cbSizeInstance
=tiBase
.size
;
2797 ptiRet
->typekind
=tiBase
.typekind
& 0xF;
2798 ptiRet
->cFuncs
=LOWORD(tiBase
.cElement
);
2799 ptiRet
->cVars
=HIWORD(tiBase
.cElement
);
2800 ptiRet
->cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2801 ptiRet
->wTypeFlags
=tiBase
.flags
;
2802 ptiRet
->wMajorVerNum
=LOWORD(tiBase
.version
);
2803 ptiRet
->wMinorVerNum
=HIWORD(tiBase
.version
);
2804 ptiRet
->cImplTypes
=tiBase
.cImplTypes
;
2805 ptiRet
->cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2806 if(ptiRet
->typekind
== TKIND_ALIAS
){
2808 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2809 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2810 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2814 /* IDLDESC idldescType; *//* never saw this one != zero */
2816 /* name, eventually add to a hash table */
2817 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2818 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2819 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2821 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2822 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2823 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2825 if (ptiRet
->typekind
== TKIND_MODULE
)
2826 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2828 /* note: InfoType's Help file and HelpStringDll come from the containing
2829 * library. Further HelpString and Docstring appear to be the same thing :(
2832 if(ptiRet
->cFuncs
>0 )
2833 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->cFuncs
,
2835 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2837 if(ptiRet
->cVars
>0 )
2838 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->cFuncs
,
2840 tiBase
.memoffset
, &ptiRet
->vardescs
);
2841 if(ptiRet
->cImplTypes
>0 ) {
2842 switch(ptiRet
->typekind
)
2845 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->cImplTypes
,
2848 case TKIND_DISPATCH
:
2849 /* This is not -1 when the interface is a non-base dual interface or
2850 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2851 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2855 if (tiBase
.datatype1
!= -1)
2857 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2858 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2862 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2863 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2867 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2869 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2870 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2871 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2872 typekind_desc
[ptiRet
->typekind
]);
2873 if (TRACE_ON(typelib
))
2874 dump_TypeInfo(ptiRet
);
2879 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2882 INT16 len_str
, len_piece
;
2883 int offs
= 0, lengthInChars
;
2885 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2889 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2892 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2893 len_piece
= len_str
+ sizeof(INT16
);
2895 len_piece
= (len_piece
+ 4) & ~0x3;
2899 string
= heap_alloc(len_piece
+ 1);
2900 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2901 string
[len_str
] = '\0';
2903 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2904 string
, -1, NULL
, 0);
2905 if (!lengthInChars
) {
2907 return E_UNEXPECTED
;
2910 tlbstr
= heap_alloc(sizeof(TLBString
));
2912 tlbstr
->offset
= offs
;
2913 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2914 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2918 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2924 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2929 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2930 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2931 MSFT_ImpInfo impinfo
;
2934 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2936 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2937 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2939 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2940 if(pImpLib
->offset
==impinfo
.oImpFile
)
2943 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2944 ref
->reference
= offs
;
2945 ref
->pImpTLInfo
= pImpLib
;
2946 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2947 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2948 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2949 ref
->index
= TLB_REF_USE_GUID
;
2951 ref
->index
= impinfo
.oGuid
;
2953 ERR("Cannot find a reference\n");
2954 ref
->reference
= -1;
2955 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2958 offs
+= sizeof(impinfo
);
2964 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2965 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2966 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2969 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2970 static CRITICAL_SECTION cache_section
;
2971 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2973 0, 0, &cache_section
,
2974 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2975 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2977 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2980 typedef struct TLB_PEFile
2982 IUnknown IUnknown_iface
;
2985 HRSRC typelib_resource
;
2986 HGLOBAL typelib_global
;
2987 LPVOID typelib_base
;
2990 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2992 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2995 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2997 if (IsEqualIID(riid
, &IID_IUnknown
))
3000 IUnknown_AddRef(iface
);
3004 return E_NOINTERFACE
;
3007 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
3009 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
3010 return InterlockedIncrement(&This
->refs
);
3013 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
3015 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
3016 ULONG refs
= InterlockedDecrement(&This
->refs
);
3019 if (This
->typelib_global
)
3020 FreeResource(This
->typelib_global
);
3022 FreeLibrary(This
->dll
);
3028 static const IUnknownVtbl TLB_PEFile_Vtable
=
3030 TLB_PEFile_QueryInterface
,
3035 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)