4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
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 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
64 #define NONAMELESSUNION
65 #define NONAMELESSSTRUCT
73 #include "wine/unicode.h"
78 #include "wine/debug.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface
= { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 /****************************************************************************
90 * Takes p_iVal (which is in little endian) and returns it
91 * in the host machine's byte order.
93 #ifdef WORDS_BIGENDIAN
94 static WORD
FromLEWord(WORD p_iVal
)
96 return (((p_iVal
& 0x00FF) << 8) |
97 ((p_iVal
& 0xFF00) >> 8));
101 static DWORD
FromLEDWord(DWORD p_iVal
)
103 return (((p_iVal
& 0x000000FF) << 24) |
104 ((p_iVal
& 0x0000FF00) << 8) |
105 ((p_iVal
& 0x00FF0000) >> 8) |
106 ((p_iVal
& 0xFF000000) >> 24));
109 #define FromLEWord(X) (X)
110 #define FromLEDWord(X) (X)
114 /****************************************************************************
117 * Fix byte order in any structure if necessary
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val
, int p_iSize
)
124 p_iSize
/= sizeof(WORD
);
127 *Val
= FromLEWord(*Val
);
134 static void FromLEDWords(void *p_Val
, int p_iSize
)
138 p_iSize
/= sizeof(DWORD
);
141 *Val
= FromLEDWord(*Val
);
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
152 /****************************************************************************
153 * QueryPathOfRegTypeLib [OLEAUT32.164]
158 QueryPathOfRegTypeLib(
159 REFGUID guid
, /* [in] referenced guid */
160 WORD wMaj
, /* [in] major version */
161 WORD wMin
, /* [in] minor version */
162 LCID lcid
, /* [in] locale id */
163 LPBSTR path
) /* [out] path of typelib */
165 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
166 string termination character on output strings */
173 char szTypeLibKey
[100];
174 char szPath
[MAX_PATH
];
175 DWORD dwPathLen
= sizeof(szPath
);
183 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID
, wMaj
, wMin
, (DWORD
)lcid
, path
);
189 sprintf(szTypeLibKey
,
190 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
191 guid
->Data1
, guid
->Data2
, guid
->Data3
,
192 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
193 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
198 if (RegQueryValueA(HKEY_LOCAL_MACHINE
, szTypeLibKey
, szPath
, &dwPathLen
))
202 else if (myLCID
== lcid
)
204 /* try with sub-langid */
205 myLCID
= SUBLANGID(lcid
);
207 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
209 /* try with system langid */
219 DWORD len
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, szPath
, dwPathLen
, NULL
, 0 );
220 BSTR bstrPath
= SysAllocStringLen(NULL
,len
);
222 MultiByteToWideChar(CP_ACP
,
234 TRACE_(typelib
)("%s not found\n", szTypeLibKey
);
239 /******************************************************************************
240 * CreateTypeLib [OLEAUT32.160] creates a typelib
246 HRESULT WINAPI
CreateTypeLib(
247 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
249 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
252 /******************************************************************************
253 * LoadTypeLib [OLEAUT32.161]
254 * Loads and registers a type library
256 * Docs: OLECHAR FAR* szFile
257 * Docs: iTypeLib FAR* FAR* pptLib
263 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
265 HRESULT WINAPI
LoadTypeLib(
266 const OLECHAR
*szFile
,/* [in] Name of file to load from */
267 ITypeLib
* *pptLib
) /* [out] Pointer to pointer to loaded type library */
270 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
273 /******************************************************************************
274 * LoadTypeLibEx [OLEAUT32.183]
275 * Loads and optionally registers a type library
281 HRESULT WINAPI
LoadTypeLibEx(
282 LPCOLESTR szFile
, /* [in] Name of file to load from */
283 REGKIND regkind
, /* [in] Specify kind of registration */
284 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
286 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
291 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
294 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
297 /* Look for a trailing '\\' followed by an index */
298 pIndexStr
= strrchrW(szFile
, '\\');
299 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
300 index
= atoiW(pIndexStr
);
301 memcpy(szFileCopy
, szFile
,
302 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
303 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
304 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
306 return TYPE_E_CANTLOADLIBRARY
;
307 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
308 return TYPE_E_CANTLOADLIBRARY
;
311 WCHAR stdole32tlb
[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
314 lstrcpyW(tstpath
,szFile
);
316 for (i
=0;i
<strlenW(tstpath
);i
++) {
317 if (tstpath
[i
] == 's') {
318 if (!strcmpW(tstpath
+i
,stdole32tlb
)) {
320 MESSAGE("**************************************************************************\n");
321 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
322 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
323 MESSAGE("on the Microsoft Download Pages.\n");
324 MESSAGE("**************************************************************************\n");
329 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile
));
330 return TYPE_E_CANTLOADLIBRARY
;
334 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
336 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
341 case REGKIND_DEFAULT
:
342 /* FIXME: is this correct? */
343 if (!szFile
|| !szFile
[0] ||
344 (szFile
[0] != '\\' && szFile
[0] != '/' && szFile
[1] != ':'))
346 /* else fall-through */
347 case REGKIND_REGISTER
:
348 /* FIXME: Help path? */
349 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szFile
, NULL
)))
351 IUnknown_Release(*pptLib
);
359 TRACE(" returns %08lx\n",res
);
363 /******************************************************************************
364 * LoadRegTypeLib [OLEAUT32.162]
366 HRESULT WINAPI
LoadRegTypeLib(
367 REFGUID rguid
, /* [in] referenced guid */
368 WORD wVerMajor
, /* [in] major version */
369 WORD wVerMinor
, /* [in] minor version */
370 LCID lcid
, /* [in] locale id */
371 ITypeLib
**ppTLib
) /* [out] path of typelib */
374 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
378 res
= LoadTypeLib(bstr
, ppTLib
);
382 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
388 /******************************************************************************
389 * RegisterTypeLib [OLEAUT32.163]
390 * Adds information about a type library to the System Registry
392 * Docs: ITypeLib FAR * ptlib
393 * Docs: OLECHAR FAR* szFullPath
394 * Docs: OLECHAR FAR* szHelpDir
400 HRESULT WINAPI
RegisterTypeLib(
401 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
402 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
403 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
414 static const char *PSOA
= "{00020424-0000-0000-C000-000000000046}";
416 if (ptlib
== NULL
|| szFullPath
== NULL
)
419 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
422 StringFromGUID2(&attr
->guid
, guid
, 80);
423 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
424 snprintf(keyName
, sizeof(keyName
), "TypeLib\\%s\\%x.%x",
425 guidA
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
426 HeapFree(GetProcessHeap(), 0, guidA
);
429 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
430 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
434 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
436 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
437 (BYTE
*)doc
, lstrlenW(doc
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
445 /* FIXME: This *seems* to be 0 always, not sure though */
446 if (res
== S_OK
&& RegCreateKeyExA(key
, "0\\win32", 0, NULL
, 0,
447 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
449 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
450 (BYTE
*)szFullPath
, lstrlenW(szFullPath
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
458 if (res
== S_OK
&& RegCreateKeyExA(key
, "FLAGS", 0, NULL
, 0,
459 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
462 /* FIXME: is %u correct? */
463 snprintf(buf
, sizeof(buf
), "%u", attr
->wLibFlags
);
464 if (RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
465 buf
, lstrlenA(buf
) + 1) != ERROR_SUCCESS
)
473 /* register OLE Automation-compatible interfaces for this typelib */
474 types
= ITypeLib_GetTypeInfoCount(ptlib
);
475 for (tidx
=0; tidx
<types
; tidx
++) {
476 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
477 LPOLESTR name
= NULL
;
478 ITypeInfo
*tinfo
= NULL
;
480 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
482 case TKIND_INTERFACE
:
483 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
484 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
487 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
488 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
491 TRACE_(typelib
)("%d: coclass %s\n", tidx
, debugstr_w(name
));
492 /* coclasses should probably not be registered? */
495 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
499 TYPEATTR
*tattr
= NULL
;
500 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
502 TRACE_(typelib
)("guid=%s, flags=%04x (",
503 debugstr_guid(&tattr
->guid
),
505 if (TRACE_ON(typelib
)) {
506 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
526 * FIXME: The 1 is just here until we implement rpcrt4
527 * stub/proxy handling. Until then it helps IShield
530 if (1 || (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
))
532 /* register interface<->typelib coupling */
533 StringFromGUID2(&tattr
->guid
, guid
, 80);
534 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
535 snprintf(keyName
, sizeof(keyName
), "Interface\\%s", guidA
);
536 HeapFree(GetProcessHeap(), 0, guidA
);
538 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
539 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
541 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
542 (BYTE
*)name
, lstrlenW(name
) * sizeof(OLECHAR
));
544 if (RegCreateKeyExA(key
, "ProxyStubClsid", 0, NULL
, 0,
545 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
546 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
550 if (RegCreateKeyExA(key
, "ProxyStubClsid32", 0, NULL
, 0,
551 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
552 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
557 if (RegCreateKeyExA(key
, "TypeLib", 0, NULL
, 0,
558 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
560 StringFromGUID2(&attr
->guid
, guid
, 80);
561 snprintf(ver
, sizeof(ver
), "%x.%x",
562 attr
->wMajorVerNum
, attr
->wMinorVerNum
);
563 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
564 (BYTE
*)guid
, lstrlenW(guid
) * sizeof(OLECHAR
));
565 RegSetValueExA(subKey
, "Version", 0, REG_SZ
,
572 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
574 ITypeInfo_Release(tinfo
);
581 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
587 /******************************************************************************
588 * UnRegisterTypeLib [OLEAUT32.186]
589 * Removes information about a type library from the System Registry
596 HRESULT WINAPI
UnRegisterTypeLib(
597 REFGUID libid
, /* [in] Guid of the library */
598 WORD wVerMajor
, /* [in] major version */
599 WORD wVerMinor
, /* [in] minor version */
600 LCID lcid
, /* [in] locale id */
603 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
604 return S_OK
; /* FIXME: pretend everything is OK */
607 /*======================= ITypeLib implementation =======================*/
609 typedef struct tagTLBCustData
613 struct tagTLBCustData
* next
;
616 /* data structure for import typelibs */
617 typedef struct tagTLBImpLib
619 int offset
; /* offset in the file (MSFT)
620 offset in nametable (SLTG)
621 just used to identify library while reading
623 GUID guid
; /* libid */
624 BSTR name
; /* name */
626 LCID lcid
; /* lcid of imported typelib */
628 WORD wVersionMajor
; /* major version number */
629 WORD wVersionMinor
; /* minor version number */
631 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
632 NULL if not yet loaded */
633 struct tagTLBImpLib
* next
;
636 /* internal ITypeLib data */
637 typedef struct tagITypeLibImpl
639 ICOM_VFIELD(ITypeLib2
);
640 ICOM_VTABLE(ITypeComp
) * lpVtblTypeComp
;
642 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
644 /* strings can be stored in tlb as multibyte strings BUT they are *always*
645 * exported to the application as a UNICODE string.
651 unsigned long dwHelpContext
;
652 int TypeInfoCount
; /* nr of typeinfo's in librarry */
653 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
654 int ctCustData
; /* number of items in cust data list */
655 TLBCustData
* pCustData
; /* linked list to cust data */
656 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
657 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
658 libary. Only used while read MSFT
661 /* typelibs are cached, keyed by path, so store the linked list info within them */
662 struct tagITypeLibImpl
*next
, *prev
;
666 static struct ICOM_VTABLE(ITypeLib2
) tlbvt
;
667 static struct ICOM_VTABLE(ITypeComp
) tlbtcvt
;
669 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
670 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
672 /* ITypeLib methods */
673 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
674 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
676 /*======================= ITypeInfo implementation =======================*/
678 /* data for refernced types */
679 typedef struct tagTLBRefType
681 INT index
; /* Type index for internal ref or for external ref
682 it the format is SLTG. -2 indicates to
685 GUID guid
; /* guid of the referenced type */
686 /* if index == TLB_REF_USE_GUID */
688 HREFTYPE reference
; /* The href of this ref */
689 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
690 TLB_REF_INTERNAL for internal refs
691 TLB_REF_NOT_FOUND for broken refs */
693 struct tagTLBRefType
* next
;
696 #define TLB_REF_USE_GUID -2
698 #define TLB_REF_INTERNAL (void*)-2
699 #define TLB_REF_NOT_FOUND (void*)-1
701 /* internal Parameter data */
702 typedef struct tagTLBParDesc
706 TLBCustData
* pCustData
; /* linked list to cust data */
709 /* internal Function data */
710 typedef struct tagTLBFuncDesc
712 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
713 BSTR Name
; /* the name of this function */
714 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
716 int HelpStringContext
;
718 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
720 TLBCustData
* pCustData
; /* linked list to cust data; */
721 struct tagTLBFuncDesc
* next
;
724 /* internal Variable data */
725 typedef struct tagTLBVarDesc
727 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
728 BSTR Name
; /* the name of this variable */
730 int HelpStringContext
; /* FIXME: where? */
733 TLBCustData
* pCustData
;/* linked list to cust data; */
734 struct tagTLBVarDesc
* next
;
737 /* internal implemented interface data */
738 typedef struct tagTLBImplType
740 HREFTYPE hRef
; /* hRef of interface */
741 int implflags
; /* IMPLFLAG_*s */
743 TLBCustData
* pCustData
;/* linked list to custom data; */
744 struct tagTLBImplType
*next
;
747 /* internal TypeInfo data */
748 typedef struct tagITypeInfoImpl
750 ICOM_VFIELD(ITypeInfo2
);
751 ICOM_VTABLE(ITypeComp
) * lpVtblTypeComp
;
753 TYPEATTR TypeAttr
; /* _lots_ of type information. */
754 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
755 int index
; /* index in this typelib; */
756 /* type libs seem to store the doc strings in ascii
757 * so why should we do it in unicode?
761 unsigned long dwHelpContext
;
762 unsigned long dwHelpStringContext
;
765 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
768 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
770 /* Implemented Interfaces */
771 TLBImplType
* impltypelist
;
773 TLBRefType
* reflist
;
775 TLBCustData
* pCustData
; /* linked list to cust data; */
776 struct tagITypeInfoImpl
* next
;
779 static struct ICOM_VTABLE(ITypeInfo2
) tinfvt
;
780 static struct ICOM_VTABLE(ITypeComp
) tcompvt
;
782 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor();
784 typedef struct tagTLBContext
786 unsigned int oStart
; /* start of TLB in file */
787 unsigned int pos
; /* current pos */
788 unsigned int length
; /* total length */
789 void *mapping
; /* memory mapping */
790 MSFT_SegDir
* pTblDir
;
791 ITypeLibImpl
* pLibInfo
;
795 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
800 static void dump_VarType(VARTYPE vt
,char *szVarType
) {
801 /* FIXME : we could have better trace here, depending on the VARTYPE
804 if (vt
& VT_RESERVED
)
805 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
807 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
809 szVarType
+= strlen(strcpy(szVarType
, "array of "));
811 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
812 switch(vt
& VT_TYPEMASK
) {
813 case VT_UI1
: sprintf(szVarType
, "VT_UI"); break;
814 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
815 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
816 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
817 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
818 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
819 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
820 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
821 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
822 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
823 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
824 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
825 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
826 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
827 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
828 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
829 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
830 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
831 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
832 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED\n"); break;
833 default: sprintf(szVarType
, "unknown(%d)", vt
& VT_TYPEMASK
); break;
837 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
838 if (pTD
->vt
& VT_RESERVED
)
839 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
840 if (pTD
->vt
& VT_BYREF
)
841 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
842 if (pTD
->vt
& VT_ARRAY
)
843 szVarType
+= strlen(strcpy(szVarType
, "array of "));
844 if (pTD
->vt
& VT_VECTOR
)
845 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
846 switch(pTD
->vt
& VT_TYPEMASK
) {
847 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
848 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
849 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
850 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
851 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
852 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
853 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
854 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
855 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
856 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
857 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
858 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
859 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
860 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
861 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
862 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
863 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
864 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
865 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
866 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
867 pTD
->u
.hreftype
); break;
868 case VT_PTR
: sprintf(szVarType
, "ptr to ");
869 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
871 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
872 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
874 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
875 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
876 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
879 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
883 void dump_ELEMDESC(ELEMDESC
*edesc
) {
885 dump_TypeDesc(&edesc
->tdesc
,buf
);
886 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
887 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
888 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
890 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
892 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
893 for (i
=0;i
<funcdesc
->cParams
;i
++) {
894 MESSAGE("Param %d:\n",i
);
895 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
897 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
898 switch (funcdesc
->funckind
) {
899 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
900 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
901 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
902 case FUNC_STATIC
: MESSAGE("static");break;
903 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
904 default: MESSAGE("unknown");break;
906 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
907 switch (funcdesc
->invkind
) {
908 case INVOKE_FUNC
: MESSAGE("func");break;
909 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
910 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
911 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
913 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
914 switch (funcdesc
->callconv
) {
915 case CC_CDECL
: MESSAGE("cdecl");break;
916 case CC_PASCAL
: MESSAGE("pascal");break;
917 case CC_STDCALL
: MESSAGE("stdcall");break;
918 case CC_SYSCALL
: MESSAGE("syscall");break;
921 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
922 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
923 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
926 void dump_IDLDESC(IDLDESC
*idl
) {
927 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
930 static const char * typekind_desc
[] =
943 void dump_TYPEATTR(TYPEATTR
*tattr
) {
945 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
946 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
947 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
948 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
949 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
950 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
951 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
952 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
953 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
954 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
955 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
956 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
957 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
958 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
959 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
960 MESSAGE("\ttypedesc: %s\n", buf
);
961 dump_IDLDESC(&tattr
->idldescType
);
964 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
967 if (!TRACE_ON(typelib
))
969 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
970 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
971 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
974 dump_FUNCDESC(&(pfd
->funcdesc
));
976 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
977 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
979 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
983 dump_TLBFuncDescOne(pfd
);
987 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
991 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
996 static void dump_TLBImpLib(TLBImpLib
*import
)
998 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
999 debugstr_w(import
->name
));
1000 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1001 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1004 static void dump_TLBRefType(TLBRefType
* prt
)
1008 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1009 if(prt
->index
== -1)
1010 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1012 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1014 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1015 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1016 TRACE_(typelib
)("in lib\n");
1017 dump_TLBImpLib(prt
->pImpTLInfo
);
1023 static void dump_TLBImplType(TLBImplType
* impl
)
1027 "implementing/inheriting interface hRef = %lx implflags %x\n",
1028 impl
->hRef
, impl
->implflags
);
1033 void dump_Variant(VARIANT
* pvar
)
1038 TRACE("(%p)\n", pvar
);
1042 ZeroMemory(szVarType
, sizeof(szVarType
));
1044 /* FIXME : we could have better trace here, depending on the VARTYPE
1047 dump_VarType(V_VT(pvar
),szVarType
);
1049 TRACE("VARTYPE: %s\n", szVarType
);
1051 if (V_VT(pvar
) & VT_BYREF
) {
1052 ref
= V_UNION(pvar
, byref
);
1055 else ref
= &V_UNION(pvar
, cVal
);
1057 if (V_VT(pvar
) & VT_ARRAY
) {
1061 if (V_VT(pvar
) & VT_VECTOR
) {
1066 switch (V_VT(pvar
) & VT_TYPEMASK
)
1069 TRACE("%d\n", *(short*)ref
);
1074 TRACE("%u\n", *(UINT
*)ref
);
1079 TRACE("%d\n", *(INT
*)ref
);
1083 TRACE("%3.3e\n", *(float*)ref
);
1087 TRACE("%3.3e\n", *(double*)ref
);
1091 TRACE("%s\n", *(VARIANT_BOOL
*)ref
? "TRUE" : "FALSE");
1095 TRACE("%s\n", debugstr_w(*(BSTR
*)ref
));
1100 TRACE("%p\n", *(LPVOID
*)ref
);
1104 if (V_VT(pvar
) & VT_BYREF
) dump_Variant(ref
);
1110 memset( &TM
, 0, sizeof(TM
) );
1112 if( DateToTm( *(DATE
*)ref
, 0, &TM
) == FALSE
) {
1113 TRACE("invalid date? (?)%ld %f\n", *(long*)ref
, *(double *)ref
);
1115 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1116 TM
.tm_year
, TM
.tm_mon
+1, TM
.tm_mday
,
1117 TM
.tm_hour
, TM
.tm_min
, TM
.tm_sec
, *(double *)ref
);
1123 TRACE("%ld (hi), %lu (lo)\n", ((CY
*)ref
)->s
.Hi
, ((CY
*)ref
)->s
.Lo
);
1128 TRACE("(?)%ld\n", *(long*)ref
);
1133 static void dump_DispParms(DISPPARAMS
* pdp
)
1137 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1139 while (index
< pdp
->cArgs
)
1141 dump_Variant( &pdp
->rgvarg
[index
] );
1146 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1148 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1149 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1150 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1151 TRACE("fct:%u var:%u impl:%u\n",
1152 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1153 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1154 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1155 dump_TLBFuncDesc(pty
->funclist
);
1156 dump_TLBVarDesc(pty
->varlist
);
1157 dump_TLBImplType(pty
->impltypelist
);
1160 void dump_VARDESC(VARDESC
*v
)
1162 MESSAGE("memid %ld\n",v
->memid
);
1163 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1164 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1165 dump_ELEMDESC(&(v
->elemdescVar
));
1166 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1167 MESSAGE("varkind %d\n",v
->varkind
);
1170 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1172 /* VT_LPWSTR is largest type that */
1173 /* may appear in type description*/
1174 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1175 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1176 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1177 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1178 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1179 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1183 static void TLB_abort()
1187 static void * TLB_Alloc(unsigned size
)
1190 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1192 ERR("cannot allocate memory\n");
1197 static void TLB_Free(void * ptr
)
1199 HeapFree(GetProcessHeap(), 0, ptr
);
1203 /**********************************************************************
1205 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1208 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1210 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1211 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1213 if (where
!= DO_NOT_SEEK
)
1215 where
+= pcx
->oStart
;
1216 if (where
> pcx
->length
)
1219 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1224 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1225 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1230 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1235 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1236 FromLEDWords(buffer
, ret
);
1241 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1246 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1247 FromLEWords(buffer
, ret
);
1252 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1254 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1255 memset(pGuid
,0, sizeof(GUID
));
1258 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1259 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1260 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1261 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1262 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1265 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1268 MSFT_NameIntro niName
;
1270 WCHAR
* pwstring
= NULL
;
1271 BSTR bstrName
= NULL
;
1273 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1274 pcx
->pTblDir
->pNametab
.offset
+offset
);
1275 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1276 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1277 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1278 name
[niName
.namelen
& 0xff]='\0';
1280 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1283 /* no invalid characters in string */
1286 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1288 /* don't check for invalid character since this has been done previously */
1289 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1291 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1292 lengthInChars
= SysStringLen(bstrName
);
1293 HeapFree(GetProcessHeap(), 0, pwstring
);
1296 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1300 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1307 if(offset
<0) return NULL
;
1308 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1309 if(length
<= 0) return 0;
1310 string
=TLB_Alloc(length
+1);
1311 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1312 string
[length
]='\0';
1314 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1315 string
, -1, NULL
, 0);
1317 /* no invalid characters in string */
1320 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1322 /* don't check for invalid character since this has been done previously */
1323 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1325 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1326 lengthInChars
= SysStringLen(bstr
);
1327 HeapFree(GetProcessHeap(), 0, pwstring
);
1330 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1334 * read a value and fill a VARIANT structure
1336 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1340 TRACE_(typelib
)("\n");
1342 if(offset
<0) { /* data are packed in here */
1343 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1344 V_UNION(pVar
, iVal
) = offset
& 0xffff;
1347 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1348 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1349 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1350 switch (V_VT(pVar
)){
1351 case VT_EMPTY
: /* FIXME: is this right? */
1352 case VT_NULL
: /* FIXME: is this right? */
1353 case VT_I2
: /* this should not happen */
1364 case VT_VOID
: /* FIXME: is this right? */
1372 case VT_DECIMAL
: /* FIXME: is this right? */
1375 /* pointer types with known behaviour */
1378 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1380 FIXME("BSTR length = %d?\n", size
);
1382 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1383 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1384 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1385 /* FIXME: do we need a AtoW conversion here? */
1386 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1387 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1392 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1399 case VT_USERDEFINED
:
1405 case VT_STREAMED_OBJECT
:
1406 case VT_STORED_OBJECT
:
1407 case VT_BLOB_OBJECT
:
1412 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1416 if(size
>0) /* (big|small) endian correct? */
1417 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1421 * create a linked list with custom data
1423 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1429 TRACE_(typelib
)("\n");
1433 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1434 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1435 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1436 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1437 /* add new custom data at head of the list */
1438 pNew
->next
=*ppCustData
;
1440 offset
= entry
.next
;
1445 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1449 pTd
->vt
=type
& VT_TYPEMASK
;
1451 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1453 if(pTd
->vt
== VT_USERDEFINED
)
1454 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1456 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1460 MSFT_DoFuncs(TLBContext
* pcx
,
1465 TLBFuncDesc
** pptfd
)
1468 * member information is stored in a data structure at offset
1469 * indicated by the memoffset field of the typeinfo structure
1470 * There are several distinctive parts.
1471 * the first part starts with a field that holds the total length
1472 * of this (first) part excluding this field. Then follow the records,
1473 * for each member there is one record.
1475 * First entry is always the length of the record (excluding this
1477 * Rest of the record depends on the type of the member. If there is
1478 * a field indicating the member type (function variable intereface etc)
1479 * I have not found it yet. At this time we depend on the information
1480 * in the type info and the usual order how things are stored.
1482 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1485 * Third is a equal sized array with file offsets to the name entry
1488 * Forth and last (?) part is an array with offsets to the records in the
1489 * first part of this file segment.
1492 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1493 int recoffset
= offset
+ sizeof(INT
);
1496 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1498 TRACE_(typelib
)("\n");
1500 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1502 for ( i
= 0; i
< cFuncs
; i
++ )
1504 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1506 /* name, eventually add to a hash table */
1507 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1508 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1510 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1512 /* read the function information record */
1513 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1517 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1519 /* do the attributes */
1520 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1523 if ( nrattributes
> 0 )
1525 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1527 if ( nrattributes
> 1 )
1529 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1530 pFuncRec
->OptAttr
[1]) ;
1532 if ( nrattributes
> 2 )
1534 if ( pFuncRec
->FKCCIC
& 0x2000 )
1536 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1540 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1541 pFuncRec
->OptAttr
[2]);
1543 if( nrattributes
> 5 )
1545 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1547 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1550 pFuncRec
->OptAttr
[6],
1551 &(*pptfd
)->pCustData
);
1558 /* fill the FuncDesc Structure */
1559 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1560 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1562 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1563 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1564 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1565 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1566 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1567 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1568 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1572 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1575 /* do the parameters/arguments */
1576 if(pFuncRec
->nrargs
)
1579 MSFT_ParameterInfo paraminfo
;
1581 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1582 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1584 (*pptfd
)->pParamDesc
=
1585 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1587 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1588 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1590 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1592 TYPEDESC
* lpArgTypeDesc
= 0;
1596 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1599 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1601 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1603 /* SEEK value = jump to offset,
1604 * from there jump to the end of record,
1605 * go back by (j-1) arguments
1607 MSFT_ReadLEDWords( ¶minfo
,
1608 sizeof(MSFT_ParameterInfo
), pcx
,
1609 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1610 * sizeof(MSFT_ParameterInfo
)));
1612 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1614 while ( lpArgTypeDesc
!= NULL
)
1616 switch ( lpArgTypeDesc
->vt
)
1619 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1623 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1626 case VT_USERDEFINED
:
1627 MSFT_DoRefType(pcx
, pTI
,
1628 lpArgTypeDesc
->u
.hreftype
);
1630 lpArgTypeDesc
= NULL
;
1634 lpArgTypeDesc
= NULL
;
1640 /* parameter is the return value! */
1641 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1643 TYPEDESC
* lpArgTypeDesc
;
1645 (*pptfd
)->funcdesc
.elemdescFunc
=
1646 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1648 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1650 while ( lpArgTypeDesc
!= NULL
)
1652 switch ( lpArgTypeDesc
->vt
)
1655 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1659 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1663 case VT_USERDEFINED
:
1666 lpArgTypeDesc
->u
.hreftype
);
1668 lpArgTypeDesc
= NULL
;
1672 lpArgTypeDesc
= NULL
;
1677 /* second time around */
1678 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1681 (*pptfd
)->pParamDesc
[j
].Name
=
1682 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1685 if ( (PARAMFLAG_FHASDEFAULT
&
1686 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1687 ((pFuncRec
->FKCCIC
) & 0x1000) )
1689 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1691 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1693 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1695 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1696 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1698 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1702 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1705 pFuncRec
->OptAttr
[7+j
],
1706 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1711 /* scode is not used: archaic win16 stuff FIXME: right? */
1712 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1713 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1715 pptfd
= & ((*pptfd
)->next
);
1716 recoffset
+= reclength
;
1720 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1721 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1723 int infolen
, nameoffset
, reclength
;
1725 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1729 TRACE_(typelib
)("\n");
1731 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1732 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1733 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1734 recoffset
+= offset
+sizeof(INT
);
1735 for(i
=0;i
<cVars
;i
++){
1736 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1737 /* name, eventually add to a hash table */
1738 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1739 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1740 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1741 /* read the variable information record */
1742 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1744 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1746 if(reclength
>(6*sizeof(INT
)) )
1747 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1748 if(reclength
>(7*sizeof(INT
)) )
1749 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1750 if(reclength
>(8*sizeof(INT
)) )
1751 if(reclength
>(9*sizeof(INT
)) )
1752 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1753 /* fill the VarDesc Structure */
1754 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1755 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1756 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1757 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1758 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1759 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1760 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1761 if(pVarRec
->VarKind
== VAR_CONST
){
1762 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1763 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1764 pVarRec
->OffsValue
, pcx
);
1766 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1767 pptvd
=&((*pptvd
)->next
);
1768 recoffset
+= reclength
;
1771 /* fill in data for a hreftype (offset). When the refernced type is contained
1772 * in the typelib, it's just an (file) offset in the type info base dir.
1773 * If comes from import, it's an offset+1 in the ImpInfo table
1775 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1779 TLBRefType
**ppRefType
= &pTI
->reflist
;
1781 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1784 if((*ppRefType
)->reference
== offset
)
1786 ppRefType
= &(*ppRefType
)->next
;
1789 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1790 sizeof(**ppRefType
));
1792 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1793 /* external typelib */
1794 MSFT_ImpInfo impinfo
;
1795 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1797 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1799 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1800 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1801 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1802 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1803 pImpLib
=pImpLib
->next
;
1806 (*ppRefType
)->reference
=offset
;
1807 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1808 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1809 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1811 ERR("Cannot find a reference\n");
1812 (*ppRefType
)->reference
=-1;
1813 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1816 /* in this typelib */
1817 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1818 (*ppRefType
)->reference
=offset
;
1819 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1823 /* process Implemented Interfaces of a com class */
1824 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1828 MSFT_RefRecord refrec
;
1829 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1831 TRACE_(typelib
)("\n");
1833 for(i
=0;i
<count
;i
++){
1834 if(offset
<0) break; /* paranoia */
1835 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1836 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1837 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1838 (*ppImpl
)->hRef
= refrec
.reftype
;
1839 (*ppImpl
)->implflags
=refrec
.flags
;
1840 (*ppImpl
)->ctCustData
=
1841 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1842 offset
=refrec
.onext
;
1843 ppImpl
=&((*ppImpl
)->next
);
1847 * process a typeinfo record
1849 ITypeInfoImpl
* MSFT_DoTypeInfo(
1852 ITypeLibImpl
* pLibInfo
)
1854 MSFT_TypeInfoBase tiBase
;
1855 ITypeInfoImpl
*ptiRet
;
1857 TRACE_(typelib
)("count=%u\n", count
);
1859 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
1860 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
1861 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
1862 /* this is where we are coming from */
1863 ptiRet
->pTypeLib
= pLibInfo
;
1864 ptiRet
->index
=count
;
1865 /* fill in the typeattr fields */
1866 WARN("Assign constructor/destructor memid\n");
1868 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
1869 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
1870 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
1871 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
1872 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
1873 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
1874 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
1875 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
1876 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
1877 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
1878 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
1879 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
1880 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
1881 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
1882 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
1883 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
1884 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
1885 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
1888 /* IDLDESC idldescType; *//* never saw this one != zero */
1890 /* name, eventually add to a hash table */
1891 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
1892 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
1894 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
1895 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
1896 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
1897 /* note: InfoType's Help file and HelpStringDll come from the containing
1898 * library. Further HelpString and Docstring appear to be the same thing :(
1901 if(ptiRet
->TypeAttr
.cFuncs
>0 )
1902 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1903 ptiRet
->TypeAttr
.cVars
,
1904 tiBase
.memoffset
, & ptiRet
->funclist
);
1906 if(ptiRet
->TypeAttr
.cVars
>0 )
1907 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1908 ptiRet
->TypeAttr
.cVars
,
1909 tiBase
.memoffset
, & ptiRet
->varlist
);
1910 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
1911 switch(ptiRet
->TypeAttr
.typekind
)
1914 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
1917 case TKIND_DISPATCH
:
1918 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1920 if (tiBase
.datatype1
!= -1)
1922 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1923 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1926 { /* FIXME: This is a really bad hack to add IDispatch */
1927 const char* szStdOle
= "stdole2.tlb\0";
1928 int nStdOleLen
= strlen(szStdOle
);
1929 TLBRefType
**ppRef
= &ptiRet
->reflist
;
1932 if((*ppRef
)->reference
== -1)
1934 ppRef
= &(*ppRef
)->next
;
1937 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
1938 (*ppRef
)->guid
= IID_IDispatch
;
1939 (*ppRef
)->reference
= -1;
1940 (*ppRef
)->index
= TLB_REF_USE_GUID
;
1941 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
1942 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
1943 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
1946 MultiByteToWideChar(CP_ACP
,
1950 (*ppRef
)->pImpTLInfo
->name
,
1951 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
1953 (*ppRef
)->pImpTLInfo
->lcid
= 0;
1954 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
1955 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
1960 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1961 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1962 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1967 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
1969 TRACE_(typelib
)("%s guid: %s kind:%s\n",
1970 debugstr_w(ptiRet
->Name
),
1971 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
1972 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
1977 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
1978 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
1979 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
1982 static ITypeLibImpl
*tlb_cache_first
;
1983 static CRITICAL_SECTION cache_section
;
1984 static CRITICAL_SECTION_DEBUG cache_section_debug
=
1986 0, 0, &cache_section
,
1987 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
1988 0, 0, { 0, (DWORD
)(__FILE__
": typelib loader cache") }
1990 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
1993 /****************************************************************************
1996 * find the type of the typelib file and map the typelib resource into
1999 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2000 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2001 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2003 ITypeLibImpl
*entry
;
2004 int ret
= TYPE_E_CANTLOADLIBRARY
;
2005 DWORD dwSignature
= 0;
2008 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2012 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2013 EnterCriticalSection(&cache_section
);
2014 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2016 if (!strcmpiW(entry
->path
, pszFileName
))
2018 TRACE("cache hit\n");
2019 *ppTypeLib
= (ITypeLib2
*)entry
;
2020 ITypeLib_AddRef(*ppTypeLib
);
2021 LeaveCriticalSection(&cache_section
);
2025 LeaveCriticalSection(&cache_section
);
2027 /* check the signature of the file */
2028 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2029 if (INVALID_HANDLE_VALUE
!= hFile
)
2031 HANDLE hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2034 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2037 /* retrieve file size */
2038 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2040 /* first try to load as *.tlb */
2041 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2042 if ( dwSignature
== MSFT_SIGNATURE
)
2044 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2046 else if ( dwSignature
== SLTG_SIGNATURE
)
2048 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2050 UnmapViewOfFile(pBase
);
2052 CloseHandle(hMapping
);
2057 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
2059 /* find the typelibrary resource*/
2060 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2061 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2064 HRSRC hrsrc
= FindResourceA(hinstDLL
, MAKEINTRESOURCEA(index
),
2068 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2071 LPVOID pBase
= LockResource(hGlobal
);
2072 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2076 /* try to load as incore resource */
2077 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2078 if ( dwSignature
== MSFT_SIGNATURE
)
2080 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2082 else if ( dwSignature
== SLTG_SIGNATURE
)
2084 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2088 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2091 FreeResource( hGlobal
);
2094 FreeLibrary(hinstDLL
);
2099 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2101 TRACE("adding to cache\n");
2102 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2103 lstrcpyW(impl
->path
, pszFileName
);
2104 /* We should really canonicalise the path here. */
2106 /* FIXME: check if it has added already in the meantime */
2107 EnterCriticalSection(&cache_section
);
2108 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2110 tlb_cache_first
= impl
;
2111 LeaveCriticalSection(&cache_section
);
2114 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2119 /*================== ITypeLib(2) Methods ===================================*/
2121 /****************************************************************************
2122 * ITypeLib2_Constructor_MSFT
2124 * loading an MSFT typelib from an in-memory image
2126 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2130 MSFT_Header tlbHeader
;
2131 MSFT_SegDir tlbSegDir
;
2132 ITypeLibImpl
* pTypeLibImpl
;
2134 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2136 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2137 if (!pTypeLibImpl
) return NULL
;
2139 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2140 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2141 pTypeLibImpl
->ref
= 1;
2143 /* get pointer to beginning of typelib data */
2147 cx
.pLibInfo
= pTypeLibImpl
;
2148 cx
.length
= dwTLBLength
;
2151 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2153 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2154 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2155 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2158 /* there is a small amount of information here until the next important
2160 * the segment directory . Try to calculate the amount of data */
2161 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2163 /* now read the segment directory */
2164 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2165 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2166 cx
.pTblDir
= &tlbSegDir
;
2168 /* just check two entries */
2169 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2171 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2172 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2176 /* now fill our internal data */
2177 /* TLIBATTR fields */
2178 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2180 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2181 /* Windows seems to have zero here, is this correct? */
2182 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2183 pTypeLibImpl
->LibAttr
.lcid
= PRIMARYLANGID(tlbHeader
.lcid
);
2185 pTypeLibImpl
->LibAttr
.lcid
= 0;
2187 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2188 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2189 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2190 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2192 /* name, eventually add to a hash table */
2193 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2196 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2197 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2199 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2202 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2203 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2206 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2209 if(tlbHeader
.CustomDataOffset
>= 0)
2211 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2214 /* fill in typedescriptions */
2215 if(tlbSegDir
.pTypdescTab
.length
> 0)
2217 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2219 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2220 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2223 /* FIXME: add several sanity checks here */
2224 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2225 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2227 /* FIXME: check safearray */
2229 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2231 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2233 else if(td
[0] == VT_CARRAY
)
2235 /* array descr table here */
2236 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2238 else if(td
[0] == VT_USERDEFINED
)
2240 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2242 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2245 /* second time around to fill the array subscript info */
2248 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2249 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2251 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2252 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2255 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2257 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2259 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2261 for(j
= 0; j
<td
[2]; j
++)
2263 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2264 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2265 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2266 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2271 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2272 ERR("didn't find array description data\n");
2277 /* imported type libs */
2278 if(tlbSegDir
.pImpFiles
.offset
>0)
2280 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2281 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2284 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2289 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2290 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2291 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2293 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2294 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2295 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2296 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2299 name
= TLB_Alloc(size
+1);
2300 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2301 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2302 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2303 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2306 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2307 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2309 ppImpLib
= &(*ppImpLib
)->next
;
2314 if(tlbHeader
.nrtypeinfos
>= 0 )
2316 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2317 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2320 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2322 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2324 ITypeInfo_AddRef((ITypeInfo
*) *ppTI
);
2325 ppTI
= &((*ppTI
)->next
);
2326 (pTypeLibImpl
->TypeInfoCount
)++;
2330 TRACE("(%p)\n", pTypeLibImpl
);
2331 return (ITypeLib2
*) pTypeLibImpl
;
2335 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2341 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2342 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2343 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2344 ret
= SysAllocString(nameW
);
2345 HeapFree(GetProcessHeap(), 0, nameW
);
2349 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2355 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2356 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2360 guid
->Data4
[0] = s
>> 8;
2361 guid
->Data4
[1] = s
& 0xff;
2364 for(i
= 0; i
< 6; i
++) {
2365 memcpy(b
, str
+ 24 + 2 * i
, 2);
2366 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2371 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2378 bytelen
= *(WORD
*)ptr
;
2379 if(bytelen
== 0xffff) return 2;
2380 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2381 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2382 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2383 *pBstr
= SysAllocStringLen(nameW
, len
);
2384 HeapFree(GetProcessHeap(), 0, nameW
);
2388 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2393 bytelen
= *(WORD
*)ptr
;
2394 if(bytelen
== 0xffff) return 2;
2395 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2396 memcpy(*str
, ptr
+ 2, bytelen
);
2397 (*str
)[bytelen
] = '\0';
2401 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2403 char *ptr
= pLibBlk
;
2406 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2407 FIXME("libblk magic = %04x\n", w
);
2412 if((w
= *(WORD
*)ptr
) != 0xffff) {
2413 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2418 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2420 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2422 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2425 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2428 pTypeLibImpl
->LibAttr
.lcid
= *(WORD
*)ptr
;
2431 ptr
+= 4; /* skip res12 */
2433 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2436 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2439 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2442 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2443 ptr
+= sizeof(GUID
);
2445 return ptr
- (char*)pLibBlk
;
2448 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2451 TYPEDESC
*pTD
= &pElem
->tdesc
;
2453 /* Handle [in/out] first */
2454 if((*pType
& 0xc000) == 0xc000)
2455 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2456 else if(*pType
& 0x8000)
2457 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2458 else if(*pType
& 0x4000)
2459 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2461 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2464 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2467 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2470 if((*pType
& 0xe00) == 0xe00) {
2472 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2474 pTD
= pTD
->u
.lptdesc
;
2476 switch(*pType
& 0x7f) {
2479 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2481 pTD
= pTD
->u
.lptdesc
;
2484 case VT_USERDEFINED
:
2485 pTD
->vt
= VT_USERDEFINED
;
2486 pTD
->u
.hreftype
= *(++pType
) / 4;
2492 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2495 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2497 pTD
->vt
= VT_CARRAY
;
2498 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2500 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2501 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2502 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2503 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2505 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2511 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2515 pTD
->vt
= VT_SAFEARRAY
;
2516 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2518 pTD
= pTD
->u
.lptdesc
;
2522 pTD
->vt
= *pType
& 0x7f;
2532 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2537 TLBRefType
**ppRefType
;
2539 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2540 FIXME("Ref magic = %x\n", pRef
->magic
);
2543 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2545 ppRefType
= &pTI
->reflist
;
2546 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2548 unsigned int lib_offs
, type_num
;
2550 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2551 sizeof(**ppRefType
));
2553 name
+= SLTG_ReadStringA(name
, &refname
);
2554 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2555 FIXME("Can't sscanf ref\n");
2556 if(lib_offs
!= 0xffff) {
2557 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2560 if((*import
)->offset
== lib_offs
)
2562 import
= &(*import
)->next
;
2565 char fname
[MAX_PATH
+1];
2568 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2570 (*import
)->offset
= lib_offs
;
2571 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2573 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2574 &(*import
)->wVersionMajor
,
2575 &(*import
)->wVersionMinor
,
2576 &(*import
)->lcid
, fname
) != 4) {
2577 FIXME("can't sscanf ref %s\n",
2578 pNameTable
+ lib_offs
+ 40);
2580 len
= strlen(fname
);
2581 if(fname
[len
-1] != '#')
2582 FIXME("fname = %s\n", fname
);
2583 fname
[len
-1] = '\0';
2584 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2586 (*ppRefType
)->pImpTLInfo
= *import
;
2587 } else { /* internal ref */
2588 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2590 (*ppRefType
)->reference
= ref
;
2591 (*ppRefType
)->index
= type_num
;
2593 HeapFree(GetProcessHeap(), 0, refname
);
2594 ppRefType
= &(*ppRefType
)->next
;
2596 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2597 FIXME("End of ref block magic = %x\n", *name
);
2598 dump_TLBRefType(pTI
->reflist
);
2601 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2604 SLTG_ImplInfo
*info
;
2605 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2606 /* I don't really get this structure, usually it's 0x16 bytes
2607 long, but iuser.tlb contains some that are 0x18 bytes long.
2608 That's ok because we can use the next ptr to jump to the next
2609 one. But how do we know the length of the last one? The WORD
2610 at offs 0x8 might be the clue. For now I'm just assuming that
2611 the last one is the regular 0x16 bytes. */
2613 info
= (SLTG_ImplInfo
*)pBlk
;
2615 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2616 sizeof(**ppImplType
));
2617 (*ppImplType
)->hRef
= info
->ref
;
2618 (*ppImplType
)->implflags
= info
->impltypeflags
;
2619 pTI
->TypeAttr
.cImplTypes
++;
2620 ppImplType
= &(*ppImplType
)->next
;
2622 if(info
->next
== 0xffff)
2625 FIXME("Interface inheriting more than one interface\n");
2626 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2628 info
++; /* see comment at top of function */
2632 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2635 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2636 SLTG_MemberHeader
*pMemHeader
;
2637 char *pFirstItem
, *pNextItem
;
2639 if(pTIHeader
->href_table
!= 0xffffffff) {
2640 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2645 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2647 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2649 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2650 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2653 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2657 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2660 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2661 SLTG_MemberHeader
*pMemHeader
;
2662 SLTG_Function
*pFunc
;
2663 char *pFirstItem
, *pNextItem
;
2664 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2667 if(pTIHeader
->href_table
!= 0xffffffff) {
2668 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2672 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2674 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2676 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2677 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2680 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2681 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2686 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2687 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2688 FIXME("func magic = %02x\n", pFunc
->magic
);
2691 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2692 sizeof(**ppFuncDesc
));
2693 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2695 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2696 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2697 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2698 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2699 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2700 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2702 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2703 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2705 if(pFunc
->retnextopt
& 0x80)
2706 pType
= &pFunc
->rettype
;
2708 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2711 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2713 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2714 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2715 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2716 (*ppFuncDesc
)->pParamDesc
=
2717 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2718 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2720 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2722 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2723 char *paramName
= pNameTable
+ *pArg
;
2725 /* If arg type follows then paramName points to the 2nd
2726 letter of the name, else the next WORD is an offset to
2727 the arg type and paramName points to the first letter.
2728 So let's take one char off paramName and see if we're
2729 pointing at an alpha-numeric char. However if *pArg is
2730 0xffff or 0xfffe then the param has no name, the former
2731 meaning that the next WORD is the type, the latter
2732 meaning the the next WORD is an offset to the type. */
2737 else if(*pArg
== 0xfffe) {
2741 else if(!isalnum(*(paramName
-1)))
2746 if(HaveOffs
) { /* the next word is an offset to type */
2747 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2748 SLTG_DoType(pType
, pFirstItem
,
2749 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2754 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2755 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2758 /* Are we an optional param ? */
2759 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2760 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2761 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2764 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2765 TLB_MultiByteToBSTR(paramName
);
2769 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2770 if(pFunc
->next
== 0xffff) break;
2772 pTI
->TypeAttr
.cFuncs
= num
;
2773 dump_TLBFuncDesc(pTI
->funclist
);
2774 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2777 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2780 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2781 SLTG_MemberHeader
*pMemHeader
;
2782 SLTG_RecordItem
*pItem
;
2784 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2789 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2791 pFirstItem
= (char*)(pMemHeader
+ 1);
2792 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2793 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2794 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2795 FIXME("record magic = %02x\n", pItem
->magic
);
2798 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2799 sizeof(**ppVarDesc
));
2800 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2801 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2802 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2803 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2805 if(pItem
->typepos
== 0x02)
2806 pType
= &pItem
->type
;
2807 else if(pItem
->typepos
== 0x00)
2808 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2810 FIXME("typepos = %02x\n", pItem
->typepos
);
2814 SLTG_DoType(pType
, pFirstItem
,
2815 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2817 /* FIXME("helpcontext, helpstring\n"); */
2819 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2821 ppVarDesc
= &((*ppVarDesc
)->next
);
2822 if(pItem
->next
== 0xffff) break;
2824 pTI
->TypeAttr
.cVars
= num
;
2825 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2828 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
2831 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2832 SLTG_MemberHeader
*pMemHeader
;
2833 SLTG_AliasItem
*pItem
;
2836 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2837 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
2840 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2841 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
2842 if (pItem
->vt
== 0xffff) {
2843 if (i
<(pMemHeader
->cbExtra
/4-1))
2844 FIXME("Endmarker too early in process alias data!\n");
2848 FIXME("Chain extends over last entry?\n");
2851 if (pItem
->vt
== VT_USERDEFINED
) {
2852 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
2853 /* guessing here ... */
2854 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
2855 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
2858 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
2859 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
2863 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
2866 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
2869 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2870 SLTG_MemberHeader
*pMemHeader
;
2871 SLTG_AliasItem
*pItem
;
2873 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2874 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
2875 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
2876 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
2877 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
2880 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
2883 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2884 SLTG_MemberHeader
*pMemHeader
;
2885 SLTG_EnumItem
*pItem
;
2887 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2890 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2892 pFirstItem
= (char*)(pMemHeader
+ 1);
2893 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
2894 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2895 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
2896 FIXME("enumitem magic = %04x\n", pItem
->magic
);
2899 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2900 sizeof(**ppVarDesc
));
2901 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2902 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2903 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2905 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2906 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2907 *(INT
*)(pItem
->value
+ pFirstItem
);
2908 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
2909 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2910 /* FIXME("helpcontext, helpstring\n"); */
2912 ppVarDesc
= &((*ppVarDesc
)->next
);
2913 if(pItem
->next
== 0xffff) break;
2915 pTI
->TypeAttr
.cVars
= num
;
2916 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2919 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2920 managable copy of it into this */
2933 } SLTG_InternalOtherTypeInfo
;
2935 /****************************************************************************
2936 * ITypeLib2_Constructor_SLTG
2938 * loading a SLTG typelib from an in-memory image
2940 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
2942 ITypeLibImpl
*pTypeLibImpl
;
2943 SLTG_Header
*pHeader
;
2944 SLTG_BlkEntry
*pBlkEntry
;
2948 LPVOID pBlk
, pFirstBlk
;
2949 SLTG_LibBlk
*pLibBlk
;
2950 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
2951 char *pAfterOTIBlks
= NULL
;
2952 char *pNameTable
, *ptr
;
2955 ITypeInfoImpl
**ppTypeInfoImpl
;
2957 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2959 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2960 if (!pTypeLibImpl
) return NULL
;
2962 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2963 pTypeLibImpl
->ref
= 1;
2968 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
2969 pHeader
->nrOfFileBlks
);
2970 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
2971 FIXME("Header type magic 0x%08lx not supported.\n",
2972 pHeader
->SLTG_magic
);
2976 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2977 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
2979 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2980 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
2982 /* Next we have a magic block */
2983 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
2985 /* Let's see if we're still in sync */
2986 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
2987 sizeof(SLTG_COMPOBJ_MAGIC
))) {
2988 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
2991 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
2992 sizeof(SLTG_DIR_MAGIC
))) {
2993 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
2997 pIndex
= (SLTG_Index
*)(pMagic
+1);
2999 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3001 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3003 /* We'll set up a ptr to the main library block, which is the last one. */
3005 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3006 pBlkEntry
[order
].next
!= 0;
3007 order
= pBlkEntry
[order
].next
- 1, i
++) {
3008 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3012 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3014 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3019 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3021 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3022 sizeof(*pOtherTypeInfoBlks
) *
3023 pTypeLibImpl
->TypeInfoCount
);
3026 ptr
= (char*)pLibBlk
+ len
;
3028 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3032 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3034 w
= *(WORD
*)(ptr
+ 2);
3037 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3039 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3040 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3042 w
= *(WORD
*)(ptr
+ 4 + len
);
3044 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3046 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3048 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3049 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3051 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3052 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3053 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3055 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3057 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3060 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3061 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3062 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3063 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3064 len
+= sizeof(SLTG_OtherTypeInfo
);
3068 pAfterOTIBlks
= ptr
;
3070 /* Skip this WORD and get the next DWORD */
3071 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3073 /* Now add this to pLibBLk look at what we're pointing at and
3074 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3075 dust and we should be pointing at the beginning of the name
3078 pNameTable
= (char*)pLibBlk
+ len
;
3080 switch(*(WORD
*)pNameTable
) {
3087 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3091 pNameTable
+= 0x216;
3095 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3097 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3100 /* Hopefully we now have enough ptrs set up to actually read in
3101 some TypeInfos. It's not clear which order to do them in, so
3102 I'll just follow the links along the BlkEntry chain and read
3103 them in in the order in which they're in the file */
3105 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3107 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3108 pBlkEntry
[order
].next
!= 0;
3109 order
= pBlkEntry
[order
].next
- 1, i
++) {
3111 SLTG_TypeInfoHeader
*pTIHeader
;
3112 SLTG_TypeInfoTail
*pTITail
;
3114 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3115 pOtherTypeInfoBlks
[i
].index_name
)) {
3116 FIXME("Index strings don't match\n");
3121 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3122 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3125 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3126 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3127 (*ppTypeInfoImpl
)->index
= i
;
3128 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3129 pOtherTypeInfoBlks
[i
].name_offs
+
3131 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3132 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3134 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3135 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3136 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3137 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3138 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3140 if((pTIHeader
->typeflags1
& 7) != 2)
3141 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3142 if(pTIHeader
->typeflags3
!= 2)
3143 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3145 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3146 debugstr_w((*ppTypeInfoImpl
)->Name
),
3147 typekind_desc
[pTIHeader
->typekind
],
3148 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3149 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3151 switch(pTIHeader
->typekind
) {
3153 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3157 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3160 case TKIND_INTERFACE
:
3161 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3165 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3169 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3170 if (pTITail
->tdescalias_vt
)
3171 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3174 case TKIND_DISPATCH
:
3175 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3179 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3185 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3186 but we've already set those */
3187 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3188 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3189 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3191 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3213 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3214 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3217 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3218 FIXME("Somehow processed %d TypeInfos\n", i
);
3222 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3223 return (ITypeLib2
*)pTypeLibImpl
;
3226 /* ITypeLib::QueryInterface
3228 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3233 ICOM_THIS( ITypeLibImpl
, iface
);
3235 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3238 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3239 IsEqualIID(riid
,&IID_ITypeLib
)||
3240 IsEqualIID(riid
,&IID_ITypeLib2
))
3247 ITypeLib2_AddRef(iface
);
3248 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3251 TRACE("-- Interface: E_NOINTERFACE\n");
3252 return E_NOINTERFACE
;
3257 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3259 ICOM_THIS( ITypeLibImpl
, iface
);
3261 TRACE("(%p)->ref was %u\n",This
, This
->ref
);
3263 return ++(This
->ref
);
3266 /* ITypeLib::Release
3268 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3270 ICOM_THIS( ITypeLibImpl
, iface
);
3274 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3278 /* remove cache entry */
3279 TRACE("removing from cache list\n");
3280 EnterCriticalSection(&cache_section
);
3281 if (This
->next
) This
->next
->prev
= This
->prev
;
3282 if (This
->prev
) This
->prev
->next
= This
->next
;
3283 else tlb_cache_first
= This
->next
;
3284 LeaveCriticalSection(&cache_section
);
3286 /* FIXME destroy child objects */
3287 TRACE(" destroying ITypeLib(%p)\n",This
);
3291 SysFreeString(This
->Name
);
3295 if (This
->DocString
)
3297 SysFreeString(This
->DocString
);
3298 This
->DocString
= NULL
;
3303 SysFreeString(This
->HelpFile
);
3304 This
->HelpFile
= NULL
;
3307 if (This
->HelpStringDll
)
3309 SysFreeString(This
->HelpStringDll
);
3310 This
->HelpStringDll
= NULL
;
3313 if (This
->pTypeInfo
) /* can be NULL */
3314 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3315 HeapFree(GetProcessHeap(),0,This
);
3322 /* ITypeLib::GetTypeInfoCount
3324 * Returns the number of type descriptions in the type library
3326 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3328 ICOM_THIS( ITypeLibImpl
, iface
);
3329 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3330 return This
->TypeInfoCount
;
3333 /* ITypeLib::GetTypeInfo
3335 * retrieves the specified type description in the library.
3337 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3340 ITypeInfo
**ppTInfo
)
3344 ICOM_THIS( ITypeLibImpl
, iface
);
3345 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3347 TRACE("(%p)->(index=%d) \n", This
, index
);
3349 if (!ppTInfo
) return E_INVALIDARG
;
3351 /* search element n in list */
3352 for(i
=0; i
< index
; i
++)
3354 pTypeInfo
= pTypeInfo
->next
;
3357 TRACE("-- element not found\n");
3358 return TYPE_E_ELEMENTNOTFOUND
;
3362 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3364 ITypeInfo_AddRef(*ppTInfo
);
3365 TRACE("-- found (%p)\n",*ppTInfo
);
3370 /* ITypeLibs::GetTypeInfoType
3372 * Retrieves the type of a type description.
3374 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3379 ICOM_THIS( ITypeLibImpl
, iface
);
3381 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3383 TRACE("(%p) index %d \n",This
, index
);
3385 if(!pTKind
) return E_INVALIDARG
;
3387 /* search element n in list */
3388 for(i
=0; i
< index
; i
++)
3392 TRACE("-- element not found\n");
3393 return TYPE_E_ELEMENTNOTFOUND
;
3395 pTInfo
= pTInfo
->next
;
3398 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3399 TRACE("-- found Type (%d)\n", *pTKind
);
3403 /* ITypeLib::GetTypeInfoOfGuid
3405 * Retrieves the type description that corresponds to the specified GUID.
3408 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3411 ITypeInfo
**ppTInfo
)
3413 ICOM_THIS( ITypeLibImpl
, iface
);
3414 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3416 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3418 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3420 /* search linked list for guid */
3421 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3423 pTypeInfo
= pTypeInfo
->next
;
3427 /* end of list reached */
3428 TRACE("-- element not found\n");
3429 return TYPE_E_ELEMENTNOTFOUND
;
3433 TRACE("-- found (%p, %s)\n",
3435 debugstr_w(pTypeInfo
->Name
));
3437 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3438 ITypeInfo_AddRef(*ppTInfo
);
3442 /* ITypeLib::GetLibAttr
3444 * Retrieves the structure that contains the library's attributes.
3447 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3449 LPTLIBATTR
*ppTLibAttr
)
3451 ICOM_THIS( ITypeLibImpl
, iface
);
3452 TRACE("(%p)\n",This
);
3453 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3454 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3458 /* ITypeLib::GetTypeComp
3460 * Enables a client compiler to bind to a library's types, variables,
3461 * constants, and global functions.
3464 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3466 ITypeComp
**ppTComp
)
3468 ICOM_THIS( ITypeLibImpl
, iface
);
3470 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3471 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3472 ITypeComp_AddRef(*ppTComp
);
3477 /* ITypeLib::GetDocumentation
3479 * Retrieves the library's documentation string, the complete Help file name
3480 * and path, and the context identifier for the library Help topic in the Help
3483 * On a successful return all non-null BSTR pointers will have been set,
3486 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3490 BSTR
*pBstrDocString
,
3491 DWORD
*pdwHelpContext
,
3492 BSTR
*pBstrHelpFile
)
3494 ICOM_THIS( ITypeLibImpl
, iface
);
3496 HRESULT result
= E_INVALIDARG
;
3501 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3503 pBstrName
, pBstrDocString
,
3504 pdwHelpContext
, pBstrHelpFile
);
3508 /* documentation for the typelib */
3512 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3518 if (This
->DocString
)
3519 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3520 else if (This
->Name
)
3521 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3523 *pBstrDocString
= NULL
;
3527 *pdwHelpContext
= This
->dwHelpContext
;
3532 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3534 *pBstrHelpFile
= NULL
;
3541 /* for a typeinfo */
3542 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3544 if(SUCCEEDED(result
))
3546 result
= ITypeInfo_GetDocumentation(pTInfo
,
3550 pdwHelpContext
, pBstrHelpFile
);
3552 ITypeInfo_Release(pTInfo
);
3557 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3559 if (pBstrName
) SysFreeString (*pBstrName
);
3561 return STG_E_INSUFFICIENTMEMORY
;
3566 * Indicates whether a passed-in string contains the name of a type or member
3567 * described in the library.
3570 static HRESULT WINAPI
ITypeLib2_fnIsName(
3576 ICOM_THIS( ITypeLibImpl
, iface
);
3577 ITypeInfoImpl
*pTInfo
;
3578 TLBFuncDesc
*pFInfo
;
3581 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3583 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3587 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3588 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3589 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3590 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3591 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3592 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3593 goto ITypeLib2_fnIsName_exit
;
3595 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3596 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3601 ITypeLib2_fnIsName_exit
:
3602 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3603 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3608 /* ITypeLib::FindName
3610 * Finds occurrences of a type description in a type library. This may be used
3611 * to quickly verify that a name exists in a type library.
3614 static HRESULT WINAPI
ITypeLib2_fnFindName(
3618 ITypeInfo
**ppTInfo
,
3622 ICOM_THIS( ITypeLibImpl
, iface
);
3623 ITypeInfoImpl
*pTInfo
;
3624 TLBFuncDesc
*pFInfo
;
3628 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3630 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3631 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3632 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3633 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3634 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3635 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3636 goto ITypeLib2_fnFindName_exit
;
3638 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3639 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3641 ITypeLib2_fnFindName_exit
:
3642 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3643 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3646 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3647 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3654 /* ITypeLib::ReleaseTLibAttr
3656 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3659 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3661 TLIBATTR
*pTLibAttr
)
3663 ICOM_THIS( ITypeLibImpl
, iface
);
3664 TRACE("freeing (%p)\n",This
);
3665 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3669 /* ITypeLib2::GetCustData
3671 * gets the custom data
3673 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3678 ICOM_THIS( ITypeLibImpl
, iface
);
3679 TLBCustData
*pCData
;
3681 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3683 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3686 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3690 VariantInit( pVarVal
);
3691 VariantCopy( pVarVal
, &pCData
->data
);
3694 return E_INVALIDARG
; /* FIXME: correct? */
3697 /* ITypeLib2::GetLibStatistics
3699 * Returns statistics about a type library that are required for efficient
3700 * sizing of hash tables.
3703 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3705 ULONG
*pcUniqueNames
,
3706 ULONG
*pcchUniqueNames
)
3708 ICOM_THIS( ITypeLibImpl
, iface
);
3710 FIXME("(%p): stub!\n", This
);
3712 if(pcUniqueNames
) *pcUniqueNames
=1;
3713 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3717 /* ITypeLib2::GetDocumentation2
3719 * Retrieves the library's documentation string, the complete Help file name
3720 * and path, the localization context to use, and the context ID for the
3721 * library Help topic in the Help file.
3724 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3728 BSTR
*pbstrHelpString
,
3729 DWORD
*pdwHelpStringContext
,
3730 BSTR
*pbstrHelpStringDll
)
3732 ICOM_THIS( ITypeLibImpl
, iface
);
3736 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3738 /* the help string should be obtained from the helpstringdll,
3739 * using the _DLLGetDocumentation function, based on the supplied
3740 * lcid. Nice to do sometime...
3744 /* documentation for the typelib */
3746 *pbstrHelpString
=SysAllocString(This
->DocString
);
3747 if(pdwHelpStringContext
)
3748 *pdwHelpStringContext
=This
->dwHelpContext
;
3749 if(pbstrHelpStringDll
)
3750 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3756 /* for a typeinfo */
3757 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3759 if(SUCCEEDED(result
))
3761 ITypeInfo2
* pTInfo2
;
3762 result
= ITypeInfo_QueryInterface(pTInfo
,
3764 (LPVOID
*) &pTInfo2
);
3766 if(SUCCEEDED(result
))
3768 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3772 pdwHelpStringContext
,
3773 pbstrHelpStringDll
);
3775 ITypeInfo2_Release(pTInfo2
);
3778 ITypeInfo_Release(pTInfo
);
3784 /* ITypeLib2::GetAllCustData
3786 * Gets all custom data items for the library.
3789 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3791 CUSTDATA
*pCustData
)
3793 ICOM_THIS( ITypeLibImpl
, iface
);
3794 TLBCustData
*pCData
;
3796 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3797 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3798 if(pCustData
->prgCustData
){
3799 pCustData
->cCustData
=This
->ctCustData
;
3800 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3801 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3802 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3805 ERR(" OUT OF MEMORY! \n");
3806 return E_OUTOFMEMORY
;
3811 static ICOM_VTABLE(ITypeLib2
) tlbvt
= {
3812 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3813 ITypeLib2_fnQueryInterface
,
3815 ITypeLib2_fnRelease
,
3816 ITypeLib2_fnGetTypeInfoCount
,
3817 ITypeLib2_fnGetTypeInfo
,
3818 ITypeLib2_fnGetTypeInfoType
,
3819 ITypeLib2_fnGetTypeInfoOfGuid
,
3820 ITypeLib2_fnGetLibAttr
,
3821 ITypeLib2_fnGetTypeComp
,
3822 ITypeLib2_fnGetDocumentation
,
3824 ITypeLib2_fnFindName
,
3825 ITypeLib2_fnReleaseTLibAttr
,
3827 ITypeLib2_fnGetCustData
,
3828 ITypeLib2_fnGetLibStatistics
,
3829 ITypeLib2_fnGetDocumentation2
,
3830 ITypeLib2_fnGetAllCustData
3834 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
3836 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3838 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
3841 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
3843 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3845 return ITypeInfo_AddRef((ITypeInfo
*)This
);
3848 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
3850 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3852 return ITypeInfo_Release((ITypeInfo
*)This
);
3855 static HRESULT WINAPI
ITypeLibComp_fnBind(
3858 unsigned long lHash
,
3859 unsigned short wFlags
,
3860 ITypeInfo
** ppTInfo
,
3861 DESCKIND
* pDescKind
,
3864 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
3868 static HRESULT WINAPI
ITypeLibComp_fnBindType(
3871 unsigned long lHash
,
3872 ITypeInfo
** ppTInfo
,
3873 ITypeComp
** ppTComp
)
3875 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
3879 static ICOM_VTABLE(ITypeComp
) tlbtcvt
=
3881 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3883 ITypeLibComp_fnQueryInterface
,
3884 ITypeLibComp_fnAddRef
,
3885 ITypeLibComp_fnRelease
,
3887 ITypeLibComp_fnBind
,
3888 ITypeLibComp_fnBindType
3891 /*================== ITypeInfo(2) Methods ===================================*/
3892 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
3894 ITypeInfoImpl
* pTypeInfoImpl
;
3896 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
3899 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
3900 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
3901 pTypeInfoImpl
->ref
=1;
3903 TRACE("(%p)\n", pTypeInfoImpl
);
3904 return (ITypeInfo2
*) pTypeInfoImpl
;
3907 /* ITypeInfo::QueryInterface
3909 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
3914 ICOM_THIS( ITypeLibImpl
, iface
);
3916 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3919 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3920 IsEqualIID(riid
,&IID_ITypeInfo
)||
3921 IsEqualIID(riid
,&IID_ITypeInfo2
))
3925 ITypeInfo_AddRef(iface
);
3926 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3929 TRACE("-- Interface: E_NOINTERFACE\n");
3930 return E_NOINTERFACE
;
3933 /* ITypeInfo::AddRef
3935 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
3937 ICOM_THIS( ITypeInfoImpl
, iface
);
3941 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3945 /* ITypeInfo::Release
3947 static ULONG WINAPI
ITypeInfo_fnRelease( ITypeInfo2
*iface
)
3949 ICOM_THIS( ITypeInfoImpl
, iface
);
3953 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3957 FIXME("destroy child objects\n");
3959 TRACE("destroying ITypeInfo(%p)\n",This
);
3962 SysFreeString(This
->Name
);
3966 if (This
->DocString
)
3968 SysFreeString(This
->DocString
);
3969 This
->DocString
= 0;
3974 ITypeInfo_Release((ITypeInfo
*)This
->next
);
3977 HeapFree(GetProcessHeap(),0,This
);
3983 /* ITypeInfo::GetTypeAttr
3985 * Retrieves a TYPEATTR structure that contains the attributes of the type
3989 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
3990 LPTYPEATTR
*ppTypeAttr
)
3992 ICOM_THIS( ITypeInfoImpl
, iface
);
3993 TRACE("(%p)\n",This
);
3994 /* FIXME: must do a copy here */
3995 *ppTypeAttr
=&This
->TypeAttr
;
3999 /* ITypeInfo::GetTypeComp
4001 * Retrieves the ITypeComp interface for the type description, which enables a
4002 * client compiler to bind to the type description's members.
4005 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4006 ITypeComp
* *ppTComp
)
4008 ICOM_THIS( ITypeInfoImpl
, iface
);
4010 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4012 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4013 ITypeComp_AddRef(*ppTComp
);
4017 /* ITypeInfo::GetFuncDesc
4019 * Retrieves the FUNCDESC structure that contains information about a
4020 * specified function.
4023 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4024 LPFUNCDESC
*ppFuncDesc
)
4026 ICOM_THIS( ITypeInfoImpl
, iface
);
4028 TLBFuncDesc
* pFDesc
;
4029 TRACE("(%p) index %d\n", This
, index
);
4030 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4033 /* FIXME: must do a copy here */
4034 *ppFuncDesc
=&pFDesc
->funcdesc
;
4037 return E_INVALIDARG
;
4040 /* ITypeInfo::GetVarDesc
4042 * Retrieves a VARDESC structure that describes the specified variable.
4045 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4046 LPVARDESC
*ppVarDesc
)
4048 ICOM_THIS( ITypeInfoImpl
, iface
);
4050 TLBVarDesc
* pVDesc
;
4051 TRACE("(%p) index %d\n", This
, index
);
4052 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4055 /* FIXME: must do a copy here */
4056 *ppVarDesc
=&pVDesc
->vardesc
;
4059 return E_INVALIDARG
;
4062 /* ITypeInfo_GetNames
4064 * Retrieves the variable with the specified member ID (or the name of the
4065 * property or method and its parameters) that correspond to the specified
4068 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4069 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4071 ICOM_THIS( ITypeInfoImpl
, iface
);
4072 TLBFuncDesc
* pFDesc
;
4073 TLBVarDesc
* pVDesc
;
4075 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4076 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4079 /* function found, now return function and parameter names */
4080 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4083 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4085 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4091 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4094 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4099 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
)
4101 /* recursive search */
4104 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4106 if(SUCCEEDED(result
))
4108 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4109 ITypeInfo_Release(pTInfo
);
4112 WARN("Could not search inherited interface!\n");
4116 WARN("no names found\n");
4119 return TYPE_E_ELEMENTNOTFOUND
;
4126 /* ITypeInfo::GetRefTypeOfImplType
4128 * If a type description describes a COM class, it retrieves the type
4129 * description of the implemented interface types. For an interface,
4130 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4134 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4139 ICOM_THIS( ITypeInfoImpl
, iface
);
4141 TLBImplType
*pImpl
= This
->impltypelist
;
4143 TRACE("(%p) index %d\n", This
, index
);
4144 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4148 /* only valid on dual interfaces;
4149 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4151 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4153 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4154 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4160 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4161 *pRefType
= pImpl
->hRef
;
4166 /* get element n from linked list */
4167 for(i
=0; pImpl
&& i
<index
; i
++)
4169 pImpl
= pImpl
->next
;
4172 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4174 *pRefType
= pImpl
->hRef
;
4176 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4183 /* ITypeInfo::GetImplTypeFlags
4185 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4186 * or base interface in a type description.
4188 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4189 UINT index
, INT
*pImplTypeFlags
)
4191 ICOM_THIS( ITypeInfoImpl
, iface
);
4195 TRACE("(%p) index %d\n", This
, index
);
4196 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4197 i
++, pImpl
=pImpl
->next
)
4199 if(i
==index
&& pImpl
){
4200 *pImplTypeFlags
=pImpl
->implflags
;
4204 return TYPE_E_ELEMENTNOTFOUND
;
4208 * Maps between member names and member IDs, and parameter names and
4211 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4212 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4214 ICOM_THIS( ITypeInfoImpl
, iface
);
4215 TLBFuncDesc
* pFDesc
;
4216 TLBVarDesc
* pVDesc
;
4219 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4221 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4223 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4224 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4225 for(i
=1; i
< cNames
; i
++){
4226 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4227 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4229 if( j
<pFDesc
->funcdesc
.cParams
)
4232 ret
=DISP_E_UNKNOWNNAME
;
4237 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4238 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4239 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4243 /* not found, see if this is and interface with an inheritance */
4244 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&&
4245 This
->TypeAttr
.cImplTypes
){
4246 /* recursive search */
4248 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4249 This
->impltypelist
->hRef
, &pTInfo
);
4251 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4252 ITypeInfo_Release(pTInfo
);
4255 WARN("Could not search inherited interface!\n");
4257 WARN("no names found\n");
4258 return DISP_E_UNKNOWNNAME
;
4261 /* ITypeInfo::Invoke
4263 * Invokes a method, or accesses a property of an object, that implements the
4264 * interface described by the type description.
4267 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4270 if (TRACE_ON(ole
)) {
4272 TRACE("Calling %p(",func
);
4273 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4285 res
= func(args
[0]);
4288 res
= func(args
[0],args
[1]);
4291 res
= func(args
[0],args
[1],args
[2]);
4294 res
= func(args
[0],args
[1],args
[2],args
[3]);
4297 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4300 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4303 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4306 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4309 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4312 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4318 FIXME("unsupported calling convention %d\n",callconv
);
4322 TRACE("returns %08lx\n",res
);
4326 extern int const _argsize(DWORD vt
);
4328 /****************************************************************************
4329 * Helper functions for Dispcall / Invoke, which copies one variant
4330 * with target type onto the argument stack.
4333 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4334 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4336 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4340 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4341 memcpy(argpos
,&arg
,sizeof(void*));
4345 if (V_VT(arg
) == vt
) {
4346 memcpy(argpos
, &V_UNION(arg
,lVal
), arglen
);
4350 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4351 memcpy(argpos
, &V_UNION(arg
,parray
), sizeof(SAFEARRAY
*));
4355 if (vt
== VT_VARIANT
) {
4356 memcpy(argpos
, arg
, arglen
);
4359 /* Deref BYREF vars if there is need */
4360 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4361 memcpy(argpos
,(void*)V_UNION(arg
,lVal
), arglen
);
4364 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4365 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4366 memcpy(argpos
,&V_UNION(arg
,lVal
), arglen
);
4369 if ((vt
== VT_PTR
) && tdesc
)
4370 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4372 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4377 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4379 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing from vt 0x%x. Copying 4 byte.\n",tdesc
->u
.hreftype
,V_VT(arg
));
4380 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4383 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4384 switch (tattr
->typekind
) {
4386 switch ( V_VT( arg
) ) {
4388 *argpos
= V_UNION(arg
,iVal
);
4391 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4394 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4399 tdesc
= &(tattr
->tdescAlias
);
4400 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4401 ITypeInfo_Release(tinfo2
);
4404 case TKIND_INTERFACE
:
4405 if (V_VT(arg
) == VT_DISPATCH
) {
4407 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4408 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4411 hres
=IUnknown_QueryInterface(V_UNION(arg
,pdispVal
),&IID_IDispatch
,(LPVOID
*)&disp
);
4412 if (SUCCEEDED(hres
)) {
4413 memcpy(argpos
,&disp
,4);
4414 IUnknown_Release(V_UNION(arg
,pdispVal
));
4417 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4420 if (V_VT(arg
) == VT_UNKNOWN
) {
4421 memcpy(argpos
, &V_UNION(arg
,punkVal
), 4);
4424 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4426 case TKIND_DISPATCH
:
4427 if (V_VT(arg
) == VT_DISPATCH
) {
4428 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4431 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4434 FIXME("TKIND_RECORD unhandled.\n");
4437 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4445 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4446 memcpy(argpos
,&V_UNION(&va
,lVal
), arglen
);
4447 FIXME("Should not use VariantChangeType here. (conversion from 0x%x -> 0x%x)\n",
4452 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4456 /***********************************************************************
4457 * DispCallFunc (OLEAUT32.@)
4461 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4462 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4464 int i
, argsize
, argspos
;
4468 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4469 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4471 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4472 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4474 for (i
=0;i
<cActuals
;i
++) {
4475 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4476 dump_Variant(prgpvarg
[i
]);
4477 argsize
+= _argsize(prgvt
[i
]);
4479 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4480 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4482 for (i
=0;i
<cActuals
;i
++) {
4483 VARIANT
*arg
= prgpvarg
[i
];
4484 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4485 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4486 argspos
+= _argsize(prgvt
[i
]);
4489 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4491 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4496 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4497 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4498 FIXME("Method returned %lx\n",hres
);
4500 HeapFree(GetProcessHeap(),0,args
);
4504 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4509 DISPPARAMS
*pDispParams
,
4510 VARIANT
*pVarResult
,
4511 EXCEPINFO
*pExcepInfo
,
4514 ICOM_THIS( ITypeInfoImpl
, iface
);
4515 TLBFuncDesc
* pFDesc
;
4516 TLBVarDesc
* pVDesc
;
4520 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4521 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4523 dump_DispParms(pDispParams
);
4525 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4526 if (pFDesc
->funcdesc
.memid
== memid
) {
4527 if (pFDesc
->funcdesc
.invkind
& dwFlags
)
4532 if (TRACE_ON(typelib
)) dump_TLBFuncDescOne(pFDesc
);
4533 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4534 switch (pFDesc
->funcdesc
.funckind
) {
4535 case FUNC_PUREVIRTUAL
:
4536 case FUNC_VIRTUAL
: {
4538 int numargs
, numargs2
, argspos
, args2pos
;
4539 DWORD
*args
, *args2
;
4542 numargs
= 1; numargs2
= 0;
4543 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4544 if (i
<pDispParams
->cArgs
)
4545 numargs
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4547 numargs
+= 1; /* sizeof(lpvoid) */
4548 numargs2
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4552 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4553 args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4555 args
[0] = (DWORD
)pIUnk
;
4556 argspos
= 1; args2pos
= 0;
4557 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4558 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4559 if (i
<pDispParams
->cArgs
) {
4560 VARIANT
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1];
4561 TYPEDESC
*tdesc
= &pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
;
4562 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4563 if (FAILED(hres
)) return hres
;
4566 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
4567 if (tdesc
->vt
!= VT_PTR
)
4568 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4569 /*FIXME: give pointers for the rest, so propertyget works*/
4570 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4572 /* If pointer to variant, pass reference it. */
4573 if ((tdesc
->vt
== VT_PTR
) &&
4574 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4577 args
[argspos
]= (DWORD
)pVarResult
;
4582 if (pFDesc
->funcdesc
.cParamsOpt
)
4583 FIXME("Does not support optional parameters (%d)\n",
4584 pFDesc
->funcdesc
.cParamsOpt
4587 res
= _invoke((*(FARPROC
**)pIUnk
)[pFDesc
->funcdesc
.oVft
/4],
4588 pFDesc
->funcdesc
.callconv
,
4592 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4594 for (i
=0;i
<pFDesc
->funcdesc
.cParams
-pDispParams
->cArgs
;i
++) {
4595 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4596 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
+pDispParams
->cArgs
].tdesc
);
4598 i4_tdesc
.vt
= VT_I4
;
4600 /* If we are a pointer to a variant, we are done already */
4601 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4604 VariantInit(pVarResult
);
4605 memcpy(&V_UNION(pVarResult
,intVal
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4607 if (tdesc
->vt
== VT_PTR
)
4608 tdesc
= tdesc
->u
.lptdesc
;
4609 if (tdesc
->vt
== VT_USERDEFINED
) {
4613 hres
= ITypeInfo_GetRefTypeInfo(iface
,tdesc
->u
.hreftype
,&tinfo2
);
4615 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc
->u
.hreftype
);
4618 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4619 switch (tattr
->typekind
) {
4621 /* force the return type to be VT_I4 */
4625 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr
->tdescAlias
.vt
);
4626 tdesc
= &(tattr
->tdescAlias
);
4629 case TKIND_INTERFACE
:
4630 FIXME("TKIND_INTERFACE unhandled.\n");
4632 case TKIND_DISPATCH
:
4633 FIXME("TKIND_DISPATCH unhandled.\n");
4636 FIXME("TKIND_RECORD unhandled.\n");
4639 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4642 ITypeInfo_Release(tinfo2
);
4644 V_VT(pVarResult
) = tdesc
->vt
;
4646 /* HACK: VB5 likes this.
4647 * I do not know why. There is 1 example in MSDN which uses
4648 * this which appears broken (mixes int vals and
4651 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4652 V_VT(pVarResult
) = VT_DISPATCH
;
4653 TRACE("storing into variant:\n");
4654 dump_Variant(pVarResult
);
4658 HeapFree(GetProcessHeap(),0,args2
);
4659 HeapFree(GetProcessHeap(),0,args
);
4662 case FUNC_DISPATCH
: {
4666 hr
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4668 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4671 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4672 hr
= IDispatch_Invoke(
4673 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4674 pVarResult
,pExcepInfo
,pArgErr
4677 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr
);
4678 IDispatch_Release(disp
);
4682 FIXME("Unknown function invocation type %d\n",pFDesc
->funcdesc
.funckind
);
4686 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4687 if (pVDesc
->vardesc
.memid
== memid
) {
4688 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR
)pVDesc
->Name
)));
4689 dump_TLBVarDesc(pVDesc
);
4694 /* not found, look for it in inherited interfaces */
4695 if (This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
) {
4696 /* recursive search */
4699 hr
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
4701 hr
=ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4702 ITypeInfo_Release(pTInfo
);
4705 WARN("Could not search inherited interface!\n");
4707 ERR("did not find member id %d, flags %d!\n", (int)memid
, dwFlags
);
4708 return DISP_E_MEMBERNOTFOUND
;
4711 /* ITypeInfo::GetDocumentation
4713 * Retrieves the documentation string, the complete Help file name and path,
4714 * and the context ID for the Help topic for a specified type description.
4716 * (Can be tested by the Visual Basic Editor in Word for instance.)
4718 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4719 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4720 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4722 ICOM_THIS( ITypeInfoImpl
, iface
);
4723 TLBFuncDesc
* pFDesc
;
4724 TLBVarDesc
* pVDesc
;
4725 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4726 " HelpContext(%p) HelpFile(%p)\n",
4727 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4728 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4730 *pBstrName
=SysAllocString(This
->Name
);
4732 *pBstrDocString
=SysAllocString(This
->DocString
);
4734 *pdwHelpContext
=This
->dwHelpContext
;
4736 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4738 }else {/* for a member */
4739 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4740 if(pFDesc
->funcdesc
.memid
==memid
){
4742 *pBstrName
= SysAllocString(pFDesc
->Name
);
4744 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4746 *pdwHelpContext
=pFDesc
->helpcontext
;
4749 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4750 if(pVDesc
->vardesc
.memid
==memid
){
4752 *pBstrName
= SysAllocString(pVDesc
->Name
);
4754 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
4756 *pdwHelpContext
=pVDesc
->HelpContext
;
4760 return TYPE_E_ELEMENTNOTFOUND
;
4763 /* ITypeInfo::GetDllEntry
4765 * Retrieves a description or specification of an entry point for a function
4768 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
4769 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
4772 ICOM_THIS( ITypeInfoImpl
, iface
);
4773 TLBFuncDesc
*pFDesc
;
4775 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
4777 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4778 if(pFDesc
->funcdesc
.memid
==memid
){
4779 dump_TypeInfo(This
);
4780 dump_TLBFuncDescOne(pFDesc
);
4782 /* FIXME: This is wrong, but how do you find that out? */
4784 const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4785 *pBstrDllName
= SysAllocString(oleaut32W
);
4788 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
4790 *pBstrName
= SysAllocString(pFDesc
->Entry
);
4798 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
4804 /* ITypeInfo::GetRefTypeInfo
4806 * If a type description references other type descriptions, it retrieves
4807 * the referenced type descriptions.
4809 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
4812 ITypeInfo
**ppTInfo
)
4814 ICOM_THIS( ITypeInfoImpl
, iface
);
4815 HRESULT result
= E_FAIL
;
4818 if (hRefType
== -1 &&
4819 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
4820 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
4822 /* when we meet a DUAL dispinterface, we must create the interface
4825 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
4828 /* the interface version contains the same information as the dispinterface
4829 * copy the contents of the structs.
4831 *pTypeInfoImpl
= *This
;
4832 pTypeInfoImpl
->ref
= 1;
4834 /* change the type to interface */
4835 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
4837 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
4839 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
4844 TLBRefType
*pRefType
;
4845 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
4846 if(pRefType
->reference
== hRefType
)
4850 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
4851 if(pRefType
&& hRefType
!= -1) {
4852 ITypeLib
*pTLib
= NULL
;
4854 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
4856 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
4858 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
4859 TRACE("typeinfo in imported typelib that is already loaded\n");
4860 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
4861 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
4864 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4865 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
4866 pRefType
->pImpTLInfo
->wVersionMajor
,
4867 pRefType
->pImpTLInfo
->wVersionMinor
,
4868 pRefType
->pImpTLInfo
->lcid
,
4871 if(!SUCCEEDED(result
)) {
4872 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
4873 result
=LoadTypeLib(libnam
, &pTLib
);
4874 SysFreeString(libnam
);
4876 if(SUCCEEDED(result
)) {
4877 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
4878 ITypeLib2_AddRef(pTLib
);
4882 if(SUCCEEDED(result
)) {
4883 if(pRefType
->index
== TLB_REF_USE_GUID
)
4884 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
4888 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
4892 ITypeLib2_Release(pTLib
);
4896 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
4897 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
4901 /* ITypeInfo::AddressOfMember
4903 * Retrieves the addresses of static functions or variables, such as those
4906 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
4907 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
4909 ICOM_THIS( ITypeInfoImpl
, iface
);
4910 FIXME("(%p) stub!\n", This
);
4914 /* ITypeInfo::CreateInstance
4916 * Creates a new instance of a type that describes a component object class
4919 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
4920 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
4922 ICOM_THIS( ITypeInfoImpl
, iface
);
4923 FIXME("(%p) stub!\n", This
);
4927 /* ITypeInfo::GetMops
4929 * Retrieves marshalling information.
4931 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
4934 ICOM_THIS( ITypeInfoImpl
, iface
);
4935 FIXME("(%p) stub!\n", This
);
4939 /* ITypeInfo::GetContainingTypeLib
4941 * Retrieves the containing type library and the index of the type description
4942 * within that type library.
4944 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
4945 ITypeLib
* *ppTLib
, UINT
*pIndex
)
4947 ICOM_THIS( ITypeInfoImpl
, iface
);
4949 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4951 *pIndex
=This
->index
;
4952 TRACE("returning pIndex=%d\n", *pIndex
);
4956 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
4957 ITypeLib2_AddRef(*ppTLib
);
4958 TRACE("returning ppTLib=%p\n", *ppTLib
);
4964 /* ITypeInfo::ReleaseTypeAttr
4966 * Releases a TYPEATTR previously returned by GetTypeAttr.
4969 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
4970 TYPEATTR
* pTypeAttr
)
4972 ICOM_THIS( ITypeInfoImpl
, iface
);
4973 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
4976 /* ITypeInfo::ReleaseFuncDesc
4978 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4980 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
4982 FUNCDESC
*pFuncDesc
)
4984 ICOM_THIS( ITypeInfoImpl
, iface
);
4985 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
4988 /* ITypeInfo::ReleaseVarDesc
4990 * Releases a VARDESC previously returned by GetVarDesc.
4992 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
4995 ICOM_THIS( ITypeInfoImpl
, iface
);
4996 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
4999 /* ITypeInfo2::GetTypeKind
5001 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5004 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5005 TYPEKIND
*pTypeKind
)
5007 ICOM_THIS( ITypeInfoImpl
, iface
);
5008 *pTypeKind
=This
->TypeAttr
.typekind
;
5009 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5013 /* ITypeInfo2::GetTypeFlags
5015 * Returns the type flags without any allocations. This returns a DWORD type
5016 * flag, which expands the type flags without growing the TYPEATTR (type
5020 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5022 ICOM_THIS( ITypeInfoImpl
, iface
);
5023 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5024 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5028 /* ITypeInfo2::GetFuncIndexOfMemId
5029 * Binds to a specific member based on a known DISPID, where the member name
5030 * is not known (for example, when binding to a default member).
5033 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5034 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5036 ICOM_THIS( ITypeInfoImpl
, iface
);
5037 TLBFuncDesc
*pFuncInfo
;
5040 /* FIXME: should check for invKind??? */
5041 for(i
=0, pFuncInfo
=This
->funclist
;pFuncInfo
&&
5042 memid
!= pFuncInfo
->funcdesc
.memid
; i
++, pFuncInfo
=pFuncInfo
->next
);
5048 result
=E_INVALIDARG
;
5050 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5051 memid
, invKind
, SUCCEEDED(result
)? "SUCCES":"FAILED");
5055 /* TypeInfo2::GetVarIndexOfMemId
5057 * Binds to a specific member based on a known DISPID, where the member name
5058 * is not known (for example, when binding to a default member).
5061 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5062 MEMBERID memid
, UINT
*pVarIndex
)
5064 ICOM_THIS( ITypeInfoImpl
, iface
);
5065 TLBVarDesc
*pVarInfo
;
5068 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5069 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5076 result
=E_INVALIDARG
;
5078 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5079 memid
, SUCCEEDED(result
)? "SUCCES":"FAILED");
5083 /* ITypeInfo2::GetCustData
5085 * Gets the custom data
5087 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5092 ICOM_THIS( ITypeInfoImpl
, iface
);
5093 TLBCustData
*pCData
;
5095 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5096 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5098 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5102 VariantInit( pVarVal
);
5103 VariantCopy( pVarVal
, &pCData
->data
);
5106 return E_INVALIDARG
; /* FIXME: correct? */
5109 /* ITypeInfo2::GetFuncCustData
5111 * Gets the custom data
5113 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5119 ICOM_THIS( ITypeInfoImpl
, iface
);
5120 TLBCustData
*pCData
=NULL
;
5121 TLBFuncDesc
* pFDesc
;
5123 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5124 pFDesc
=pFDesc
->next
);
5127 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5128 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5130 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5133 VariantInit( pVarVal
);
5134 VariantCopy( pVarVal
, &pCData
->data
);
5137 return E_INVALIDARG
; /* FIXME: correct? */
5140 /* ITypeInfo2::GetParamCustData
5142 * Gets the custom data
5144 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5151 ICOM_THIS( ITypeInfoImpl
, iface
);
5152 TLBCustData
*pCData
=NULL
;
5153 TLBFuncDesc
* pFDesc
;
5156 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5158 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5159 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5160 pCData
= pCData
->next
)
5161 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5163 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5167 VariantInit( pVarVal
);
5168 VariantCopy( pVarVal
, &pCData
->data
);
5171 return E_INVALIDARG
; /* FIXME: correct? */
5174 /* ITypeInfo2::GetVarCustData
5176 * Gets the custom data
5178 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5184 ICOM_THIS( ITypeInfoImpl
, iface
);
5185 TLBCustData
*pCData
=NULL
;
5186 TLBVarDesc
* pVDesc
;
5189 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5193 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5195 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5199 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5203 VariantInit( pVarVal
);
5204 VariantCopy( pVarVal
, &pCData
->data
);
5207 return E_INVALIDARG
; /* FIXME: correct? */
5210 /* ITypeInfo2::GetImplCustData
5212 * Gets the custom data
5214 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5220 ICOM_THIS( ITypeInfoImpl
, iface
);
5221 TLBCustData
*pCData
=NULL
;
5222 TLBImplType
* pRDesc
;
5225 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5229 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5231 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5235 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5239 VariantInit( pVarVal
);
5240 VariantCopy( pVarVal
, &pCData
->data
);
5243 return E_INVALIDARG
; /* FIXME: correct? */
5246 /* ITypeInfo2::GetDocumentation2
5248 * Retrieves the documentation string, the complete Help file name and path,
5249 * the localization context to use, and the context ID for the library Help
5250 * topic in the Help file.
5253 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5257 BSTR
*pbstrHelpString
,
5258 DWORD
*pdwHelpStringContext
,
5259 BSTR
*pbstrHelpStringDll
)
5261 ICOM_THIS( ITypeInfoImpl
, iface
);
5262 TLBFuncDesc
* pFDesc
;
5263 TLBVarDesc
* pVDesc
;
5264 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5265 "HelpStringContext(%p) HelpStringDll(%p)\n",
5266 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5267 pbstrHelpStringDll
);
5268 /* the help string should be obtained from the helpstringdll,
5269 * using the _DLLGetDocumentation function, based on the supplied
5270 * lcid. Nice to do sometime...
5272 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5274 *pbstrHelpString
=SysAllocString(This
->Name
);
5275 if(pdwHelpStringContext
)
5276 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5277 if(pbstrHelpStringDll
)
5278 *pbstrHelpStringDll
=
5279 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5281 }else {/* for a member */
5282 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5283 if(pFDesc
->funcdesc
.memid
==memid
){
5285 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5286 if(pdwHelpStringContext
)
5287 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5288 if(pbstrHelpStringDll
)
5289 *pbstrHelpStringDll
=
5290 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5293 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5294 if(pVDesc
->vardesc
.memid
==memid
){
5296 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5297 if(pdwHelpStringContext
)
5298 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5299 if(pbstrHelpStringDll
)
5300 *pbstrHelpStringDll
=
5301 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5305 return TYPE_E_ELEMENTNOTFOUND
;
5308 /* ITypeInfo2::GetAllCustData
5310 * Gets all custom data items for the Type info.
5313 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5315 CUSTDATA
*pCustData
)
5317 ICOM_THIS( ITypeInfoImpl
, iface
);
5318 TLBCustData
*pCData
;
5321 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5323 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5324 if(pCustData
->prgCustData
){
5325 pCustData
->cCustData
=This
->ctCustData
;
5326 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5327 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5328 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5331 ERR(" OUT OF MEMORY! \n");
5332 return E_OUTOFMEMORY
;
5337 /* ITypeInfo2::GetAllFuncCustData
5339 * Gets all custom data items for the specified Function
5342 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5345 CUSTDATA
*pCustData
)
5347 ICOM_THIS( ITypeInfoImpl
, iface
);
5348 TLBCustData
*pCData
;
5349 TLBFuncDesc
* pFDesc
;
5351 TRACE("(%p) index %d\n", This
, index
);
5352 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5353 pFDesc
=pFDesc
->next
)
5356 pCustData
->prgCustData
=
5357 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5358 if(pCustData
->prgCustData
){
5359 pCustData
->cCustData
=pFDesc
->ctCustData
;
5360 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5361 pCData
= pCData
->next
){
5362 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5363 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5367 ERR(" OUT OF MEMORY! \n");
5368 return E_OUTOFMEMORY
;
5372 return TYPE_E_ELEMENTNOTFOUND
;
5375 /* ITypeInfo2::GetAllParamCustData
5377 * Gets all custom data items for the Functions
5380 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5381 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5383 ICOM_THIS( ITypeInfoImpl
, iface
);
5384 TLBCustData
*pCData
=NULL
;
5385 TLBFuncDesc
* pFDesc
;
5387 TRACE("(%p) index %d\n", This
, indexFunc
);
5388 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5389 pFDesc
=pFDesc
->next
)
5391 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5392 pCustData
->prgCustData
=
5393 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5394 sizeof(CUSTDATAITEM
));
5395 if(pCustData
->prgCustData
){
5396 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5397 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5398 pCData
; i
++, pCData
= pCData
->next
){
5399 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5400 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5404 ERR(" OUT OF MEMORY! \n");
5405 return E_OUTOFMEMORY
;
5409 return TYPE_E_ELEMENTNOTFOUND
;
5412 /* ITypeInfo2::GetAllVarCustData
5414 * Gets all custom data items for the specified Variable
5417 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5418 UINT index
, CUSTDATA
*pCustData
)
5420 ICOM_THIS( ITypeInfoImpl
, iface
);
5421 TLBCustData
*pCData
;
5422 TLBVarDesc
* pVDesc
;
5424 TRACE("(%p) index %d\n", This
, index
);
5425 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5426 pVDesc
=pVDesc
->next
)
5429 pCustData
->prgCustData
=
5430 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5431 if(pCustData
->prgCustData
){
5432 pCustData
->cCustData
=pVDesc
->ctCustData
;
5433 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5434 pCData
= pCData
->next
){
5435 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5436 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5440 ERR(" OUT OF MEMORY! \n");
5441 return E_OUTOFMEMORY
;
5445 return TYPE_E_ELEMENTNOTFOUND
;
5448 /* ITypeInfo2::GetAllImplCustData
5450 * Gets all custom data items for the specified implementation type
5453 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5456 CUSTDATA
*pCustData
)
5458 ICOM_THIS( ITypeInfoImpl
, iface
);
5459 TLBCustData
*pCData
;
5460 TLBImplType
* pRDesc
;
5462 TRACE("(%p) index %d\n", This
, index
);
5463 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5464 pRDesc
=pRDesc
->next
)
5467 pCustData
->prgCustData
=
5468 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5469 if(pCustData
->prgCustData
){
5470 pCustData
->cCustData
=pRDesc
->ctCustData
;
5471 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5472 pCData
= pCData
->next
){
5473 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5474 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5478 ERR(" OUT OF MEMORY! \n");
5479 return E_OUTOFMEMORY
;
5483 return TYPE_E_ELEMENTNOTFOUND
;
5486 static ICOM_VTABLE(ITypeInfo2
) tinfvt
=
5488 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5490 ITypeInfo_fnQueryInterface
,
5492 ITypeInfo_fnRelease
,
5494 ITypeInfo_fnGetTypeAttr
,
5495 ITypeInfo_fnGetTypeComp
,
5496 ITypeInfo_fnGetFuncDesc
,
5497 ITypeInfo_fnGetVarDesc
,
5498 ITypeInfo_fnGetNames
,
5499 ITypeInfo_fnGetRefTypeOfImplType
,
5500 ITypeInfo_fnGetImplTypeFlags
,
5501 ITypeInfo_fnGetIDsOfNames
,
5503 ITypeInfo_fnGetDocumentation
,
5504 ITypeInfo_fnGetDllEntry
,
5505 ITypeInfo_fnGetRefTypeInfo
,
5506 ITypeInfo_fnAddressOfMember
,
5507 ITypeInfo_fnCreateInstance
,
5508 ITypeInfo_fnGetMops
,
5509 ITypeInfo_fnGetContainingTypeLib
,
5510 ITypeInfo_fnReleaseTypeAttr
,
5511 ITypeInfo_fnReleaseFuncDesc
,
5512 ITypeInfo_fnReleaseVarDesc
,
5514 ITypeInfo2_fnGetTypeKind
,
5515 ITypeInfo2_fnGetTypeFlags
,
5516 ITypeInfo2_fnGetFuncIndexOfMemId
,
5517 ITypeInfo2_fnGetVarIndexOfMemId
,
5518 ITypeInfo2_fnGetCustData
,
5519 ITypeInfo2_fnGetFuncCustData
,
5520 ITypeInfo2_fnGetParamCustData
,
5521 ITypeInfo2_fnGetVarCustData
,
5522 ITypeInfo2_fnGetImplTypeCustData
,
5523 ITypeInfo2_fnGetDocumentation2
,
5524 ITypeInfo2_fnGetAllCustData
,
5525 ITypeInfo2_fnGetAllFuncCustData
,
5526 ITypeInfo2_fnGetAllParamCustData
,
5527 ITypeInfo2_fnGetAllVarCustData
,
5528 ITypeInfo2_fnGetAllImplTypeCustData
,
5531 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5533 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5535 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
5538 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
5540 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5542 return ITypeInfo_AddRef((ITypeInfo
*)This
);
5545 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
5547 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5549 return ITypeInfo_Release((ITypeInfo
*)This
);
5552 static HRESULT WINAPI
ITypeComp_fnBind(
5555 unsigned long lHash
,
5556 unsigned short wFlags
,
5557 ITypeInfo
** ppTInfo
,
5558 DESCKIND
* pDescKind
,
5561 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5562 TLBFuncDesc
* pFDesc
;
5563 TLBVarDesc
* pVDesc
;
5565 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5567 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
5568 if (pFDesc
->funcdesc
.invkind
& wFlags
)
5569 if (!strcmpW(pFDesc
->Name
, szName
)) {
5575 *pDescKind
= DESCKIND_FUNCDESC
;
5576 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
5577 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5580 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
5582 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
5583 if (!strcmpW(pVDesc
->Name
, szName
)) {
5584 *pDescKind
= DESCKIND_VARDESC
;
5585 pBindPtr
->lpvardesc
= &pVDesc
->vardesc
;
5586 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5592 /* not found, look for it in inherited interfaces */
5593 if ((This
->TypeAttr
.typekind
== TKIND_INTERFACE
) && This
->TypeAttr
.cImplTypes
) {
5594 /* recursive search */
5598 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
5601 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
5602 ITypeInfo_Release(pTInfo
);
5606 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5607 ITypeComp_Release(pTComp
);
5610 WARN("Could not search inherited interface!\n");
5612 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
5613 *pDescKind
= DESCKIND_NONE
;
5614 pBindPtr
->lpfuncdesc
= NULL
;
5616 return DISP_E_MEMBERNOTFOUND
;
5619 static HRESULT WINAPI
ITypeComp_fnBindType(
5622 unsigned long lHash
,
5623 ITypeInfo
** ppTInfo
,
5624 ITypeComp
** ppTComp
)
5626 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5628 /* strange behaviour (does nothing) but like the
5631 if (!ppTInfo
|| !ppTComp
)
5640 static ICOM_VTABLE(ITypeComp
) tcompvt
=
5642 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5644 ITypeComp_fnQueryInterface
,
5646 ITypeComp_fnRelease
,
5649 ITypeComp_fnBindType