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_EMPTY
: sprintf(szVarType
, "VT_EMPTY"); break;
814 case VT_NULL
: sprintf(szVarType
, "VT_NULL"); break;
815 case VT_RECORD
: sprintf(szVarType
, "VT_RECORD"); break;
816 case VT_I8
: sprintf(szVarType
, "VT_I8"); break;
817 case VT_UI8
: sprintf(szVarType
, "VT_UI8"); break;
818 case VT_UI1
: sprintf(szVarType
, "VT_UI"); break;
819 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
820 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
821 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
822 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
823 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
824 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
825 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
826 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
827 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
828 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
829 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
830 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
831 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
832 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
833 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
834 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
835 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
836 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
837 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED\n"); break;
838 default: sprintf(szVarType
, "unknown(%d)", vt
& VT_TYPEMASK
); break;
842 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
843 if (pTD
->vt
& VT_RESERVED
)
844 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
845 if (pTD
->vt
& VT_BYREF
)
846 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
847 if (pTD
->vt
& VT_ARRAY
)
848 szVarType
+= strlen(strcpy(szVarType
, "array of "));
849 if (pTD
->vt
& VT_VECTOR
)
850 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
851 switch(pTD
->vt
& VT_TYPEMASK
) {
852 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
853 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
854 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
855 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
856 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
857 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
858 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
859 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
860 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
861 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
862 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
863 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
864 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
865 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
866 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
867 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
868 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
869 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
870 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
871 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
872 pTD
->u
.hreftype
); break;
873 case VT_PTR
: sprintf(szVarType
, "ptr to ");
874 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
876 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
877 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
879 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
880 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
881 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
884 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
888 void dump_ELEMDESC(ELEMDESC
*edesc
) {
890 dump_TypeDesc(&edesc
->tdesc
,buf
);
891 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
892 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
893 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
895 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
897 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
898 for (i
=0;i
<funcdesc
->cParams
;i
++) {
899 MESSAGE("Param %d:\n",i
);
900 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
902 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
903 switch (funcdesc
->funckind
) {
904 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
905 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
906 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
907 case FUNC_STATIC
: MESSAGE("static");break;
908 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
909 default: MESSAGE("unknown");break;
911 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
912 switch (funcdesc
->invkind
) {
913 case INVOKE_FUNC
: MESSAGE("func");break;
914 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
915 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
916 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
918 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
919 switch (funcdesc
->callconv
) {
920 case CC_CDECL
: MESSAGE("cdecl");break;
921 case CC_PASCAL
: MESSAGE("pascal");break;
922 case CC_STDCALL
: MESSAGE("stdcall");break;
923 case CC_SYSCALL
: MESSAGE("syscall");break;
926 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
927 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
928 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
931 void dump_IDLDESC(IDLDESC
*idl
) {
932 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
935 static const char * typekind_desc
[] =
948 void dump_TYPEATTR(TYPEATTR
*tattr
) {
950 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
951 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
952 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
953 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
954 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
955 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
956 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
957 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
958 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
959 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
960 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
961 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
962 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
963 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
964 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
965 MESSAGE("\ttypedesc: %s\n", buf
);
966 dump_IDLDESC(&tattr
->idldescType
);
969 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
972 if (!TRACE_ON(typelib
))
974 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
975 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
976 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
979 dump_FUNCDESC(&(pfd
->funcdesc
));
981 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
982 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
984 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
988 dump_TLBFuncDescOne(pfd
);
992 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
996 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1001 static void dump_TLBImpLib(TLBImpLib
*import
)
1003 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1004 debugstr_w(import
->name
));
1005 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
1006 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1009 static void dump_TLBRefType(TLBRefType
* prt
)
1013 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
1014 if(prt
->index
== -1)
1015 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
1017 TRACE_(typelib
)("type no: %d\n", prt
->index
);
1019 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
1020 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1021 TRACE_(typelib
)("in lib\n");
1022 dump_TLBImpLib(prt
->pImpTLInfo
);
1028 static void dump_TLBImplType(TLBImplType
* impl
)
1032 "implementing/inheriting interface hRef = %lx implflags %x\n",
1033 impl
->hRef
, impl
->implflags
);
1038 void dump_Variant(VARIANT
* pvar
)
1043 TRACE("(%p)\n", pvar
);
1047 ZeroMemory(szVarType
, sizeof(szVarType
));
1049 /* FIXME : we could have better trace here, depending on the VARTYPE
1052 dump_VarType(V_VT(pvar
),szVarType
);
1054 TRACE("VARTYPE: %s\n", szVarType
);
1056 if (V_VT(pvar
) & VT_BYREF
) {
1057 ref
= V_UNION(pvar
, byref
);
1060 else ref
= &V_UNION(pvar
, cVal
);
1062 if (V_VT(pvar
) & VT_ARRAY
) {
1066 if (V_VT(pvar
) & VT_VECTOR
) {
1071 switch (V_VT(pvar
) & VT_TYPEMASK
)
1074 TRACE("%d\n", *(short*)ref
);
1079 TRACE("%u\n", *(UINT
*)ref
);
1084 TRACE("%d\n", *(INT
*)ref
);
1088 TRACE("%3.3e\n", *(float*)ref
);
1092 TRACE("%3.3e\n", *(double*)ref
);
1096 TRACE("%s\n", *(VARIANT_BOOL
*)ref
? "TRUE" : "FALSE");
1100 TRACE("%s\n", debugstr_w(*(BSTR
*)ref
));
1105 TRACE("%p\n", *(LPVOID
*)ref
);
1109 if (V_VT(pvar
) & VT_BYREF
) dump_Variant(ref
);
1116 if(!VariantTimeToSystemTime(*(DATE
*)ref
, &st
)) {
1117 TRACE("invalid date? (?)%ld %f\n", *(long*)ref
, *(double *)ref
);
1119 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1120 st
.wYear
, st
.wMonth
, st
.wDay
, st
.wHour
, st
.wMinute
,
1121 st
.wSecond
, *(double *)ref
);
1127 TRACE("%ld (hi), %lu (lo)\n", ((CY
*)ref
)->s
.Hi
, ((CY
*)ref
)->s
.Lo
);
1132 TRACE("(?)%ld\n", *(long*)ref
);
1137 static void dump_DispParms(DISPPARAMS
* pdp
)
1141 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1143 while (index
< pdp
->cArgs
)
1145 dump_Variant( &pdp
->rgvarg
[index
] );
1150 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1152 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1153 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1154 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1155 TRACE("fct:%u var:%u impl:%u\n",
1156 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1157 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1158 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1159 dump_TLBFuncDesc(pty
->funclist
);
1160 dump_TLBVarDesc(pty
->varlist
);
1161 dump_TLBImplType(pty
->impltypelist
);
1164 void dump_VARDESC(VARDESC
*v
)
1166 MESSAGE("memid %ld\n",v
->memid
);
1167 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1168 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1169 dump_ELEMDESC(&(v
->elemdescVar
));
1170 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1171 MESSAGE("varkind %d\n",v
->varkind
);
1174 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1176 /* VT_LPWSTR is largest type that */
1177 /* may appear in type description*/
1178 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1179 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1180 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1181 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1182 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1183 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1187 static void TLB_abort()
1191 static void * TLB_Alloc(unsigned size
)
1194 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1196 ERR("cannot allocate memory\n");
1201 static void TLB_Free(void * ptr
)
1203 HeapFree(GetProcessHeap(), 0, ptr
);
1207 /**********************************************************************
1209 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1212 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1214 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1215 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1217 if (where
!= DO_NOT_SEEK
)
1219 where
+= pcx
->oStart
;
1220 if (where
> pcx
->length
)
1223 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1228 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1229 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1234 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1239 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1240 FromLEDWords(buffer
, ret
);
1245 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1250 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1251 FromLEWords(buffer
, ret
);
1256 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1258 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1259 memset(pGuid
,0, sizeof(GUID
));
1262 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1263 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1264 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1265 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1266 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1269 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1272 MSFT_NameIntro niName
;
1274 WCHAR
* pwstring
= NULL
;
1275 BSTR bstrName
= NULL
;
1277 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1278 pcx
->pTblDir
->pNametab
.offset
+offset
);
1279 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1280 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1281 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1282 name
[niName
.namelen
& 0xff]='\0';
1284 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1287 /* no invalid characters in string */
1290 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1292 /* don't check for invalid character since this has been done previously */
1293 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1295 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1296 lengthInChars
= SysStringLen(bstrName
);
1297 HeapFree(GetProcessHeap(), 0, pwstring
);
1300 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1304 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1311 if(offset
<0) return NULL
;
1312 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1313 if(length
<= 0) return 0;
1314 string
=TLB_Alloc(length
+1);
1315 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1316 string
[length
]='\0';
1318 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1319 string
, -1, NULL
, 0);
1321 /* no invalid characters in string */
1324 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1326 /* don't check for invalid character since this has been done previously */
1327 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1329 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1330 lengthInChars
= SysStringLen(bstr
);
1331 HeapFree(GetProcessHeap(), 0, pwstring
);
1334 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1338 * read a value and fill a VARIANT structure
1340 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1344 TRACE_(typelib
)("\n");
1346 if(offset
<0) { /* data are packed in here */
1347 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1348 V_UNION(pVar
, iVal
) = offset
& 0xffff;
1351 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1352 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1353 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1354 switch (V_VT(pVar
)){
1355 case VT_EMPTY
: /* FIXME: is this right? */
1356 case VT_NULL
: /* FIXME: is this right? */
1357 case VT_I2
: /* this should not happen */
1368 case VT_VOID
: /* FIXME: is this right? */
1376 case VT_DECIMAL
: /* FIXME: is this right? */
1379 /* pointer types with known behaviour */
1382 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1384 FIXME("BSTR length = %d?\n", size
);
1386 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1387 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1388 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1389 /* FIXME: do we need a AtoW conversion here? */
1390 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1391 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1396 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1403 case VT_USERDEFINED
:
1409 case VT_STREAMED_OBJECT
:
1410 case VT_STORED_OBJECT
:
1411 case VT_BLOB_OBJECT
:
1416 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1420 if(size
>0) /* (big|small) endian correct? */
1421 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1425 * create a linked list with custom data
1427 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1433 TRACE_(typelib
)("\n");
1437 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1438 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1439 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1440 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1441 /* add new custom data at head of the list */
1442 pNew
->next
=*ppCustData
;
1444 offset
= entry
.next
;
1449 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1453 pTd
->vt
=type
& VT_TYPEMASK
;
1455 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1457 if(pTd
->vt
== VT_USERDEFINED
)
1458 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1460 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1464 MSFT_DoFuncs(TLBContext
* pcx
,
1469 TLBFuncDesc
** pptfd
)
1472 * member information is stored in a data structure at offset
1473 * indicated by the memoffset field of the typeinfo structure
1474 * There are several distinctive parts.
1475 * the first part starts with a field that holds the total length
1476 * of this (first) part excluding this field. Then follow the records,
1477 * for each member there is one record.
1479 * First entry is always the length of the record (excluding this
1481 * Rest of the record depends on the type of the member. If there is
1482 * a field indicating the member type (function variable intereface etc)
1483 * I have not found it yet. At this time we depend on the information
1484 * in the type info and the usual order how things are stored.
1486 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1489 * Third is a equal sized array with file offsets to the name entry
1492 * Forth and last (?) part is an array with offsets to the records in the
1493 * first part of this file segment.
1496 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1497 int recoffset
= offset
+ sizeof(INT
);
1500 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1502 TRACE_(typelib
)("\n");
1504 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1506 for ( i
= 0; i
< cFuncs
; i
++ )
1508 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1510 /* name, eventually add to a hash table */
1511 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1512 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1514 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1516 /* read the function information record */
1517 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1521 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1523 /* do the attributes */
1524 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1527 if ( nrattributes
> 0 )
1529 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1531 if ( nrattributes
> 1 )
1533 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1534 pFuncRec
->OptAttr
[1]) ;
1536 if ( nrattributes
> 2 )
1538 if ( pFuncRec
->FKCCIC
& 0x2000 )
1540 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1544 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1545 pFuncRec
->OptAttr
[2]);
1547 if( nrattributes
> 5 )
1549 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1551 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1554 pFuncRec
->OptAttr
[6],
1555 &(*pptfd
)->pCustData
);
1562 /* fill the FuncDesc Structure */
1563 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1564 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1566 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1567 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1568 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1569 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1570 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1571 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1572 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1576 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1579 /* do the parameters/arguments */
1580 if(pFuncRec
->nrargs
)
1583 MSFT_ParameterInfo paraminfo
;
1585 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1586 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1588 (*pptfd
)->pParamDesc
=
1589 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1591 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1592 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1594 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1596 TYPEDESC
* lpArgTypeDesc
= 0;
1600 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1603 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1605 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1607 /* SEEK value = jump to offset,
1608 * from there jump to the end of record,
1609 * go back by (j-1) arguments
1611 MSFT_ReadLEDWords( ¶minfo
,
1612 sizeof(MSFT_ParameterInfo
), pcx
,
1613 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1614 * sizeof(MSFT_ParameterInfo
)));
1616 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1618 while ( lpArgTypeDesc
!= NULL
)
1620 switch ( lpArgTypeDesc
->vt
)
1623 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1627 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1630 case VT_USERDEFINED
:
1631 MSFT_DoRefType(pcx
, pTI
,
1632 lpArgTypeDesc
->u
.hreftype
);
1634 lpArgTypeDesc
= NULL
;
1638 lpArgTypeDesc
= NULL
;
1644 /* parameter is the return value! */
1645 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1647 TYPEDESC
* lpArgTypeDesc
;
1649 (*pptfd
)->funcdesc
.elemdescFunc
=
1650 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1652 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1654 while ( lpArgTypeDesc
!= NULL
)
1656 switch ( lpArgTypeDesc
->vt
)
1659 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1663 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1667 case VT_USERDEFINED
:
1670 lpArgTypeDesc
->u
.hreftype
);
1672 lpArgTypeDesc
= NULL
;
1676 lpArgTypeDesc
= NULL
;
1681 /* second time around */
1682 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1685 (*pptfd
)->pParamDesc
[j
].Name
=
1686 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1689 if ( (PARAMFLAG_FHASDEFAULT
&
1690 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1691 ((pFuncRec
->FKCCIC
) & 0x1000) )
1693 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1695 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1697 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1699 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1700 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1702 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1706 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1709 pFuncRec
->OptAttr
[7+j
],
1710 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1715 /* scode is not used: archaic win16 stuff FIXME: right? */
1716 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1717 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1719 pptfd
= & ((*pptfd
)->next
);
1720 recoffset
+= reclength
;
1724 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1725 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1727 int infolen
, nameoffset
, reclength
;
1729 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1733 TRACE_(typelib
)("\n");
1735 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1736 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1737 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1738 recoffset
+= offset
+sizeof(INT
);
1739 for(i
=0;i
<cVars
;i
++){
1740 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1741 /* name, eventually add to a hash table */
1742 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1743 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1744 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1745 /* read the variable information record */
1746 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1748 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1750 if(reclength
>(6*sizeof(INT
)) )
1751 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1752 if(reclength
>(7*sizeof(INT
)) )
1753 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1754 if(reclength
>(8*sizeof(INT
)) )
1755 if(reclength
>(9*sizeof(INT
)) )
1756 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1757 /* fill the VarDesc Structure */
1758 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1759 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1760 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1761 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1762 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1763 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1764 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1765 if(pVarRec
->VarKind
== VAR_CONST
){
1766 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1767 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1768 pVarRec
->OffsValue
, pcx
);
1770 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1771 pptvd
=&((*pptvd
)->next
);
1772 recoffset
+= reclength
;
1775 /* fill in data for a hreftype (offset). When the refernced type is contained
1776 * in the typelib, it's just an (file) offset in the type info base dir.
1777 * If comes from import, it's an offset+1 in the ImpInfo table
1779 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1783 TLBRefType
**ppRefType
= &pTI
->reflist
;
1785 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1788 if((*ppRefType
)->reference
== offset
)
1790 ppRefType
= &(*ppRefType
)->next
;
1793 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1794 sizeof(**ppRefType
));
1796 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1797 /* external typelib */
1798 MSFT_ImpInfo impinfo
;
1799 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1801 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1803 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1804 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1805 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1806 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1807 pImpLib
=pImpLib
->next
;
1810 (*ppRefType
)->reference
=offset
;
1811 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1812 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1813 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1815 ERR("Cannot find a reference\n");
1816 (*ppRefType
)->reference
=-1;
1817 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1820 /* in this typelib */
1821 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1822 (*ppRefType
)->reference
=offset
;
1823 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1827 /* process Implemented Interfaces of a com class */
1828 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1832 MSFT_RefRecord refrec
;
1833 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1835 TRACE_(typelib
)("\n");
1837 for(i
=0;i
<count
;i
++){
1838 if(offset
<0) break; /* paranoia */
1839 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1840 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1841 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1842 (*ppImpl
)->hRef
= refrec
.reftype
;
1843 (*ppImpl
)->implflags
=refrec
.flags
;
1844 (*ppImpl
)->ctCustData
=
1845 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1846 offset
=refrec
.onext
;
1847 ppImpl
=&((*ppImpl
)->next
);
1851 * process a typeinfo record
1853 ITypeInfoImpl
* MSFT_DoTypeInfo(
1856 ITypeLibImpl
* pLibInfo
)
1858 MSFT_TypeInfoBase tiBase
;
1859 ITypeInfoImpl
*ptiRet
;
1861 TRACE_(typelib
)("count=%u\n", count
);
1863 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
1864 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
1865 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
1866 /* this is where we are coming from */
1867 ptiRet
->pTypeLib
= pLibInfo
;
1868 ptiRet
->index
=count
;
1869 /* fill in the typeattr fields */
1870 WARN("Assign constructor/destructor memid\n");
1872 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
1873 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
1874 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
1875 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
1876 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
1877 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
1878 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
1879 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
1880 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
1881 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
1882 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
1883 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
1884 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
1885 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
1886 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
1887 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
1888 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
1889 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
1892 /* IDLDESC idldescType; *//* never saw this one != zero */
1894 /* name, eventually add to a hash table */
1895 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
1896 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
1898 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
1899 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
1900 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
1901 /* note: InfoType's Help file and HelpStringDll come from the containing
1902 * library. Further HelpString and Docstring appear to be the same thing :(
1905 if(ptiRet
->TypeAttr
.cFuncs
>0 )
1906 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1907 ptiRet
->TypeAttr
.cVars
,
1908 tiBase
.memoffset
, & ptiRet
->funclist
);
1910 if(ptiRet
->TypeAttr
.cVars
>0 )
1911 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1912 ptiRet
->TypeAttr
.cVars
,
1913 tiBase
.memoffset
, & ptiRet
->varlist
);
1914 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
1915 switch(ptiRet
->TypeAttr
.typekind
)
1918 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
1921 case TKIND_DISPATCH
:
1922 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1924 if (tiBase
.datatype1
!= -1)
1926 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1927 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1930 { /* FIXME: This is a really bad hack to add IDispatch */
1931 const char* szStdOle
= "stdole2.tlb\0";
1932 int nStdOleLen
= strlen(szStdOle
);
1933 TLBRefType
**ppRef
= &ptiRet
->reflist
;
1936 if((*ppRef
)->reference
== -1)
1938 ppRef
= &(*ppRef
)->next
;
1941 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
1942 (*ppRef
)->guid
= IID_IDispatch
;
1943 (*ppRef
)->reference
= -1;
1944 (*ppRef
)->index
= TLB_REF_USE_GUID
;
1945 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
1946 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
1947 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
1950 MultiByteToWideChar(CP_ACP
,
1954 (*ppRef
)->pImpTLInfo
->name
,
1955 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
1957 (*ppRef
)->pImpTLInfo
->lcid
= 0;
1958 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
1959 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
1964 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1965 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1966 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1971 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
1973 TRACE_(typelib
)("%s guid: %s kind:%s\n",
1974 debugstr_w(ptiRet
->Name
),
1975 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
1976 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
1981 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
1982 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
1983 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
1986 static ITypeLibImpl
*tlb_cache_first
;
1987 static CRITICAL_SECTION cache_section
;
1988 static CRITICAL_SECTION_DEBUG cache_section_debug
=
1990 0, 0, &cache_section
,
1991 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
1992 0, 0, { 0, (DWORD
)(__FILE__
": typelib loader cache") }
1994 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
1997 /****************************************************************************
2000 * find the type of the typelib file and map the typelib resource into
2003 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2004 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2005 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
2007 ITypeLibImpl
*entry
;
2008 int ret
= TYPE_E_CANTLOADLIBRARY
;
2009 DWORD dwSignature
= 0;
2012 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
2016 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2017 EnterCriticalSection(&cache_section
);
2018 for (entry
= tlb_cache_first
; entry
!= NULL
; entry
= entry
->next
)
2020 if (!strcmpiW(entry
->path
, pszFileName
))
2022 TRACE("cache hit\n");
2023 *ppTypeLib
= (ITypeLib2
*)entry
;
2024 ITypeLib_AddRef(*ppTypeLib
);
2025 LeaveCriticalSection(&cache_section
);
2029 LeaveCriticalSection(&cache_section
);
2031 /* check the signature of the file */
2032 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
2033 if (INVALID_HANDLE_VALUE
!= hFile
)
2035 HANDLE hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2038 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
2041 /* retrieve file size */
2042 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
2044 /* first try to load as *.tlb */
2045 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2046 if ( dwSignature
== MSFT_SIGNATURE
)
2048 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2050 else if ( dwSignature
== SLTG_SIGNATURE
)
2052 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2054 UnmapViewOfFile(pBase
);
2056 CloseHandle(hMapping
);
2061 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
2063 /* find the typelibrary resource*/
2064 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2065 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2068 HRSRC hrsrc
= FindResourceA(hinstDLL
, MAKEINTRESOURCEA(index
),
2072 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2075 LPVOID pBase
= LockResource(hGlobal
);
2076 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2080 /* try to load as incore resource */
2081 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2082 if ( dwSignature
== MSFT_SIGNATURE
)
2084 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2086 else if ( dwSignature
== SLTG_SIGNATURE
)
2088 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2092 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2095 FreeResource( hGlobal
);
2098 FreeLibrary(hinstDLL
);
2103 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2105 TRACE("adding to cache\n");
2106 impl
->path
= HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName
)+1) * sizeof(WCHAR
));
2107 lstrcpyW(impl
->path
, pszFileName
);
2108 /* We should really canonicalise the path here. */
2110 /* FIXME: check if it has added already in the meantime */
2111 EnterCriticalSection(&cache_section
);
2112 if ((impl
->next
= tlb_cache_first
) != NULL
) impl
->next
->prev
= impl
;
2114 tlb_cache_first
= impl
;
2115 LeaveCriticalSection(&cache_section
);
2118 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
2123 /*================== ITypeLib(2) Methods ===================================*/
2125 /****************************************************************************
2126 * ITypeLib2_Constructor_MSFT
2128 * loading an MSFT typelib from an in-memory image
2130 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2134 MSFT_Header tlbHeader
;
2135 MSFT_SegDir tlbSegDir
;
2136 ITypeLibImpl
* pTypeLibImpl
;
2138 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2140 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2141 if (!pTypeLibImpl
) return NULL
;
2143 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2144 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2145 pTypeLibImpl
->ref
= 1;
2147 /* get pointer to beginning of typelib data */
2151 cx
.pLibInfo
= pTypeLibImpl
;
2152 cx
.length
= dwTLBLength
;
2155 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2157 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2158 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2159 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2162 /* there is a small amount of information here until the next important
2164 * the segment directory . Try to calculate the amount of data */
2165 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2167 /* now read the segment directory */
2168 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2169 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2170 cx
.pTblDir
= &tlbSegDir
;
2172 /* just check two entries */
2173 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2175 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2176 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2180 /* now fill our internal data */
2181 /* TLIBATTR fields */
2182 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2184 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2185 /* Windows seems to have zero here, is this correct? */
2186 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2187 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader
.lcid
),0),0);
2189 pTypeLibImpl
->LibAttr
.lcid
= 0;
2191 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2192 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2193 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2194 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2196 /* name, eventually add to a hash table */
2197 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2200 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2201 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2203 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2206 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2207 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2210 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2213 if(tlbHeader
.CustomDataOffset
>= 0)
2215 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2218 /* fill in typedescriptions */
2219 if(tlbSegDir
.pTypdescTab
.length
> 0)
2221 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2223 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2224 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2227 /* FIXME: add several sanity checks here */
2228 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2229 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2231 /* FIXME: check safearray */
2233 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2235 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2237 else if(td
[0] == VT_CARRAY
)
2239 /* array descr table here */
2240 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2242 else if(td
[0] == VT_USERDEFINED
)
2244 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2246 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2249 /* second time around to fill the array subscript info */
2252 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2253 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2255 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2256 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2259 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2261 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2263 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2265 for(j
= 0; j
<td
[2]; j
++)
2267 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2268 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2269 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2270 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2275 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2276 ERR("didn't find array description data\n");
2281 /* imported type libs */
2282 if(tlbSegDir
.pImpFiles
.offset
>0)
2284 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2285 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2288 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2293 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2294 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2295 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2297 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2298 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2299 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2300 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2303 name
= TLB_Alloc(size
+1);
2304 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
2305 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
2306 (*ppImpLib
)->name
= TLB_Alloc(len
* sizeof(WCHAR
));
2307 MultiByteToWideChar(CP_ACP
, 0, name
, -1, (*ppImpLib
)->name
, len
);
2310 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2311 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
2313 ppImpLib
= &(*ppImpLib
)->next
;
2318 if(tlbHeader
.nrtypeinfos
>= 0 )
2320 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2321 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2324 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2326 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2328 ITypeInfo_AddRef((ITypeInfo
*) *ppTI
);
2329 ppTI
= &((*ppTI
)->next
);
2330 (pTypeLibImpl
->TypeInfoCount
)++;
2334 TRACE("(%p)\n", pTypeLibImpl
);
2335 return (ITypeLib2
*) pTypeLibImpl
;
2339 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2345 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2346 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2347 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2348 ret
= SysAllocString(nameW
);
2349 HeapFree(GetProcessHeap(), 0, nameW
);
2353 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2359 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2360 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2364 guid
->Data4
[0] = s
>> 8;
2365 guid
->Data4
[1] = s
& 0xff;
2368 for(i
= 0; i
< 6; i
++) {
2369 memcpy(b
, str
+ 24 + 2 * i
, 2);
2370 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2375 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2382 bytelen
= *(WORD
*)ptr
;
2383 if(bytelen
== 0xffff) return 2;
2384 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2385 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2386 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2387 *pBstr
= SysAllocStringLen(nameW
, len
);
2388 HeapFree(GetProcessHeap(), 0, nameW
);
2392 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2397 bytelen
= *(WORD
*)ptr
;
2398 if(bytelen
== 0xffff) return 2;
2399 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2400 memcpy(*str
, ptr
+ 2, bytelen
);
2401 (*str
)[bytelen
] = '\0';
2405 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2407 char *ptr
= pLibBlk
;
2410 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2411 FIXME("libblk magic = %04x\n", w
);
2416 if((w
= *(WORD
*)ptr
) != 0xffff) {
2417 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2422 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2424 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2426 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2429 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2432 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
2433 pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
2435 pTypeLibImpl
->LibAttr
.lcid
= 0;
2438 ptr
+= 4; /* skip res12 */
2440 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2443 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2446 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2449 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2450 ptr
+= sizeof(GUID
);
2452 return ptr
- (char*)pLibBlk
;
2455 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2458 TYPEDESC
*pTD
= &pElem
->tdesc
;
2460 /* Handle [in/out] first */
2461 if((*pType
& 0xc000) == 0xc000)
2462 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2463 else if(*pType
& 0x8000)
2464 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2465 else if(*pType
& 0x4000)
2466 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2468 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2471 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2474 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2477 if((*pType
& 0xe00) == 0xe00) {
2479 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2481 pTD
= pTD
->u
.lptdesc
;
2483 switch(*pType
& 0x7f) {
2486 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2488 pTD
= pTD
->u
.lptdesc
;
2491 case VT_USERDEFINED
:
2492 pTD
->vt
= VT_USERDEFINED
;
2493 pTD
->u
.hreftype
= *(++pType
) / 4;
2499 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2502 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2504 pTD
->vt
= VT_CARRAY
;
2505 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2507 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2508 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2509 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2510 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2512 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2518 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2522 pTD
->vt
= VT_SAFEARRAY
;
2523 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2525 pTD
= pTD
->u
.lptdesc
;
2529 pTD
->vt
= *pType
& 0x7f;
2539 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2544 TLBRefType
**ppRefType
;
2546 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2547 FIXME("Ref magic = %x\n", pRef
->magic
);
2550 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2552 ppRefType
= &pTI
->reflist
;
2553 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2555 unsigned int lib_offs
, type_num
;
2557 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2558 sizeof(**ppRefType
));
2560 name
+= SLTG_ReadStringA(name
, &refname
);
2561 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2562 FIXME("Can't sscanf ref\n");
2563 if(lib_offs
!= 0xffff) {
2564 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2567 if((*import
)->offset
== lib_offs
)
2569 import
= &(*import
)->next
;
2572 char fname
[MAX_PATH
+1];
2575 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2577 (*import
)->offset
= lib_offs
;
2578 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2580 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2581 &(*import
)->wVersionMajor
,
2582 &(*import
)->wVersionMinor
,
2583 &(*import
)->lcid
, fname
) != 4) {
2584 FIXME("can't sscanf ref %s\n",
2585 pNameTable
+ lib_offs
+ 40);
2587 len
= strlen(fname
);
2588 if(fname
[len
-1] != '#')
2589 FIXME("fname = %s\n", fname
);
2590 fname
[len
-1] = '\0';
2591 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2593 (*ppRefType
)->pImpTLInfo
= *import
;
2594 } else { /* internal ref */
2595 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2597 (*ppRefType
)->reference
= ref
;
2598 (*ppRefType
)->index
= type_num
;
2600 HeapFree(GetProcessHeap(), 0, refname
);
2601 ppRefType
= &(*ppRefType
)->next
;
2603 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2604 FIXME("End of ref block magic = %x\n", *name
);
2605 dump_TLBRefType(pTI
->reflist
);
2608 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2611 SLTG_ImplInfo
*info
;
2612 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2613 /* I don't really get this structure, usually it's 0x16 bytes
2614 long, but iuser.tlb contains some that are 0x18 bytes long.
2615 That's ok because we can use the next ptr to jump to the next
2616 one. But how do we know the length of the last one? The WORD
2617 at offs 0x8 might be the clue. For now I'm just assuming that
2618 the last one is the regular 0x16 bytes. */
2620 info
= (SLTG_ImplInfo
*)pBlk
;
2622 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2623 sizeof(**ppImplType
));
2624 (*ppImplType
)->hRef
= info
->ref
;
2625 (*ppImplType
)->implflags
= info
->impltypeflags
;
2626 pTI
->TypeAttr
.cImplTypes
++;
2627 ppImplType
= &(*ppImplType
)->next
;
2629 if(info
->next
== 0xffff)
2632 FIXME("Interface inheriting more than one interface\n");
2633 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2635 info
++; /* see comment at top of function */
2639 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2642 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2643 SLTG_MemberHeader
*pMemHeader
;
2644 char *pFirstItem
, *pNextItem
;
2646 if(pTIHeader
->href_table
!= 0xffffffff) {
2647 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2652 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2654 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2656 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2657 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2660 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2664 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2667 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2668 SLTG_MemberHeader
*pMemHeader
;
2669 SLTG_Function
*pFunc
;
2670 char *pFirstItem
, *pNextItem
;
2671 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2674 if(pTIHeader
->href_table
!= 0xffffffff) {
2675 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2679 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2681 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2683 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2684 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2687 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2688 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2693 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2694 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2695 FIXME("func magic = %02x\n", pFunc
->magic
);
2698 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2699 sizeof(**ppFuncDesc
));
2700 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2702 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2703 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2704 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2705 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2706 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2707 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2709 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2710 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2712 if(pFunc
->retnextopt
& 0x80)
2713 pType
= &pFunc
->rettype
;
2715 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2718 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2720 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2721 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2722 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2723 (*ppFuncDesc
)->pParamDesc
=
2724 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2725 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2727 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2729 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2730 char *paramName
= pNameTable
+ *pArg
;
2732 /* If arg type follows then paramName points to the 2nd
2733 letter of the name, else the next WORD is an offset to
2734 the arg type and paramName points to the first letter.
2735 So let's take one char off paramName and see if we're
2736 pointing at an alpha-numeric char. However if *pArg is
2737 0xffff or 0xfffe then the param has no name, the former
2738 meaning that the next WORD is the type, the latter
2739 meaning the the next WORD is an offset to the type. */
2744 else if(*pArg
== 0xfffe) {
2748 else if(!isalnum(*(paramName
-1)))
2753 if(HaveOffs
) { /* the next word is an offset to type */
2754 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2755 SLTG_DoType(pType
, pFirstItem
,
2756 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2761 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2762 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2765 /* Are we an optional param ? */
2766 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2767 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2768 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2771 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2772 TLB_MultiByteToBSTR(paramName
);
2776 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2777 if(pFunc
->next
== 0xffff) break;
2779 pTI
->TypeAttr
.cFuncs
= num
;
2780 dump_TLBFuncDesc(pTI
->funclist
);
2781 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2784 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2787 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2788 SLTG_MemberHeader
*pMemHeader
;
2789 SLTG_RecordItem
*pItem
;
2791 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2796 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2798 pFirstItem
= (char*)(pMemHeader
+ 1);
2799 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2800 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2801 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2802 FIXME("record magic = %02x\n", pItem
->magic
);
2805 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2806 sizeof(**ppVarDesc
));
2807 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2808 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2809 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2810 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2812 if(pItem
->typepos
== 0x02)
2813 pType
= &pItem
->type
;
2814 else if(pItem
->typepos
== 0x00)
2815 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2817 FIXME("typepos = %02x\n", pItem
->typepos
);
2821 SLTG_DoType(pType
, pFirstItem
,
2822 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2824 /* FIXME("helpcontext, helpstring\n"); */
2826 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2828 ppVarDesc
= &((*ppVarDesc
)->next
);
2829 if(pItem
->next
== 0xffff) break;
2831 pTI
->TypeAttr
.cVars
= num
;
2832 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2835 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
2838 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2839 SLTG_MemberHeader
*pMemHeader
;
2840 SLTG_AliasItem
*pItem
;
2843 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2844 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
2847 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2848 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
2849 if (pItem
->vt
== 0xffff) {
2850 if (i
<(pMemHeader
->cbExtra
/4-1))
2851 FIXME("Endmarker too early in process alias data!\n");
2855 FIXME("Chain extends over last entry?\n");
2858 if (pItem
->vt
== VT_USERDEFINED
) {
2859 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
2860 /* guessing here ... */
2861 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
2862 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
2865 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
2866 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
2870 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
2873 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
2876 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2877 SLTG_MemberHeader
*pMemHeader
;
2878 SLTG_AliasItem
*pItem
;
2880 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2881 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
2882 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
2883 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
2884 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
2887 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
2890 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2891 SLTG_MemberHeader
*pMemHeader
;
2892 SLTG_EnumItem
*pItem
;
2894 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2897 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2899 pFirstItem
= (char*)(pMemHeader
+ 1);
2900 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
2901 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2902 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
2903 FIXME("enumitem magic = %04x\n", pItem
->magic
);
2906 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2907 sizeof(**ppVarDesc
));
2908 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2909 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2910 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2912 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2913 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2914 *(INT
*)(pItem
->value
+ pFirstItem
);
2915 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
2916 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2917 /* FIXME("helpcontext, helpstring\n"); */
2919 ppVarDesc
= &((*ppVarDesc
)->next
);
2920 if(pItem
->next
== 0xffff) break;
2922 pTI
->TypeAttr
.cVars
= num
;
2923 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2926 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2927 managable copy of it into this */
2940 } SLTG_InternalOtherTypeInfo
;
2942 /****************************************************************************
2943 * ITypeLib2_Constructor_SLTG
2945 * loading a SLTG typelib from an in-memory image
2947 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
2949 ITypeLibImpl
*pTypeLibImpl
;
2950 SLTG_Header
*pHeader
;
2951 SLTG_BlkEntry
*pBlkEntry
;
2955 LPVOID pBlk
, pFirstBlk
;
2956 SLTG_LibBlk
*pLibBlk
;
2957 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
2958 char *pAfterOTIBlks
= NULL
;
2959 char *pNameTable
, *ptr
;
2962 ITypeInfoImpl
**ppTypeInfoImpl
;
2964 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2966 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2967 if (!pTypeLibImpl
) return NULL
;
2969 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2970 pTypeLibImpl
->ref
= 1;
2975 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
2976 pHeader
->nrOfFileBlks
);
2977 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
2978 FIXME("Header type magic 0x%08lx not supported.\n",
2979 pHeader
->SLTG_magic
);
2983 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2984 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
2986 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2987 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
2989 /* Next we have a magic block */
2990 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
2992 /* Let's see if we're still in sync */
2993 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
2994 sizeof(SLTG_COMPOBJ_MAGIC
))) {
2995 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
2998 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
2999 sizeof(SLTG_DIR_MAGIC
))) {
3000 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
3004 pIndex
= (SLTG_Index
*)(pMagic
+1);
3006 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3008 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
3010 /* We'll set up a ptr to the main library block, which is the last one. */
3012 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3013 pBlkEntry
[order
].next
!= 0;
3014 order
= pBlkEntry
[order
].next
- 1, i
++) {
3015 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3019 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3021 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3026 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3028 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
3029 sizeof(*pOtherTypeInfoBlks
) *
3030 pTypeLibImpl
->TypeInfoCount
);
3033 ptr
= (char*)pLibBlk
+ len
;
3035 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3039 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3041 w
= *(WORD
*)(ptr
+ 2);
3044 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
3046 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3047 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3049 w
= *(WORD
*)(ptr
+ 4 + len
);
3051 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
3053 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
3055 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
3056 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
3058 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
3059 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
3060 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
3062 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
3064 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
3067 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
3068 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
3069 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
3070 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
3071 len
+= sizeof(SLTG_OtherTypeInfo
);
3075 pAfterOTIBlks
= ptr
;
3077 /* Skip this WORD and get the next DWORD */
3078 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3080 /* Now add this to pLibBLk look at what we're pointing at and
3081 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3082 dust and we should be pointing at the beginning of the name
3085 pNameTable
= (char*)pLibBlk
+ len
;
3087 switch(*(WORD
*)pNameTable
) {
3094 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3098 pNameTable
+= 0x216;
3102 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3104 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3107 /* Hopefully we now have enough ptrs set up to actually read in
3108 some TypeInfos. It's not clear which order to do them in, so
3109 I'll just follow the links along the BlkEntry chain and read
3110 them in in the order in which they're in the file */
3112 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3114 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3115 pBlkEntry
[order
].next
!= 0;
3116 order
= pBlkEntry
[order
].next
- 1, i
++) {
3118 SLTG_TypeInfoHeader
*pTIHeader
;
3119 SLTG_TypeInfoTail
*pTITail
;
3121 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3122 pOtherTypeInfoBlks
[i
].index_name
)) {
3123 FIXME("Index strings don't match\n");
3128 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3129 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3132 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3133 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3134 (*ppTypeInfoImpl
)->index
= i
;
3135 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3136 pOtherTypeInfoBlks
[i
].name_offs
+
3138 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3139 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3141 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3142 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3143 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3144 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3145 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3147 if((pTIHeader
->typeflags1
& 7) != 2)
3148 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3149 if(pTIHeader
->typeflags3
!= 2)
3150 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3152 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3153 debugstr_w((*ppTypeInfoImpl
)->Name
),
3154 typekind_desc
[pTIHeader
->typekind
],
3155 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3156 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3158 switch(pTIHeader
->typekind
) {
3160 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3164 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3167 case TKIND_INTERFACE
:
3168 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3172 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3176 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3177 if (pTITail
->tdescalias_vt
)
3178 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3181 case TKIND_DISPATCH
:
3182 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3186 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3192 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3193 but we've already set those */
3194 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3195 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3196 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3198 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3220 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3221 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3224 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3225 FIXME("Somehow processed %d TypeInfos\n", i
);
3229 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3230 return (ITypeLib2
*)pTypeLibImpl
;
3233 /* ITypeLib::QueryInterface
3235 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3240 ICOM_THIS( ITypeLibImpl
, iface
);
3242 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3245 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3246 IsEqualIID(riid
,&IID_ITypeLib
)||
3247 IsEqualIID(riid
,&IID_ITypeLib2
))
3254 ITypeLib2_AddRef(iface
);
3255 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3258 TRACE("-- Interface: E_NOINTERFACE\n");
3259 return E_NOINTERFACE
;
3264 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3266 ICOM_THIS( ITypeLibImpl
, iface
);
3268 TRACE("(%p)->ref was %u\n",This
, This
->ref
);
3270 return ++(This
->ref
);
3273 /* ITypeLib::Release
3275 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3277 ICOM_THIS( ITypeLibImpl
, iface
);
3281 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3285 /* remove cache entry */
3286 TRACE("removing from cache list\n");
3287 EnterCriticalSection(&cache_section
);
3288 if (This
->next
) This
->next
->prev
= This
->prev
;
3289 if (This
->prev
) This
->prev
->next
= This
->next
;
3290 else tlb_cache_first
= This
->next
;
3291 LeaveCriticalSection(&cache_section
);
3293 /* FIXME destroy child objects */
3294 TRACE(" destroying ITypeLib(%p)\n",This
);
3298 SysFreeString(This
->Name
);
3302 if (This
->DocString
)
3304 SysFreeString(This
->DocString
);
3305 This
->DocString
= NULL
;
3310 SysFreeString(This
->HelpFile
);
3311 This
->HelpFile
= NULL
;
3314 if (This
->HelpStringDll
)
3316 SysFreeString(This
->HelpStringDll
);
3317 This
->HelpStringDll
= NULL
;
3320 if (This
->pTypeInfo
) /* can be NULL */
3321 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3322 HeapFree(GetProcessHeap(),0,This
);
3329 /* ITypeLib::GetTypeInfoCount
3331 * Returns the number of type descriptions in the type library
3333 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3335 ICOM_THIS( ITypeLibImpl
, iface
);
3336 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3337 return This
->TypeInfoCount
;
3340 /* ITypeLib::GetTypeInfo
3342 * retrieves the specified type description in the library.
3344 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3347 ITypeInfo
**ppTInfo
)
3351 ICOM_THIS( ITypeLibImpl
, iface
);
3352 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3354 TRACE("(%p)->(index=%d) \n", This
, index
);
3356 if (!ppTInfo
) return E_INVALIDARG
;
3358 /* search element n in list */
3359 for(i
=0; i
< index
; i
++)
3361 pTypeInfo
= pTypeInfo
->next
;
3364 TRACE("-- element not found\n");
3365 return TYPE_E_ELEMENTNOTFOUND
;
3369 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3371 ITypeInfo_AddRef(*ppTInfo
);
3372 TRACE("-- found (%p)\n",*ppTInfo
);
3377 /* ITypeLibs::GetTypeInfoType
3379 * Retrieves the type of a type description.
3381 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3386 ICOM_THIS( ITypeLibImpl
, iface
);
3388 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3390 TRACE("(%p) index %d \n",This
, index
);
3392 if(!pTKind
) return E_INVALIDARG
;
3394 /* search element n in list */
3395 for(i
=0; i
< index
; i
++)
3399 TRACE("-- element not found\n");
3400 return TYPE_E_ELEMENTNOTFOUND
;
3402 pTInfo
= pTInfo
->next
;
3405 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3406 TRACE("-- found Type (%d)\n", *pTKind
);
3410 /* ITypeLib::GetTypeInfoOfGuid
3412 * Retrieves the type description that corresponds to the specified GUID.
3415 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3418 ITypeInfo
**ppTInfo
)
3420 ICOM_THIS( ITypeLibImpl
, iface
);
3421 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3423 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3425 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3427 /* search linked list for guid */
3428 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3430 pTypeInfo
= pTypeInfo
->next
;
3434 /* end of list reached */
3435 TRACE("-- element not found\n");
3436 return TYPE_E_ELEMENTNOTFOUND
;
3440 TRACE("-- found (%p, %s)\n",
3442 debugstr_w(pTypeInfo
->Name
));
3444 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3445 ITypeInfo_AddRef(*ppTInfo
);
3449 /* ITypeLib::GetLibAttr
3451 * Retrieves the structure that contains the library's attributes.
3454 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3456 LPTLIBATTR
*ppTLibAttr
)
3458 ICOM_THIS( ITypeLibImpl
, iface
);
3459 TRACE("(%p)\n",This
);
3460 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3461 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3465 /* ITypeLib::GetTypeComp
3467 * Enables a client compiler to bind to a library's types, variables,
3468 * constants, and global functions.
3471 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3473 ITypeComp
**ppTComp
)
3475 ICOM_THIS( ITypeLibImpl
, iface
);
3477 TRACE("(%p)->(%p)\n",This
,ppTComp
);
3478 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
3479 ITypeComp_AddRef(*ppTComp
);
3484 /* ITypeLib::GetDocumentation
3486 * Retrieves the library's documentation string, the complete Help file name
3487 * and path, and the context identifier for the library Help topic in the Help
3490 * On a successful return all non-null BSTR pointers will have been set,
3493 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3497 BSTR
*pBstrDocString
,
3498 DWORD
*pdwHelpContext
,
3499 BSTR
*pBstrHelpFile
)
3501 ICOM_THIS( ITypeLibImpl
, iface
);
3503 HRESULT result
= E_INVALIDARG
;
3508 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3510 pBstrName
, pBstrDocString
,
3511 pdwHelpContext
, pBstrHelpFile
);
3515 /* documentation for the typelib */
3519 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3525 if (This
->DocString
)
3526 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3527 else if (This
->Name
)
3528 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3530 *pBstrDocString
= NULL
;
3534 *pdwHelpContext
= This
->dwHelpContext
;
3539 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3541 *pBstrHelpFile
= NULL
;
3548 /* for a typeinfo */
3549 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3551 if(SUCCEEDED(result
))
3553 result
= ITypeInfo_GetDocumentation(pTInfo
,
3557 pdwHelpContext
, pBstrHelpFile
);
3559 ITypeInfo_Release(pTInfo
);
3564 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3566 if (pBstrName
) SysFreeString (*pBstrName
);
3568 return STG_E_INSUFFICIENTMEMORY
;
3573 * Indicates whether a passed-in string contains the name of a type or member
3574 * described in the library.
3577 static HRESULT WINAPI
ITypeLib2_fnIsName(
3583 ICOM_THIS( ITypeLibImpl
, iface
);
3584 ITypeInfoImpl
*pTInfo
;
3585 TLBFuncDesc
*pFInfo
;
3588 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3590 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3594 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3595 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3596 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3597 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3598 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3599 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3600 goto ITypeLib2_fnIsName_exit
;
3602 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3603 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3608 ITypeLib2_fnIsName_exit
:
3609 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3610 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3615 /* ITypeLib::FindName
3617 * Finds occurrences of a type description in a type library. This may be used
3618 * to quickly verify that a name exists in a type library.
3621 static HRESULT WINAPI
ITypeLib2_fnFindName(
3625 ITypeInfo
**ppTInfo
,
3629 ICOM_THIS( ITypeLibImpl
, iface
);
3630 ITypeInfoImpl
*pTInfo
;
3631 TLBFuncDesc
*pFInfo
;
3635 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3637 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3638 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3639 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3640 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3641 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3642 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3643 goto ITypeLib2_fnFindName_exit
;
3645 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3646 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3648 ITypeLib2_fnFindName_exit
:
3649 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3650 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3653 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3654 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3661 /* ITypeLib::ReleaseTLibAttr
3663 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3666 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3668 TLIBATTR
*pTLibAttr
)
3670 ICOM_THIS( ITypeLibImpl
, iface
);
3671 TRACE("freeing (%p)\n",This
);
3672 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3676 /* ITypeLib2::GetCustData
3678 * gets the custom data
3680 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3685 ICOM_THIS( ITypeLibImpl
, iface
);
3686 TLBCustData
*pCData
;
3688 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3690 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3693 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3697 VariantInit( pVarVal
);
3698 VariantCopy( pVarVal
, &pCData
->data
);
3701 return E_INVALIDARG
; /* FIXME: correct? */
3704 /* ITypeLib2::GetLibStatistics
3706 * Returns statistics about a type library that are required for efficient
3707 * sizing of hash tables.
3710 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3712 ULONG
*pcUniqueNames
,
3713 ULONG
*pcchUniqueNames
)
3715 ICOM_THIS( ITypeLibImpl
, iface
);
3717 FIXME("(%p): stub!\n", This
);
3719 if(pcUniqueNames
) *pcUniqueNames
=1;
3720 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3724 /* ITypeLib2::GetDocumentation2
3726 * Retrieves the library's documentation string, the complete Help file name
3727 * and path, the localization context to use, and the context ID for the
3728 * library Help topic in the Help file.
3731 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3735 BSTR
*pbstrHelpString
,
3736 DWORD
*pdwHelpStringContext
,
3737 BSTR
*pbstrHelpStringDll
)
3739 ICOM_THIS( ITypeLibImpl
, iface
);
3743 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3745 /* the help string should be obtained from the helpstringdll,
3746 * using the _DLLGetDocumentation function, based on the supplied
3747 * lcid. Nice to do sometime...
3751 /* documentation for the typelib */
3753 *pbstrHelpString
=SysAllocString(This
->DocString
);
3754 if(pdwHelpStringContext
)
3755 *pdwHelpStringContext
=This
->dwHelpContext
;
3756 if(pbstrHelpStringDll
)
3757 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3763 /* for a typeinfo */
3764 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3766 if(SUCCEEDED(result
))
3768 ITypeInfo2
* pTInfo2
;
3769 result
= ITypeInfo_QueryInterface(pTInfo
,
3771 (LPVOID
*) &pTInfo2
);
3773 if(SUCCEEDED(result
))
3775 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3779 pdwHelpStringContext
,
3780 pbstrHelpStringDll
);
3782 ITypeInfo2_Release(pTInfo2
);
3785 ITypeInfo_Release(pTInfo
);
3791 /* ITypeLib2::GetAllCustData
3793 * Gets all custom data items for the library.
3796 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3798 CUSTDATA
*pCustData
)
3800 ICOM_THIS( ITypeLibImpl
, iface
);
3801 TLBCustData
*pCData
;
3803 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3804 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3805 if(pCustData
->prgCustData
){
3806 pCustData
->cCustData
=This
->ctCustData
;
3807 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3808 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3809 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3812 ERR(" OUT OF MEMORY! \n");
3813 return E_OUTOFMEMORY
;
3818 static ICOM_VTABLE(ITypeLib2
) tlbvt
= {
3819 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3820 ITypeLib2_fnQueryInterface
,
3822 ITypeLib2_fnRelease
,
3823 ITypeLib2_fnGetTypeInfoCount
,
3824 ITypeLib2_fnGetTypeInfo
,
3825 ITypeLib2_fnGetTypeInfoType
,
3826 ITypeLib2_fnGetTypeInfoOfGuid
,
3827 ITypeLib2_fnGetLibAttr
,
3828 ITypeLib2_fnGetTypeComp
,
3829 ITypeLib2_fnGetDocumentation
,
3831 ITypeLib2_fnFindName
,
3832 ITypeLib2_fnReleaseTLibAttr
,
3834 ITypeLib2_fnGetCustData
,
3835 ITypeLib2_fnGetLibStatistics
,
3836 ITypeLib2_fnGetDocumentation2
,
3837 ITypeLib2_fnGetAllCustData
3841 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
3843 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3845 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
3848 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
3850 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3852 return ITypeInfo_AddRef((ITypeInfo
*)This
);
3855 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
3857 ICOM_THIS_From_ITypeComp(ITypeLibImpl
, iface
);
3859 return ITypeInfo_Release((ITypeInfo
*)This
);
3862 static HRESULT WINAPI
ITypeLibComp_fnBind(
3865 unsigned long lHash
,
3866 unsigned short wFlags
,
3867 ITypeInfo
** ppTInfo
,
3868 DESCKIND
* pDescKind
,
3871 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
3875 static HRESULT WINAPI
ITypeLibComp_fnBindType(
3878 unsigned long lHash
,
3879 ITypeInfo
** ppTInfo
,
3880 ITypeComp
** ppTComp
)
3882 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
3886 static ICOM_VTABLE(ITypeComp
) tlbtcvt
=
3888 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3890 ITypeLibComp_fnQueryInterface
,
3891 ITypeLibComp_fnAddRef
,
3892 ITypeLibComp_fnRelease
,
3894 ITypeLibComp_fnBind
,
3895 ITypeLibComp_fnBindType
3898 /*================== ITypeInfo(2) Methods ===================================*/
3899 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
3901 ITypeInfoImpl
* pTypeInfoImpl
;
3903 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
3906 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
3907 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
3908 pTypeInfoImpl
->ref
=1;
3910 TRACE("(%p)\n", pTypeInfoImpl
);
3911 return (ITypeInfo2
*) pTypeInfoImpl
;
3914 /* ITypeInfo::QueryInterface
3916 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
3921 ICOM_THIS( ITypeLibImpl
, iface
);
3923 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3926 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3927 IsEqualIID(riid
,&IID_ITypeInfo
)||
3928 IsEqualIID(riid
,&IID_ITypeInfo2
))
3932 ITypeInfo_AddRef(iface
);
3933 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3936 TRACE("-- Interface: E_NOINTERFACE\n");
3937 return E_NOINTERFACE
;
3940 /* ITypeInfo::AddRef
3942 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
3944 ICOM_THIS( ITypeInfoImpl
, iface
);
3948 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3952 /* ITypeInfo::Release
3954 static ULONG WINAPI
ITypeInfo_fnRelease( ITypeInfo2
*iface
)
3956 ICOM_THIS( ITypeInfoImpl
, iface
);
3960 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3964 FIXME("destroy child objects\n");
3966 TRACE("destroying ITypeInfo(%p)\n",This
);
3969 SysFreeString(This
->Name
);
3973 if (This
->DocString
)
3975 SysFreeString(This
->DocString
);
3976 This
->DocString
= 0;
3981 ITypeInfo_Release((ITypeInfo
*)This
->next
);
3984 HeapFree(GetProcessHeap(),0,This
);
3990 /* ITypeInfo::GetTypeAttr
3992 * Retrieves a TYPEATTR structure that contains the attributes of the type
3996 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
3997 LPTYPEATTR
*ppTypeAttr
)
3999 ICOM_THIS( ITypeInfoImpl
, iface
);
4000 TRACE("(%p)\n",This
);
4001 /* FIXME: must do a copy here */
4002 *ppTypeAttr
=&This
->TypeAttr
;
4006 /* ITypeInfo::GetTypeComp
4008 * Retrieves the ITypeComp interface for the type description, which enables a
4009 * client compiler to bind to the type description's members.
4012 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
4013 ITypeComp
* *ppTComp
)
4015 ICOM_THIS( ITypeInfoImpl
, iface
);
4017 TRACE("(%p)->(%p) stub!\n", This
, ppTComp
);
4019 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4020 ITypeComp_AddRef(*ppTComp
);
4024 /* ITypeInfo::GetFuncDesc
4026 * Retrieves the FUNCDESC structure that contains information about a
4027 * specified function.
4030 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
4031 LPFUNCDESC
*ppFuncDesc
)
4033 ICOM_THIS( ITypeInfoImpl
, iface
);
4035 TLBFuncDesc
* pFDesc
;
4036 TRACE("(%p) index %d\n", This
, index
);
4037 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
4040 /* FIXME: must do a copy here */
4041 *ppFuncDesc
=&pFDesc
->funcdesc
;
4044 return E_INVALIDARG
;
4047 /* ITypeInfo::GetVarDesc
4049 * Retrieves a VARDESC structure that describes the specified variable.
4052 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
4053 LPVARDESC
*ppVarDesc
)
4055 ICOM_THIS( ITypeInfoImpl
, iface
);
4057 TLBVarDesc
* pVDesc
;
4058 TRACE("(%p) index %d\n", This
, index
);
4059 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
4062 /* FIXME: must do a copy here */
4063 *ppVarDesc
=&pVDesc
->vardesc
;
4066 return E_INVALIDARG
;
4069 /* ITypeInfo_GetNames
4071 * Retrieves the variable with the specified member ID (or the name of the
4072 * property or method and its parameters) that correspond to the specified
4075 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
4076 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
4078 ICOM_THIS( ITypeInfoImpl
, iface
);
4079 TLBFuncDesc
* pFDesc
;
4080 TLBVarDesc
* pVDesc
;
4082 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
4083 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
4086 /* function found, now return function and parameter names */
4087 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
4090 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
4092 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
4098 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
4101 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
4106 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
)
4108 /* recursive search */
4111 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
4113 if(SUCCEEDED(result
))
4115 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
4116 ITypeInfo_Release(pTInfo
);
4119 WARN("Could not search inherited interface!\n");
4123 WARN("no names found\n");
4126 return TYPE_E_ELEMENTNOTFOUND
;
4133 /* ITypeInfo::GetRefTypeOfImplType
4135 * If a type description describes a COM class, it retrieves the type
4136 * description of the implemented interface types. For an interface,
4137 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4141 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
4146 ICOM_THIS( ITypeInfoImpl
, iface
);
4148 TLBImplType
*pImpl
= This
->impltypelist
;
4150 TRACE("(%p) index %d\n", This
, index
);
4151 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4155 /* only valid on dual interfaces;
4156 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4158 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4160 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4161 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4167 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4168 *pRefType
= pImpl
->hRef
;
4173 /* get element n from linked list */
4174 for(i
=0; pImpl
&& i
<index
; i
++)
4176 pImpl
= pImpl
->next
;
4179 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4181 *pRefType
= pImpl
->hRef
;
4183 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4190 /* ITypeInfo::GetImplTypeFlags
4192 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4193 * or base interface in a type description.
4195 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4196 UINT index
, INT
*pImplTypeFlags
)
4198 ICOM_THIS( ITypeInfoImpl
, iface
);
4202 TRACE("(%p) index %d\n", This
, index
);
4203 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4204 i
++, pImpl
=pImpl
->next
)
4206 if(i
==index
&& pImpl
){
4207 *pImplTypeFlags
=pImpl
->implflags
;
4211 return TYPE_E_ELEMENTNOTFOUND
;
4215 * Maps between member names and member IDs, and parameter names and
4218 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4219 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4221 ICOM_THIS( ITypeInfoImpl
, iface
);
4222 TLBFuncDesc
* pFDesc
;
4223 TLBVarDesc
* pVDesc
;
4226 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4228 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4230 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4231 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4232 for(i
=1; i
< cNames
; i
++){
4233 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4234 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4236 if( j
<pFDesc
->funcdesc
.cParams
)
4239 ret
=DISP_E_UNKNOWNNAME
;
4244 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4245 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4246 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4250 /* not found, see if this is and interface with an inheritance */
4251 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&&
4252 This
->TypeAttr
.cImplTypes
){
4253 /* recursive search */
4255 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4256 This
->impltypelist
->hRef
, &pTInfo
);
4258 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4259 ITypeInfo_Release(pTInfo
);
4262 WARN("Could not search inherited interface!\n");
4264 WARN("no names found\n");
4265 return DISP_E_UNKNOWNNAME
;
4268 /* ITypeInfo::Invoke
4270 * Invokes a method, or accesses a property of an object, that implements the
4271 * interface described by the type description.
4274 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4277 if (TRACE_ON(ole
)) {
4279 TRACE("Calling %p(",func
);
4280 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4292 res
= func(args
[0]);
4295 res
= func(args
[0],args
[1]);
4298 res
= func(args
[0],args
[1],args
[2]);
4301 res
= func(args
[0],args
[1],args
[2],args
[3]);
4304 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4307 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4310 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4313 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4316 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4319 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4325 FIXME("unsupported calling convention %d\n",callconv
);
4329 TRACE("returns %08lx\n",res
);
4333 extern int const _argsize(DWORD vt
);
4335 /****************************************************************************
4336 * Helper functions for Dispcall / Invoke, which copies one variant
4337 * with target type onto the argument stack.
4340 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4341 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4343 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4347 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4348 memcpy(argpos
,&arg
,sizeof(void*));
4352 if (V_VT(arg
) == vt
) {
4353 memcpy(argpos
, &V_UNION(arg
,lVal
), arglen
);
4357 if (V_ISARRAY(arg
) && (vt
== VT_SAFEARRAY
)) {
4358 memcpy(argpos
, &V_UNION(arg
,parray
), sizeof(SAFEARRAY
*));
4362 if (vt
== VT_VARIANT
) {
4363 memcpy(argpos
, arg
, arglen
);
4366 /* Deref BYREF vars if there is need */
4367 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4368 memcpy(argpos
,(void*)V_UNION(arg
,lVal
), arglen
);
4371 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4372 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4373 memcpy(argpos
,&V_UNION(arg
,lVal
), arglen
);
4376 if ((vt
== VT_PTR
) && tdesc
)
4377 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4379 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4384 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4386 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
));
4387 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4390 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4391 switch (tattr
->typekind
) {
4393 switch ( V_VT( arg
) ) {
4395 *argpos
= V_UNION(arg
,iVal
);
4398 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4401 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4406 tdesc
= &(tattr
->tdescAlias
);
4407 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4408 ITypeInfo_Release(tinfo2
);
4411 case TKIND_INTERFACE
:
4412 if (V_VT(arg
) == VT_DISPATCH
) {
4414 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4415 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4418 hres
=IUnknown_QueryInterface(V_UNION(arg
,pdispVal
),&IID_IDispatch
,(LPVOID
*)&disp
);
4419 if (SUCCEEDED(hres
)) {
4420 memcpy(argpos
,&disp
,4);
4421 IUnknown_Release(V_UNION(arg
,pdispVal
));
4424 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4427 if (V_VT(arg
) == VT_UNKNOWN
) {
4428 memcpy(argpos
, &V_UNION(arg
,punkVal
), 4);
4431 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4433 case TKIND_DISPATCH
:
4434 if (V_VT(arg
) == VT_DISPATCH
) {
4435 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4438 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4441 FIXME("TKIND_RECORD unhandled.\n");
4444 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4452 if (VariantChangeType(&va
,arg
,0,vt
)==S_OK
) {
4453 memcpy(argpos
,&V_UNION(&va
,lVal
), arglen
);
4454 FIXME("Should not use VariantChangeType here. (conversion from 0x%x -> 0x%x)\n",
4459 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4463 /***********************************************************************
4464 * DispCallFunc (OLEAUT32.@)
4468 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4469 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4471 int i
, argsize
, argspos
;
4475 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4476 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4478 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4479 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4481 for (i
=0;i
<cActuals
;i
++) {
4482 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4483 dump_Variant(prgpvarg
[i
]);
4484 argsize
+= _argsize(prgvt
[i
]);
4486 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4487 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4489 for (i
=0;i
<cActuals
;i
++) {
4490 VARIANT
*arg
= prgpvarg
[i
];
4491 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4492 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4493 argspos
+= _argsize(prgvt
[i
]);
4496 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4498 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4503 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4504 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4505 FIXME("Method returned %lx\n",hres
);
4507 HeapFree(GetProcessHeap(),0,args
);
4511 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4516 DISPPARAMS
*pDispParams
,
4517 VARIANT
*pVarResult
,
4518 EXCEPINFO
*pExcepInfo
,
4521 ICOM_THIS( ITypeInfoImpl
, iface
);
4522 TLBFuncDesc
* pFDesc
;
4523 TLBVarDesc
* pVDesc
;
4527 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4528 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4530 dump_DispParms(pDispParams
);
4532 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4533 if (pFDesc
->funcdesc
.memid
== memid
) {
4534 if (pFDesc
->funcdesc
.invkind
& dwFlags
)
4539 if (TRACE_ON(typelib
)) dump_TLBFuncDescOne(pFDesc
);
4540 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4541 switch (pFDesc
->funcdesc
.funckind
) {
4542 case FUNC_PUREVIRTUAL
:
4543 case FUNC_VIRTUAL
: {
4545 int numargs
, numargs2
, argspos
, args2pos
;
4546 DWORD
*args
, *args2
;
4549 numargs
= 1; numargs2
= 0;
4550 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4551 if (i
<pDispParams
->cArgs
)
4552 numargs
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4554 numargs
+= 1; /* sizeof(lpvoid) */
4555 numargs2
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4559 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4560 args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4562 args
[0] = (DWORD
)pIUnk
;
4563 argspos
= 1; args2pos
= 0;
4564 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4565 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4566 if (i
<pDispParams
->cArgs
) {
4567 VARIANT
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1];
4568 TYPEDESC
*tdesc
= &pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
;
4569 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4570 if (FAILED(hres
)) return hres
;
4573 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
4574 if (tdesc
->vt
!= VT_PTR
)
4575 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4576 /*FIXME: give pointers for the rest, so propertyget works*/
4577 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4579 /* If pointer to variant, pass reference it. */
4580 if ((tdesc
->vt
== VT_PTR
) &&
4581 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4584 args
[argspos
]= (DWORD
)pVarResult
;
4589 if (pFDesc
->funcdesc
.cParamsOpt
)
4590 FIXME("Does not support optional parameters (%d)\n",
4591 pFDesc
->funcdesc
.cParamsOpt
4594 res
= _invoke((*(FARPROC
**)pIUnk
)[pFDesc
->funcdesc
.oVft
/4],
4595 pFDesc
->funcdesc
.callconv
,
4599 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4601 for (i
=0;i
<pFDesc
->funcdesc
.cParams
-pDispParams
->cArgs
;i
++) {
4602 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4603 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
+pDispParams
->cArgs
].tdesc
);
4605 i4_tdesc
.vt
= VT_I4
;
4607 /* If we are a pointer to a variant, we are done already */
4608 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4611 VariantInit(pVarResult
);
4612 memcpy(&V_UNION(pVarResult
,intVal
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4614 if (tdesc
->vt
== VT_PTR
)
4615 tdesc
= tdesc
->u
.lptdesc
;
4616 if (tdesc
->vt
== VT_USERDEFINED
) {
4620 hres
= ITypeInfo_GetRefTypeInfo(iface
,tdesc
->u
.hreftype
,&tinfo2
);
4622 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc
->u
.hreftype
);
4625 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4626 switch (tattr
->typekind
) {
4628 /* force the return type to be VT_I4 */
4632 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr
->tdescAlias
.vt
);
4633 tdesc
= &(tattr
->tdescAlias
);
4636 case TKIND_INTERFACE
:
4637 FIXME("TKIND_INTERFACE unhandled.\n");
4639 case TKIND_DISPATCH
:
4640 FIXME("TKIND_DISPATCH unhandled.\n");
4643 FIXME("TKIND_RECORD unhandled.\n");
4646 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4649 ITypeInfo_Release(tinfo2
);
4651 V_VT(pVarResult
) = tdesc
->vt
;
4653 /* HACK: VB5 likes this.
4654 * I do not know why. There is 1 example in MSDN which uses
4655 * this which appears broken (mixes int vals and
4658 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4659 V_VT(pVarResult
) = VT_DISPATCH
;
4660 TRACE("storing into variant:\n");
4661 dump_Variant(pVarResult
);
4665 HeapFree(GetProcessHeap(),0,args2
);
4666 HeapFree(GetProcessHeap(),0,args
);
4669 case FUNC_DISPATCH
: {
4673 hr
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4675 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4678 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4679 hr
= IDispatch_Invoke(
4680 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4681 pVarResult
,pExcepInfo
,pArgErr
4684 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr
);
4685 IDispatch_Release(disp
);
4689 FIXME("Unknown function invocation type %d\n",pFDesc
->funcdesc
.funckind
);
4693 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4694 if (pVDesc
->vardesc
.memid
== memid
) {
4695 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR
)pVDesc
->Name
)));
4696 dump_TLBVarDesc(pVDesc
);
4701 /* not found, look for it in inherited interfaces */
4702 if (This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
) {
4703 /* recursive search */
4706 hr
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
4708 hr
=ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4709 ITypeInfo_Release(pTInfo
);
4712 WARN("Could not search inherited interface!\n");
4714 ERR("did not find member id %d, flags %d!\n", (int)memid
, dwFlags
);
4715 return DISP_E_MEMBERNOTFOUND
;
4718 /* ITypeInfo::GetDocumentation
4720 * Retrieves the documentation string, the complete Help file name and path,
4721 * and the context ID for the Help topic for a specified type description.
4723 * (Can be tested by the Visual Basic Editor in Word for instance.)
4725 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4726 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4727 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4729 ICOM_THIS( ITypeInfoImpl
, iface
);
4730 TLBFuncDesc
* pFDesc
;
4731 TLBVarDesc
* pVDesc
;
4732 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4733 " HelpContext(%p) HelpFile(%p)\n",
4734 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4735 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4737 *pBstrName
=SysAllocString(This
->Name
);
4739 *pBstrDocString
=SysAllocString(This
->DocString
);
4741 *pdwHelpContext
=This
->dwHelpContext
;
4743 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4745 }else {/* for a member */
4746 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4747 if(pFDesc
->funcdesc
.memid
==memid
){
4749 *pBstrName
= SysAllocString(pFDesc
->Name
);
4751 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4753 *pdwHelpContext
=pFDesc
->helpcontext
;
4756 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4757 if(pVDesc
->vardesc
.memid
==memid
){
4759 *pBstrName
= SysAllocString(pVDesc
->Name
);
4761 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
4763 *pdwHelpContext
=pVDesc
->HelpContext
;
4767 return TYPE_E_ELEMENTNOTFOUND
;
4770 /* ITypeInfo::GetDllEntry
4772 * Retrieves a description or specification of an entry point for a function
4775 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
4776 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
4779 ICOM_THIS( ITypeInfoImpl
, iface
);
4780 TLBFuncDesc
*pFDesc
;
4782 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
4784 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4785 if(pFDesc
->funcdesc
.memid
==memid
){
4786 dump_TypeInfo(This
);
4787 dump_TLBFuncDescOne(pFDesc
);
4789 /* FIXME: This is wrong, but how do you find that out? */
4791 const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4792 *pBstrDllName
= SysAllocString(oleaut32W
);
4795 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
4797 *pBstrName
= SysAllocString(pFDesc
->Entry
);
4805 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
4811 /* ITypeInfo::GetRefTypeInfo
4813 * If a type description references other type descriptions, it retrieves
4814 * the referenced type descriptions.
4816 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
4819 ITypeInfo
**ppTInfo
)
4821 ICOM_THIS( ITypeInfoImpl
, iface
);
4822 HRESULT result
= E_FAIL
;
4825 if (hRefType
== -1 &&
4826 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
4827 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
4829 /* when we meet a DUAL dispinterface, we must create the interface
4832 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
4835 /* the interface version contains the same information as the dispinterface
4836 * copy the contents of the structs.
4838 *pTypeInfoImpl
= *This
;
4839 pTypeInfoImpl
->ref
= 1;
4841 /* change the type to interface */
4842 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
4844 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
4846 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
4851 TLBRefType
*pRefType
;
4852 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
4853 if(pRefType
->reference
== hRefType
)
4857 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
4858 if(pRefType
&& hRefType
!= -1) {
4859 ITypeLib
*pTLib
= NULL
;
4861 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
4863 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
4865 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
4866 TRACE("typeinfo in imported typelib that is already loaded\n");
4867 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
4868 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
4871 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4872 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
4873 pRefType
->pImpTLInfo
->wVersionMajor
,
4874 pRefType
->pImpTLInfo
->wVersionMinor
,
4875 pRefType
->pImpTLInfo
->lcid
,
4878 if(!SUCCEEDED(result
)) {
4879 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
4880 result
=LoadTypeLib(libnam
, &pTLib
);
4881 SysFreeString(libnam
);
4883 if(SUCCEEDED(result
)) {
4884 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
4885 ITypeLib2_AddRef(pTLib
);
4889 if(SUCCEEDED(result
)) {
4890 if(pRefType
->index
== TLB_REF_USE_GUID
)
4891 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
4895 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
4899 ITypeLib2_Release(pTLib
);
4903 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
4904 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
4908 /* ITypeInfo::AddressOfMember
4910 * Retrieves the addresses of static functions or variables, such as those
4913 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
4914 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
4916 ICOM_THIS( ITypeInfoImpl
, iface
);
4917 FIXME("(%p) stub!\n", This
);
4921 /* ITypeInfo::CreateInstance
4923 * Creates a new instance of a type that describes a component object class
4926 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
4927 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
4929 ICOM_THIS( ITypeInfoImpl
, iface
);
4930 FIXME("(%p) stub!\n", This
);
4934 /* ITypeInfo::GetMops
4936 * Retrieves marshalling information.
4938 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
4941 ICOM_THIS( ITypeInfoImpl
, iface
);
4942 FIXME("(%p) stub!\n", This
);
4946 /* ITypeInfo::GetContainingTypeLib
4948 * Retrieves the containing type library and the index of the type description
4949 * within that type library.
4951 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
4952 ITypeLib
* *ppTLib
, UINT
*pIndex
)
4954 ICOM_THIS( ITypeInfoImpl
, iface
);
4956 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4958 *pIndex
=This
->index
;
4959 TRACE("returning pIndex=%d\n", *pIndex
);
4963 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
4964 ITypeLib2_AddRef(*ppTLib
);
4965 TRACE("returning ppTLib=%p\n", *ppTLib
);
4971 /* ITypeInfo::ReleaseTypeAttr
4973 * Releases a TYPEATTR previously returned by GetTypeAttr.
4976 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
4977 TYPEATTR
* pTypeAttr
)
4979 ICOM_THIS( ITypeInfoImpl
, iface
);
4980 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
4983 /* ITypeInfo::ReleaseFuncDesc
4985 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4987 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
4989 FUNCDESC
*pFuncDesc
)
4991 ICOM_THIS( ITypeInfoImpl
, iface
);
4992 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
4995 /* ITypeInfo::ReleaseVarDesc
4997 * Releases a VARDESC previously returned by GetVarDesc.
4999 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
5002 ICOM_THIS( ITypeInfoImpl
, iface
);
5003 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
5006 /* ITypeInfo2::GetTypeKind
5008 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5011 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
5012 TYPEKIND
*pTypeKind
)
5014 ICOM_THIS( ITypeInfoImpl
, iface
);
5015 *pTypeKind
=This
->TypeAttr
.typekind
;
5016 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
5020 /* ITypeInfo2::GetTypeFlags
5022 * Returns the type flags without any allocations. This returns a DWORD type
5023 * flag, which expands the type flags without growing the TYPEATTR (type
5027 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
5029 ICOM_THIS( ITypeInfoImpl
, iface
);
5030 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
5031 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
5035 /* ITypeInfo2::GetFuncIndexOfMemId
5036 * Binds to a specific member based on a known DISPID, where the member name
5037 * is not known (for example, when binding to a default member).
5040 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
5041 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
5043 ICOM_THIS( ITypeInfoImpl
, iface
);
5044 TLBFuncDesc
*pFuncInfo
;
5047 /* FIXME: should check for invKind??? */
5048 for(i
=0, pFuncInfo
=This
->funclist
;pFuncInfo
&&
5049 memid
!= pFuncInfo
->funcdesc
.memid
; i
++, pFuncInfo
=pFuncInfo
->next
);
5055 result
=E_INVALIDARG
;
5057 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
5058 memid
, invKind
, SUCCEEDED(result
)? "SUCCES":"FAILED");
5062 /* TypeInfo2::GetVarIndexOfMemId
5064 * Binds to a specific member based on a known DISPID, where the member name
5065 * is not known (for example, when binding to a default member).
5068 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
5069 MEMBERID memid
, UINT
*pVarIndex
)
5071 ICOM_THIS( ITypeInfoImpl
, iface
);
5072 TLBVarDesc
*pVarInfo
;
5075 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
5076 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
5083 result
=E_INVALIDARG
;
5085 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
5086 memid
, SUCCEEDED(result
)? "SUCCES":"FAILED");
5090 /* ITypeInfo2::GetCustData
5092 * Gets the custom data
5094 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
5099 ICOM_THIS( ITypeInfoImpl
, iface
);
5100 TLBCustData
*pCData
;
5102 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
5103 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5105 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5109 VariantInit( pVarVal
);
5110 VariantCopy( pVarVal
, &pCData
->data
);
5113 return E_INVALIDARG
; /* FIXME: correct? */
5116 /* ITypeInfo2::GetFuncCustData
5118 * Gets the custom data
5120 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
5126 ICOM_THIS( ITypeInfoImpl
, iface
);
5127 TLBCustData
*pCData
=NULL
;
5128 TLBFuncDesc
* pFDesc
;
5130 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5131 pFDesc
=pFDesc
->next
);
5134 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5135 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5137 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5140 VariantInit( pVarVal
);
5141 VariantCopy( pVarVal
, &pCData
->data
);
5144 return E_INVALIDARG
; /* FIXME: correct? */
5147 /* ITypeInfo2::GetParamCustData
5149 * Gets the custom data
5151 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
5158 ICOM_THIS( ITypeInfoImpl
, iface
);
5159 TLBCustData
*pCData
=NULL
;
5160 TLBFuncDesc
* pFDesc
;
5163 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5165 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5166 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5167 pCData
= pCData
->next
)
5168 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5170 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5174 VariantInit( pVarVal
);
5175 VariantCopy( pVarVal
, &pCData
->data
);
5178 return E_INVALIDARG
; /* FIXME: correct? */
5181 /* ITypeInfo2::GetVarCustData
5183 * Gets the custom data
5185 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5191 ICOM_THIS( ITypeInfoImpl
, iface
);
5192 TLBCustData
*pCData
=NULL
;
5193 TLBVarDesc
* pVDesc
;
5196 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5200 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5202 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5206 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5210 VariantInit( pVarVal
);
5211 VariantCopy( pVarVal
, &pCData
->data
);
5214 return E_INVALIDARG
; /* FIXME: correct? */
5217 /* ITypeInfo2::GetImplCustData
5219 * Gets the custom data
5221 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5227 ICOM_THIS( ITypeInfoImpl
, iface
);
5228 TLBCustData
*pCData
=NULL
;
5229 TLBImplType
* pRDesc
;
5232 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5236 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5238 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5242 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5246 VariantInit( pVarVal
);
5247 VariantCopy( pVarVal
, &pCData
->data
);
5250 return E_INVALIDARG
; /* FIXME: correct? */
5253 /* ITypeInfo2::GetDocumentation2
5255 * Retrieves the documentation string, the complete Help file name and path,
5256 * the localization context to use, and the context ID for the library Help
5257 * topic in the Help file.
5260 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5264 BSTR
*pbstrHelpString
,
5265 DWORD
*pdwHelpStringContext
,
5266 BSTR
*pbstrHelpStringDll
)
5268 ICOM_THIS( ITypeInfoImpl
, iface
);
5269 TLBFuncDesc
* pFDesc
;
5270 TLBVarDesc
* pVDesc
;
5271 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5272 "HelpStringContext(%p) HelpStringDll(%p)\n",
5273 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5274 pbstrHelpStringDll
);
5275 /* the help string should be obtained from the helpstringdll,
5276 * using the _DLLGetDocumentation function, based on the supplied
5277 * lcid. Nice to do sometime...
5279 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5281 *pbstrHelpString
=SysAllocString(This
->Name
);
5282 if(pdwHelpStringContext
)
5283 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5284 if(pbstrHelpStringDll
)
5285 *pbstrHelpStringDll
=
5286 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5288 }else {/* for a member */
5289 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5290 if(pFDesc
->funcdesc
.memid
==memid
){
5292 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5293 if(pdwHelpStringContext
)
5294 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5295 if(pbstrHelpStringDll
)
5296 *pbstrHelpStringDll
=
5297 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5300 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5301 if(pVDesc
->vardesc
.memid
==memid
){
5303 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5304 if(pdwHelpStringContext
)
5305 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5306 if(pbstrHelpStringDll
)
5307 *pbstrHelpStringDll
=
5308 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5312 return TYPE_E_ELEMENTNOTFOUND
;
5315 /* ITypeInfo2::GetAllCustData
5317 * Gets all custom data items for the Type info.
5320 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5322 CUSTDATA
*pCustData
)
5324 ICOM_THIS( ITypeInfoImpl
, iface
);
5325 TLBCustData
*pCData
;
5328 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5330 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5331 if(pCustData
->prgCustData
){
5332 pCustData
->cCustData
=This
->ctCustData
;
5333 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5334 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5335 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5338 ERR(" OUT OF MEMORY! \n");
5339 return E_OUTOFMEMORY
;
5344 /* ITypeInfo2::GetAllFuncCustData
5346 * Gets all custom data items for the specified Function
5349 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5352 CUSTDATA
*pCustData
)
5354 ICOM_THIS( ITypeInfoImpl
, iface
);
5355 TLBCustData
*pCData
;
5356 TLBFuncDesc
* pFDesc
;
5358 TRACE("(%p) index %d\n", This
, index
);
5359 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5360 pFDesc
=pFDesc
->next
)
5363 pCustData
->prgCustData
=
5364 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5365 if(pCustData
->prgCustData
){
5366 pCustData
->cCustData
=pFDesc
->ctCustData
;
5367 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5368 pCData
= pCData
->next
){
5369 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5370 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5374 ERR(" OUT OF MEMORY! \n");
5375 return E_OUTOFMEMORY
;
5379 return TYPE_E_ELEMENTNOTFOUND
;
5382 /* ITypeInfo2::GetAllParamCustData
5384 * Gets all custom data items for the Functions
5387 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5388 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5390 ICOM_THIS( ITypeInfoImpl
, iface
);
5391 TLBCustData
*pCData
=NULL
;
5392 TLBFuncDesc
* pFDesc
;
5394 TRACE("(%p) index %d\n", This
, indexFunc
);
5395 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5396 pFDesc
=pFDesc
->next
)
5398 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5399 pCustData
->prgCustData
=
5400 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5401 sizeof(CUSTDATAITEM
));
5402 if(pCustData
->prgCustData
){
5403 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5404 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5405 pCData
; i
++, pCData
= pCData
->next
){
5406 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5407 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5411 ERR(" OUT OF MEMORY! \n");
5412 return E_OUTOFMEMORY
;
5416 return TYPE_E_ELEMENTNOTFOUND
;
5419 /* ITypeInfo2::GetAllVarCustData
5421 * Gets all custom data items for the specified Variable
5424 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5425 UINT index
, CUSTDATA
*pCustData
)
5427 ICOM_THIS( ITypeInfoImpl
, iface
);
5428 TLBCustData
*pCData
;
5429 TLBVarDesc
* pVDesc
;
5431 TRACE("(%p) index %d\n", This
, index
);
5432 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5433 pVDesc
=pVDesc
->next
)
5436 pCustData
->prgCustData
=
5437 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5438 if(pCustData
->prgCustData
){
5439 pCustData
->cCustData
=pVDesc
->ctCustData
;
5440 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5441 pCData
= pCData
->next
){
5442 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5443 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5447 ERR(" OUT OF MEMORY! \n");
5448 return E_OUTOFMEMORY
;
5452 return TYPE_E_ELEMENTNOTFOUND
;
5455 /* ITypeInfo2::GetAllImplCustData
5457 * Gets all custom data items for the specified implementation type
5460 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5463 CUSTDATA
*pCustData
)
5465 ICOM_THIS( ITypeInfoImpl
, iface
);
5466 TLBCustData
*pCData
;
5467 TLBImplType
* pRDesc
;
5469 TRACE("(%p) index %d\n", This
, index
);
5470 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5471 pRDesc
=pRDesc
->next
)
5474 pCustData
->prgCustData
=
5475 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5476 if(pCustData
->prgCustData
){
5477 pCustData
->cCustData
=pRDesc
->ctCustData
;
5478 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5479 pCData
= pCData
->next
){
5480 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5481 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5485 ERR(" OUT OF MEMORY! \n");
5486 return E_OUTOFMEMORY
;
5490 return TYPE_E_ELEMENTNOTFOUND
;
5493 static ICOM_VTABLE(ITypeInfo2
) tinfvt
=
5495 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5497 ITypeInfo_fnQueryInterface
,
5499 ITypeInfo_fnRelease
,
5501 ITypeInfo_fnGetTypeAttr
,
5502 ITypeInfo_fnGetTypeComp
,
5503 ITypeInfo_fnGetFuncDesc
,
5504 ITypeInfo_fnGetVarDesc
,
5505 ITypeInfo_fnGetNames
,
5506 ITypeInfo_fnGetRefTypeOfImplType
,
5507 ITypeInfo_fnGetImplTypeFlags
,
5508 ITypeInfo_fnGetIDsOfNames
,
5510 ITypeInfo_fnGetDocumentation
,
5511 ITypeInfo_fnGetDllEntry
,
5512 ITypeInfo_fnGetRefTypeInfo
,
5513 ITypeInfo_fnAddressOfMember
,
5514 ITypeInfo_fnCreateInstance
,
5515 ITypeInfo_fnGetMops
,
5516 ITypeInfo_fnGetContainingTypeLib
,
5517 ITypeInfo_fnReleaseTypeAttr
,
5518 ITypeInfo_fnReleaseFuncDesc
,
5519 ITypeInfo_fnReleaseVarDesc
,
5521 ITypeInfo2_fnGetTypeKind
,
5522 ITypeInfo2_fnGetTypeFlags
,
5523 ITypeInfo2_fnGetFuncIndexOfMemId
,
5524 ITypeInfo2_fnGetVarIndexOfMemId
,
5525 ITypeInfo2_fnGetCustData
,
5526 ITypeInfo2_fnGetFuncCustData
,
5527 ITypeInfo2_fnGetParamCustData
,
5528 ITypeInfo2_fnGetVarCustData
,
5529 ITypeInfo2_fnGetImplTypeCustData
,
5530 ITypeInfo2_fnGetDocumentation2
,
5531 ITypeInfo2_fnGetAllCustData
,
5532 ITypeInfo2_fnGetAllFuncCustData
,
5533 ITypeInfo2_fnGetAllParamCustData
,
5534 ITypeInfo2_fnGetAllVarCustData
,
5535 ITypeInfo2_fnGetAllImplTypeCustData
,
5538 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5540 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5542 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
5545 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
5547 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5549 return ITypeInfo_AddRef((ITypeInfo
*)This
);
5552 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
5554 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5556 return ITypeInfo_Release((ITypeInfo
*)This
);
5559 static HRESULT WINAPI
ITypeComp_fnBind(
5562 unsigned long lHash
,
5563 unsigned short wFlags
,
5564 ITypeInfo
** ppTInfo
,
5565 DESCKIND
* pDescKind
,
5568 ICOM_THIS_From_ITypeComp(ITypeInfoImpl
, iface
);
5569 TLBFuncDesc
* pFDesc
;
5570 TLBVarDesc
* pVDesc
;
5572 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5574 for(pFDesc
= This
->funclist
; pFDesc
; pFDesc
= pFDesc
->next
)
5575 if (pFDesc
->funcdesc
.invkind
& wFlags
)
5576 if (!strcmpW(pFDesc
->Name
, szName
)) {
5582 *pDescKind
= DESCKIND_FUNCDESC
;
5583 pBindPtr
->lpfuncdesc
= &pFDesc
->funcdesc
;
5584 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5587 if (!(wFlags
& ~(INVOKE_PROPERTYGET
)))
5589 for(pVDesc
= This
->varlist
; pVDesc
; pVDesc
= pVDesc
->next
) {
5590 if (!strcmpW(pVDesc
->Name
, szName
)) {
5591 *pDescKind
= DESCKIND_VARDESC
;
5592 pBindPtr
->lpvardesc
= &pVDesc
->vardesc
;
5593 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
5599 /* not found, look for it in inherited interfaces */
5600 if ((This
->TypeAttr
.typekind
== TKIND_INTERFACE
) && This
->TypeAttr
.cImplTypes
) {
5601 /* recursive search */
5605 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypelist
->hRef
, &pTInfo
);
5608 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
5609 ITypeInfo_Release(pTInfo
);
5613 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5614 ITypeComp_Release(pTComp
);
5617 WARN("Could not search inherited interface!\n");
5619 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName
), wFlags
);
5620 *pDescKind
= DESCKIND_NONE
;
5621 pBindPtr
->lpfuncdesc
= NULL
;
5623 return DISP_E_MEMBERNOTFOUND
;
5626 static HRESULT WINAPI
ITypeComp_fnBindType(
5629 unsigned long lHash
,
5630 ITypeInfo
** ppTInfo
,
5631 ITypeComp
** ppTComp
)
5633 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5635 /* strange behaviour (does nothing) but like the
5638 if (!ppTInfo
|| !ppTComp
)
5647 static ICOM_VTABLE(ITypeComp
) tcompvt
=
5649 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5651 ITypeComp_fnQueryInterface
,
5653 ITypeComp_fnRelease
,
5656 ITypeComp_fnBindType