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"
63 #define NONAMELESSUNION
64 #define NONAMELESSSTRUCT
66 #include "winnls.h" /* for PRIMARYLANGID */
67 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
70 #include "wine/unicode.h"
75 #include "wine/debug.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
81 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
82 const GUID CLSID_PSOAInterface
= { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
84 /****************************************************************************
87 * Takes p_iVal (which is in little endian) and returns it
88 * in the host machine's byte order.
90 #ifdef WORDS_BIGENDIAN
91 static WORD
FromLEWord(WORD p_iVal
)
93 return (((p_iVal
& 0x00FF) << 8) |
94 ((p_iVal
& 0xFF00) >> 8));
98 static DWORD
FromLEDWord(DWORD p_iVal
)
100 return (((p_iVal
& 0x000000FF) << 24) |
101 ((p_iVal
& 0x0000FF00) << 8) |
102 ((p_iVal
& 0x00FF0000) >> 8) |
103 ((p_iVal
& 0xFF000000) >> 24));
106 #define FromLEWord(X) (X)
107 #define FromLEDWord(X) (X)
111 /****************************************************************************
114 * Fix byte order in any structure if necessary
116 #ifdef WORDS_BIGENDIAN
117 static void FromLEWords(void *p_Val
, int p_iSize
)
121 p_iSize
/= sizeof(WORD
);
124 *Val
= FromLEWord(*Val
);
131 static void FromLEDWords(void *p_Val
, int p_iSize
)
135 p_iSize
/= sizeof(DWORD
);
138 *Val
= FromLEDWord(*Val
);
144 #define FromLEWords(X,Y) /*nothing*/
145 #define FromLEDWords(X,Y) /*nothing*/
149 /****************************************************************************
150 * QueryPathOfRegTypeLib [OLEAUT32.164]
155 QueryPathOfRegTypeLib(
156 REFGUID guid
, /* [in] referenced guid */
157 WORD wMaj
, /* [in] major version */
158 WORD wMin
, /* [in] minor version */
159 LCID lcid
, /* [in] locale id */
160 LPBSTR path
) /* [out] path of typelib */
162 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
163 string termination character on output strings */
170 char szTypeLibKey
[100];
171 char szPath
[MAX_PATH
];
172 DWORD dwPathLen
= sizeof(szPath
);
180 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID
, wMaj
, wMin
, (DWORD
)lcid
, path
);
186 sprintf(szTypeLibKey
,
187 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
188 guid
->Data1
, guid
->Data2
, guid
->Data3
,
189 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
190 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
195 if (RegQueryValueA(HKEY_LOCAL_MACHINE
, szTypeLibKey
, szPath
, &dwPathLen
))
199 else if (myLCID
== lcid
)
201 /* try with sub-langid */
202 myLCID
= SUBLANGID(lcid
);
204 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
206 /* try with system langid */
216 DWORD len
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, szPath
, dwPathLen
, NULL
, 0 );
217 BSTR bstrPath
= SysAllocStringLen(NULL
,len
);
219 MultiByteToWideChar(CP_ACP
,
231 TRACE_(typelib
)("%s not found\n", szTypeLibKey
);
236 /******************************************************************************
237 * CreateTypeLib [OLEAUT32.160] creates a typelib
243 HRESULT WINAPI
CreateTypeLib(
244 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
246 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
249 /******************************************************************************
250 * LoadTypeLib [OLEAUT32.161]
251 * Loads and registers a type library
253 * Docs: OLECHAR FAR* szFile
254 * Docs: iTypeLib FAR* FAR* pptLib
260 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
262 HRESULT WINAPI
LoadTypeLib(
263 const OLECHAR
*szFile
,/* [in] Name of file to load from */
264 ITypeLib
* *pptLib
) /* [out] Pointer to pointer to loaded type library */
267 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
270 /******************************************************************************
271 * LoadTypeLibEx [OLEAUT32.183]
272 * Loads and optionally registers a type library
278 HRESULT WINAPI
LoadTypeLibEx(
279 LPCOLESTR szFile
, /* [in] Name of file to load from */
280 REGKIND regkind
, /* [in] Specify kind of registration */
281 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
283 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
288 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
289 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
292 /* Look for a trailing '\\' followed by an index */
293 pIndexStr
= strrchrW(szFile
, '\\');
294 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
295 index
= atoiW(pIndexStr
);
296 memcpy(szFileCopy
, szFile
,
297 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
298 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
299 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
301 return TYPE_E_CANTLOADLIBRARY
;
302 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
303 return TYPE_E_CANTLOADLIBRARY
;
306 WCHAR stdole32tlb
[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
309 lstrcpyW(tstpath
,szFile
);
311 for (i
=0;i
<strlenW(tstpath
);i
++) {
312 if (tstpath
[i
] == 's') {
313 if (!strcmpW(tstpath
+i
,stdole32tlb
)) {
315 MESSAGE("**************************************************************************\n");
316 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
317 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
318 MESSAGE("on the Microsoft Download Pages.\n");
319 MESSAGE("**************************************************************************\n");
324 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile
));
325 return TYPE_E_CANTLOADLIBRARY
;
329 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
331 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
336 case REGKIND_DEFAULT
:
337 /* FIXME: is this correct? */
338 if (!szFile
|| !szFile
[0] ||
339 (szFile
[0] != '\\' && szFile
[0] != '/' && szFile
[1] != ':'))
341 /* else fall-through */
342 case REGKIND_REGISTER
:
343 /* FIXME: Help path? */
344 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szFile
, NULL
)))
346 IUnknown_Release(*pptLib
);
354 TRACE(" returns %08lx\n",res
);
358 /******************************************************************************
359 * LoadRegTypeLib [OLEAUT32.162]
361 HRESULT WINAPI
LoadRegTypeLib(
362 REFGUID rguid
, /* [in] referenced guid */
363 WORD wVerMajor
, /* [in] major version */
364 WORD wVerMinor
, /* [in] minor version */
365 LCID lcid
, /* [in] locale id */
366 ITypeLib
**ppTLib
) /* [out] path of typelib */
369 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
373 res
= LoadTypeLib(bstr
, ppTLib
);
377 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
383 /******************************************************************************
384 * RegisterTypeLib [OLEAUT32.163]
385 * Adds information about a type library to the System Registry
387 * Docs: ITypeLib FAR * ptlib
388 * Docs: OLECHAR FAR* szFullPath
389 * Docs: OLECHAR FAR* szHelpDir
395 HRESULT WINAPI
RegisterTypeLib(
396 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
397 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
398 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
409 static const char *PSOA
= "{00020424-0000-0000-C000-000000000046}";
411 if (ptlib
== NULL
|| szFullPath
== NULL
)
414 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
417 StringFromGUID2(&attr
->guid
, guid
, 80);
418 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
419 snprintf(keyName
, sizeof(keyName
), "TypeLib\\%s\\%x.%x",
420 guidA
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
421 HeapFree(GetProcessHeap(), 0, guidA
);
424 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
425 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
429 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
431 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
432 (BYTE
*)doc
, lstrlenW(doc
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
440 /* FIXME: This *seems* to be 0 always, not sure though */
441 if (res
== S_OK
&& RegCreateKeyExA(key
, "0\\win32", 0, NULL
, 0,
442 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
444 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
445 (BYTE
*)szFullPath
, lstrlenW(szFullPath
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
453 if (res
== S_OK
&& RegCreateKeyExA(key
, "FLAGS", 0, NULL
, 0,
454 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
457 /* FIXME: is %u correct? */
458 snprintf(buf
, sizeof(buf
), "%u", attr
->wLibFlags
);
459 if (RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
460 buf
, lstrlenA(buf
) + 1) != ERROR_SUCCESS
)
468 /* register OLE Automation-compatible interfaces for this typelib */
469 types
= ITypeLib_GetTypeInfoCount(ptlib
);
470 for (tidx
=0; tidx
<types
; tidx
++) {
471 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
472 LPOLESTR name
= NULL
;
473 ITypeInfo
*tinfo
= NULL
;
475 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
477 case TKIND_INTERFACE
:
478 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
479 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
482 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
483 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
486 TRACE_(typelib
)("%d: coclass %s\n", tidx
, debugstr_w(name
));
487 /* coclasses should probably not be registered? */
490 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
494 TYPEATTR
*tattr
= NULL
;
495 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
497 TRACE_(typelib
)("guid=%s, flags=%04x (",
498 debugstr_guid(&tattr
->guid
),
500 if (TRACE_ON(typelib
)) {
501 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
521 * FIXME: The 1 is just here until we implement rpcrt4
522 * stub/proxy handling. Until then it helps IShield
525 if (1 || (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
))
527 /* register interface<->typelib coupling */
528 StringFromGUID2(&tattr
->guid
, guid
, 80);
529 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
530 snprintf(keyName
, sizeof(keyName
), "Interface\\%s", guidA
);
531 HeapFree(GetProcessHeap(), 0, guidA
);
533 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
534 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
536 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
537 (BYTE
*)name
, lstrlenW(name
) * sizeof(OLECHAR
));
539 if (RegCreateKeyExA(key
, "ProxyStubClsid", 0, NULL
, 0,
540 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
541 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
545 if (RegCreateKeyExA(key
, "ProxyStubClsid32", 0, NULL
, 0,
546 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
547 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
552 if (RegCreateKeyExA(key
, "TypeLib", 0, NULL
, 0,
553 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
555 StringFromGUID2(&attr
->guid
, guid
, 80);
556 snprintf(ver
, sizeof(ver
), "%x.%x",
557 attr
->wMajorVerNum
, attr
->wMinorVerNum
);
558 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
559 (BYTE
*)guid
, lstrlenW(guid
) * sizeof(OLECHAR
));
560 RegSetValueExA(subKey
, "Version", 0, REG_SZ
,
567 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
569 ITypeInfo_Release(tinfo
);
576 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
582 /******************************************************************************
583 * UnRegisterTypeLib [OLEAUT32.186]
584 * Removes information about a type library from the System Registry
591 HRESULT WINAPI
UnRegisterTypeLib(
592 REFGUID libid
, /* [in] Guid of the library */
593 WORD wVerMajor
, /* [in] major version */
594 WORD wVerMinor
, /* [in] minor version */
595 LCID lcid
, /* [in] locale id */
598 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
599 return S_OK
; /* FIXME: pretend everything is OK */
602 /*======================= ITypeLib implementation =======================*/
604 typedef struct tagTLBCustData
608 struct tagTLBCustData
* next
;
611 /* data structure for import typelibs */
612 typedef struct tagTLBImpLib
614 int offset
; /* offset in the file (MSFT)
615 offset in nametable (SLTG)
616 just used to identify library while reading
618 GUID guid
; /* libid */
619 BSTR name
; /* name */
621 LCID lcid
; /* lcid of imported typelib */
623 WORD wVersionMajor
; /* major version number */
624 WORD wVersionMinor
; /* minor version number */
626 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
627 NULL if not yet loaded */
628 struct tagTLBImpLib
* next
;
631 /* internal ITypeLib data */
632 typedef struct tagITypeLibImpl
634 ICOM_VFIELD(ITypeLib2
);
636 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
638 /* strings can be stored in tlb as multibyte strings BUT they are *always*
639 * exported to the application as a UNICODE string.
645 unsigned long dwHelpContext
;
646 int TypeInfoCount
; /* nr of typeinfo's in librarry */
647 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
648 int ctCustData
; /* number of items in cust data list */
649 TLBCustData
* pCustData
; /* linked list to cust data */
650 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
651 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
652 libary. Only used while read MSFT
656 static struct ICOM_VTABLE(ITypeLib2
) tlbvt
;
658 /* ITypeLib methods */
659 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
660 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
662 /*======================= ITypeInfo implementation =======================*/
664 /* data for refernced types */
665 typedef struct tagTLBRefType
667 INT index
; /* Type index for internal ref or for external ref
668 it the format is SLTG. -2 indicates to
671 GUID guid
; /* guid of the referenced type */
672 /* if index == TLB_REF_USE_GUID */
674 HREFTYPE reference
; /* The href of this ref */
675 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
676 TLB_REF_INTERNAL for internal refs
677 TLB_REF_NOT_FOUND for broken refs */
679 struct tagTLBRefType
* next
;
682 #define TLB_REF_USE_GUID -2
684 #define TLB_REF_INTERNAL (void*)-2
685 #define TLB_REF_NOT_FOUND (void*)-1
687 /* internal Parameter data */
688 typedef struct tagTLBParDesc
692 TLBCustData
* pCustData
; /* linked list to cust data */
695 /* internal Function data */
696 typedef struct tagTLBFuncDesc
698 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
699 BSTR Name
; /* the name of this function */
700 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
702 int HelpStringContext
;
704 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
706 TLBCustData
* pCustData
; /* linked list to cust data; */
707 struct tagTLBFuncDesc
* next
;
710 /* internal Variable data */
711 typedef struct tagTLBVarDesc
713 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
714 BSTR Name
; /* the name of this variable */
716 int HelpStringContext
; /* FIXME: where? */
719 TLBCustData
* pCustData
;/* linked list to cust data; */
720 struct tagTLBVarDesc
* next
;
723 /* internal implemented interface data */
724 typedef struct tagTLBImplType
726 HREFTYPE hRef
; /* hRef of interface */
727 int implflags
; /* IMPLFLAG_*s */
729 TLBCustData
* pCustData
;/* linked list to custom data; */
730 struct tagTLBImplType
*next
;
733 /* internal TypeInfo data */
734 typedef struct tagITypeInfoImpl
736 ICOM_VFIELD(ITypeInfo2
);
738 TYPEATTR TypeAttr
; /* _lots_ of type information. */
739 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
740 int index
; /* index in this typelib; */
741 /* type libs seem to store the doc strings in ascii
742 * so why should we do it in unicode?
746 unsigned long dwHelpContext
;
747 unsigned long dwHelpStringContext
;
750 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
753 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
755 /* Implemented Interfaces */
756 TLBImplType
* impltypelist
;
758 TLBRefType
* reflist
;
760 TLBCustData
* pCustData
; /* linked list to cust data; */
761 struct tagITypeInfoImpl
* next
;
764 static struct ICOM_VTABLE(ITypeInfo2
) tinfvt
;
766 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor();
768 typedef struct tagTLBContext
770 unsigned int oStart
; /* start of TLB in file */
771 unsigned int pos
; /* current pos */
772 unsigned int length
; /* total length */
773 void *mapping
; /* memory mapping */
774 MSFT_SegDir
* pTblDir
;
775 ITypeLibImpl
* pLibInfo
;
779 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
784 static void dump_VarType(VARTYPE vt
,char *szVarType
) {
785 /* FIXME : we could have better trace here, depending on the VARTYPE
788 if (vt
& VT_RESERVED
)
789 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
791 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
793 szVarType
+= strlen(strcpy(szVarType
, "array of "));
795 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
796 switch(vt
& VT_TYPEMASK
) {
797 case VT_UI1
: sprintf(szVarType
, "VT_UI"); break;
798 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
799 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
800 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
801 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
802 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
803 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
804 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
805 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
806 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
807 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
808 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
809 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
810 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
811 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
812 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
813 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
814 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
815 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
816 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED\n"); break;
817 default: sprintf(szVarType
, "unknown(%d)", vt
& VT_TYPEMASK
); break;
821 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
822 if (pTD
->vt
& VT_RESERVED
)
823 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
824 if (pTD
->vt
& VT_BYREF
)
825 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
826 if (pTD
->vt
& VT_ARRAY
)
827 szVarType
+= strlen(strcpy(szVarType
, "array of "));
828 if (pTD
->vt
& VT_VECTOR
)
829 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
830 switch(pTD
->vt
& VT_TYPEMASK
) {
831 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
832 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
833 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
834 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
835 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
836 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
837 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
838 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
839 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
840 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
841 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
842 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
843 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
844 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
845 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
846 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
847 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
848 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
849 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
850 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
851 pTD
->u
.hreftype
); break;
852 case VT_PTR
: sprintf(szVarType
, "ptr to ");
853 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
855 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
856 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
858 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
859 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
860 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
863 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
867 void dump_ELEMDESC(ELEMDESC
*edesc
) {
869 dump_TypeDesc(&edesc
->tdesc
,buf
);
870 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
871 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
872 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
874 void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
876 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
877 for (i
=0;i
<funcdesc
->cParams
;i
++) {
878 MESSAGE("Param %d:\n",i
);
879 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
881 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
882 switch (funcdesc
->funckind
) {
883 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
884 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
885 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
886 case FUNC_STATIC
: MESSAGE("static");break;
887 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
888 default: MESSAGE("unknown");break;
890 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
891 switch (funcdesc
->invkind
) {
892 case INVOKE_FUNC
: MESSAGE("func");break;
893 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
894 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
895 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
897 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
898 switch (funcdesc
->callconv
) {
899 case CC_CDECL
: MESSAGE("cdecl");break;
900 case CC_PASCAL
: MESSAGE("pascal");break;
901 case CC_STDCALL
: MESSAGE("stdcall");break;
902 case CC_SYSCALL
: MESSAGE("syscall");break;
905 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
906 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
907 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
910 void dump_IDLDESC(IDLDESC
*idl
) {
911 MESSAGE("\t\twIdlflags: %d\n",idl
->wIDLFlags
);
914 static char * typekind_desc
[] =
927 void dump_TYPEATTR(TYPEATTR
*tattr
) {
929 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr
->guid
));
930 MESSAGE("\tlcid: %ld\n",tattr
->lcid
);
931 MESSAGE("\tmemidConstructor: %ld\n",tattr
->memidConstructor
);
932 MESSAGE("\tmemidDestructor: %ld\n",tattr
->memidDestructor
);
933 MESSAGE("\tschema: %s\n",debugstr_w(tattr
->lpstrSchema
));
934 MESSAGE("\tsizeInstance: %ld\n",tattr
->cbSizeInstance
);
935 MESSAGE("\tkind:%s\n", typekind_desc
[tattr
->typekind
]);
936 MESSAGE("\tcFuncs: %d\n", tattr
->cFuncs
);
937 MESSAGE("\tcVars: %d\n", tattr
->cVars
);
938 MESSAGE("\tcImplTypes: %d\n", tattr
->cImplTypes
);
939 MESSAGE("\tcbSizeVft: %d\n", tattr
->cbSizeVft
);
940 MESSAGE("\tcbAlignment: %d\n", tattr
->cbAlignment
);
941 MESSAGE("\twTypeFlags: %d\n", tattr
->wTypeFlags
);
942 MESSAGE("\tVernum: %d.%d\n", tattr
->wMajorVerNum
,tattr
->wMinorVerNum
);
943 dump_TypeDesc(&tattr
->tdescAlias
,buf
);
944 MESSAGE("\ttypedesc: %s\n", buf
);
945 dump_IDLDESC(&tattr
->idldescType
);
948 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
951 if (!TRACE_ON(typelib
))
953 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
954 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
955 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
958 dump_FUNCDESC(&(pfd
->funcdesc
));
960 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
961 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
963 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
967 dump_TLBFuncDescOne(pfd
);
971 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
975 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
980 static void dump_TLBImpLib(TLBImpLib
*import
)
982 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
983 debugstr_w(import
->name
));
984 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
985 import
->wVersionMinor
, import
->lcid
, import
->offset
);
988 static void dump_TLBRefType(TLBRefType
* prt
)
992 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
994 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
996 TRACE_(typelib
)("type no: %d\n", prt
->index
);
998 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
999 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
1000 TRACE_(typelib
)("in lib\n");
1001 dump_TLBImpLib(prt
->pImpTLInfo
);
1007 static void dump_TLBImplType(TLBImplType
* impl
)
1011 "implementing/inheriting interface hRef = %lx implflags %x\n",
1012 impl
->hRef
, impl
->implflags
);
1017 void dump_Variant(VARIANT
* pvar
)
1022 TRACE("(%p)\n", pvar
);
1026 ZeroMemory(szVarType
, sizeof(szVarType
));
1028 /* FIXME : we could have better trace here, depending on the VARTYPE
1031 dump_VarType(V_VT(pvar
),szVarType
);
1033 TRACE("VARTYPE: %s\n", szVarType
);
1035 if (V_VT(pvar
) & VT_BYREF
) {
1036 ref
= V_UNION(pvar
, byref
);
1039 else ref
= &V_UNION(pvar
, cVal
);
1041 if (V_VT(pvar
) & VT_ARRAY
) {
1045 if (V_VT(pvar
) & VT_VECTOR
) {
1050 switch (V_VT(pvar
) & VT_TYPEMASK
)
1053 TRACE("%d\n", *(short*)ref
);
1058 TRACE("%u\n", *(UINT
*)ref
);
1063 TRACE("%d\n", *(INT
*)ref
);
1067 TRACE("%3.3e\n", *(float*)ref
);
1071 TRACE("%3.3e\n", *(double*)ref
);
1075 TRACE("%s\n", *(VARIANT_BOOL
*)ref
? "TRUE" : "FALSE");
1079 TRACE("%s\n", debugstr_w(*(BSTR
*)ref
));
1084 TRACE("%p\n", *(LPVOID
*)ref
);
1088 if (V_VT(pvar
) & VT_BYREF
) dump_Variant(ref
);
1094 memset( &TM
, 0, sizeof(TM
) );
1096 if( DateToTm( *(DATE
*)ref
, 0, &TM
) == FALSE
) {
1097 TRACE("invalid date? (?)%ld %f\n", *(long*)ref
, *(double *)ref
);
1099 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1100 TM
.tm_year
, TM
.tm_mon
+1, TM
.tm_mday
,
1101 TM
.tm_hour
, TM
.tm_min
, TM
.tm_sec
, *(double *)ref
);
1107 TRACE("%ld (hi), %lu (lo)\n", ((CY
*)ref
)->s
.Hi
, ((CY
*)ref
)->s
.Lo
);
1112 TRACE("(?)%ld\n", *(long*)ref
);
1117 static void dump_DispParms(DISPPARAMS
* pdp
)
1121 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1123 while (index
< pdp
->cArgs
)
1125 dump_Variant( &pdp
->rgvarg
[index
] );
1130 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1132 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1133 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1134 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1135 TRACE("fct:%u var:%u impl:%u\n",
1136 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1137 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1138 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1139 dump_TLBFuncDesc(pty
->funclist
);
1140 dump_TLBVarDesc(pty
->varlist
);
1141 dump_TLBImplType(pty
->impltypelist
);
1144 void dump_VARDESC(VARDESC
*v
)
1146 MESSAGE("memid %ld\n",v
->memid
);
1147 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1148 MESSAGE("oInst %ld\n",v
->u
.oInst
);
1149 dump_ELEMDESC(&(v
->elemdescVar
));
1150 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1151 MESSAGE("varkind %d\n",v
->varkind
);
1154 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1156 /* VT_LPWSTR is largest type that */
1157 /* may appear in type description*/
1158 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1159 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1160 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1161 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1162 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1163 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1167 static void TLB_abort()
1171 static void * TLB_Alloc(unsigned size
)
1174 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1176 ERR("cannot allocate memory\n");
1181 static void TLB_Free(void * ptr
)
1183 HeapFree(GetProcessHeap(), 0, ptr
);
1187 /**********************************************************************
1189 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1192 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1194 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1195 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1197 if (where
!= DO_NOT_SEEK
)
1199 where
+= pcx
->oStart
;
1200 if (where
> pcx
->length
)
1203 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1208 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1209 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1214 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1219 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1220 FromLEDWords(buffer
, ret
);
1225 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1230 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1231 FromLEWords(buffer
, ret
);
1236 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1238 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1239 memset(pGuid
,0, sizeof(GUID
));
1242 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1243 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1244 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1245 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1246 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1249 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1252 MSFT_NameIntro niName
;
1254 WCHAR
* pwstring
= NULL
;
1255 BSTR bstrName
= NULL
;
1257 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1258 pcx
->pTblDir
->pNametab
.offset
+offset
);
1259 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1260 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1261 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1262 name
[niName
.namelen
& 0xff]='\0';
1264 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1267 /* no invalid characters in string */
1270 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1272 /* don't check for invalid character since this has been done previously */
1273 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1275 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1276 lengthInChars
= SysStringLen(bstrName
);
1277 HeapFree(GetProcessHeap(), 0, pwstring
);
1280 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1284 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1291 if(offset
<0) return NULL
;
1292 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1293 if(length
<= 0) return 0;
1294 string
=TLB_Alloc(length
+1);
1295 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1296 string
[length
]='\0';
1298 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1299 string
, -1, NULL
, 0);
1301 /* no invalid characters in string */
1304 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1306 /* don't check for invalid character since this has been done previously */
1307 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1309 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1310 lengthInChars
= SysStringLen(bstr
);
1311 HeapFree(GetProcessHeap(), 0, pwstring
);
1314 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1318 * read a value and fill a VARIANT structure
1320 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1324 TRACE_(typelib
)("\n");
1326 if(offset
<0) { /* data are packed in here */
1327 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1328 V_UNION(pVar
, iVal
) = offset
& 0xffff;
1331 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1332 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1333 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1334 switch (V_VT(pVar
)){
1335 case VT_EMPTY
: /* FIXME: is this right? */
1336 case VT_NULL
: /* FIXME: is this right? */
1337 case VT_I2
: /* this should not happen */
1348 case VT_VOID
: /* FIXME: is this right? */
1356 case VT_DECIMAL
: /* FIXME: is this right? */
1359 /* pointer types with known behaviour */
1362 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1364 FIXME("BSTR length = %d?\n", size
);
1366 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1367 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1368 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1369 /* FIXME: do we need a AtoW conversion here? */
1370 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1371 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1376 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1383 case VT_USERDEFINED
:
1389 case VT_STREAMED_OBJECT
:
1390 case VT_STORED_OBJECT
:
1391 case VT_BLOB_OBJECT
:
1396 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1400 if(size
>0) /* (big|small) endian correct? */
1401 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1405 * create a linked list with custom data
1407 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1413 TRACE_(typelib
)("\n");
1417 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1418 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1419 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1420 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1421 /* add new custom data at head of the list */
1422 pNew
->next
=*ppCustData
;
1424 offset
= entry
.next
;
1429 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1433 pTd
->vt
=type
& VT_TYPEMASK
;
1435 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1437 if(pTd
->vt
== VT_USERDEFINED
)
1438 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1440 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1444 MSFT_DoFuncs(TLBContext
* pcx
,
1449 TLBFuncDesc
** pptfd
)
1452 * member information is stored in a data structure at offset
1453 * indicated by the memoffset field of the typeinfo structure
1454 * There are several distinctive parts.
1455 * the first part starts with a field that holds the total length
1456 * of this (first) part excluding this field. Then follow the records,
1457 * for each member there is one record.
1459 * First entry is always the length of the record (excluding this
1461 * Rest of the record depends on the type of the member. If there is
1462 * a field indicating the member type (function variable intereface etc)
1463 * I have not found it yet. At this time we depend on the information
1464 * in the type info and the usual order how things are stored.
1466 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1469 * Third is a equal sized array with file offsets to the name entry
1472 * Forth and last (?) part is an array with offsets to the records in the
1473 * first part of this file segment.
1476 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1477 int recoffset
= offset
+ sizeof(INT
);
1480 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1482 TRACE_(typelib
)("\n");
1484 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
1486 for ( i
= 0; i
< cFuncs
; i
++ )
1488 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1490 /* name, eventually add to a hash table */
1491 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1492 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1494 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1496 /* read the function information record */
1497 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1501 MSFT_ReadLEDWords(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1503 /* do the attributes */
1504 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1507 if ( nrattributes
> 0 )
1509 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1511 if ( nrattributes
> 1 )
1513 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1514 pFuncRec
->OptAttr
[1]) ;
1516 if ( nrattributes
> 2 )
1518 if ( pFuncRec
->FKCCIC
& 0x2000 )
1520 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1524 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1525 pFuncRec
->OptAttr
[2]);
1527 if( nrattributes
> 5 )
1529 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1531 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1534 pFuncRec
->OptAttr
[6],
1535 &(*pptfd
)->pCustData
);
1542 /* fill the FuncDesc Structure */
1543 MSFT_ReadLEDWords( & (*pptfd
)->funcdesc
.memid
, sizeof(INT
), pcx
,
1544 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1546 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1547 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1548 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1549 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1550 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1551 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1552 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1556 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1559 /* do the parameters/arguments */
1560 if(pFuncRec
->nrargs
)
1563 MSFT_ParameterInfo paraminfo
;
1565 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1566 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1568 (*pptfd
)->pParamDesc
=
1569 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1571 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
1572 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1574 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1576 TYPEDESC
* lpArgTypeDesc
= 0;
1580 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1583 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1585 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1587 /* SEEK value = jump to offset,
1588 * from there jump to the end of record,
1589 * go back by (j-1) arguments
1591 MSFT_ReadLEDWords( ¶minfo
,
1592 sizeof(MSFT_ParameterInfo
), pcx
,
1593 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1594 * sizeof(MSFT_ParameterInfo
)));
1596 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1598 while ( lpArgTypeDesc
!= NULL
)
1600 switch ( lpArgTypeDesc
->vt
)
1603 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1607 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1610 case VT_USERDEFINED
:
1611 MSFT_DoRefType(pcx
, pTI
,
1612 lpArgTypeDesc
->u
.hreftype
);
1614 lpArgTypeDesc
= NULL
;
1618 lpArgTypeDesc
= NULL
;
1624 /* parameter is the return value! */
1625 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1627 TYPEDESC
* lpArgTypeDesc
;
1629 (*pptfd
)->funcdesc
.elemdescFunc
=
1630 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1632 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1634 while ( lpArgTypeDesc
!= NULL
)
1636 switch ( lpArgTypeDesc
->vt
)
1639 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1643 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1647 case VT_USERDEFINED
:
1650 lpArgTypeDesc
->u
.hreftype
);
1652 lpArgTypeDesc
= NULL
;
1656 lpArgTypeDesc
= NULL
;
1661 /* second time around */
1662 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1665 (*pptfd
)->pParamDesc
[j
].Name
=
1666 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1669 if ( (PARAMFLAG_FHASDEFAULT
&
1670 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1671 ((pFuncRec
->FKCCIC
) & 0x1000) )
1673 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1675 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1677 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1679 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1680 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1682 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1686 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1689 pFuncRec
->OptAttr
[7+j
],
1690 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1695 /* scode is not used: archaic win16 stuff FIXME: right? */
1696 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1697 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1699 pptfd
= & ((*pptfd
)->next
);
1700 recoffset
+= reclength
;
1703 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1704 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1706 int infolen
, nameoffset
, reclength
;
1708 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1712 TRACE_(typelib
)("\n");
1714 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
1715 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1716 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1717 recoffset
+= offset
+sizeof(INT
);
1718 for(i
=0;i
<cVars
;i
++){
1719 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1720 /* name, eventually add to a hash table */
1721 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
1722 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1723 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1724 /* read the variable information record */
1725 MSFT_ReadLEDWords(&reclength
, sizeof(INT
), pcx
, recoffset
);
1727 MSFT_ReadLEDWords(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
);
1729 if(reclength
>(6*sizeof(INT
)) )
1730 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1731 if(reclength
>(7*sizeof(INT
)) )
1732 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1733 if(reclength
>(8*sizeof(INT
)) )
1734 if(reclength
>(9*sizeof(INT
)) )
1735 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1736 /* fill the VarDesc Structure */
1737 MSFT_ReadLEDWords(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1738 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1739 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1740 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1741 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1742 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1743 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1744 if(pVarRec
->VarKind
== VAR_CONST
){
1745 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1746 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1747 pVarRec
->OffsValue
, pcx
);
1749 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1750 pptvd
=&((*pptvd
)->next
);
1751 recoffset
+= reclength
;
1754 /* fill in data for a hreftype (offset). When the refernced type is contained
1755 * in the typelib, it's just an (file) offset in the type info base dir.
1756 * If comes from import, it's an offset+1 in the ImpInfo table
1758 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1762 TLBRefType
**ppRefType
= &pTI
->reflist
;
1764 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1767 if((*ppRefType
)->reference
== offset
)
1769 ppRefType
= &(*ppRefType
)->next
;
1772 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1773 sizeof(**ppRefType
));
1775 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1776 /* external typelib */
1777 MSFT_ImpInfo impinfo
;
1778 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1780 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1782 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
1783 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1784 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1785 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1786 pImpLib
=pImpLib
->next
;
1789 (*ppRefType
)->reference
=offset
;
1790 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1791 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1792 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1794 ERR("Cannot find a reference\n");
1795 (*ppRefType
)->reference
=-1;
1796 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1799 /* in this typelib */
1800 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1801 (*ppRefType
)->reference
=offset
;
1802 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1806 /* process Implemented Interfaces of a com class */
1807 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1811 MSFT_RefRecord refrec
;
1812 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1814 TRACE_(typelib
)("\n");
1816 for(i
=0;i
<count
;i
++){
1817 if(offset
<0) break; /* paranoia */
1818 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1819 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1820 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1821 (*ppImpl
)->hRef
= refrec
.reftype
;
1822 (*ppImpl
)->implflags
=refrec
.flags
;
1823 (*ppImpl
)->ctCustData
=
1824 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1825 offset
=refrec
.onext
;
1826 ppImpl
=&((*ppImpl
)->next
);
1830 * process a typeinfo record
1832 ITypeInfoImpl
* MSFT_DoTypeInfo(
1835 ITypeLibImpl
* pLibInfo
)
1837 MSFT_TypeInfoBase tiBase
;
1838 ITypeInfoImpl
*ptiRet
;
1840 TRACE_(typelib
)("count=%u\n", count
);
1842 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
1843 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
1844 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
1845 /* this is where we are coming from */
1846 ptiRet
->pTypeLib
= pLibInfo
;
1847 ptiRet
->index
=count
;
1848 /* fill in the typeattr fields */
1849 FIXME("Assign constructor/destructor memid\n");
1851 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
1852 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
1853 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
1854 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
1855 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
1856 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
1857 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
1858 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
1859 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
1860 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
1861 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
1862 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
1863 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
1864 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
1865 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
1866 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
1867 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
1868 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
1871 /* IDLDESC idldescType; *//* never saw this one != zero */
1873 /* name, eventually add to a hash table */
1874 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
1875 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
1877 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
1878 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
1879 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
1880 /* note: InfoType's Help file and HelpStringDll come from the containing
1881 * library. Further HelpString and Docstring appear to be the same thing :(
1884 if(ptiRet
->TypeAttr
.cFuncs
>0 )
1885 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1886 ptiRet
->TypeAttr
.cVars
,
1887 tiBase
.memoffset
, & ptiRet
->funclist
);
1889 if(ptiRet
->TypeAttr
.cVars
>0 )
1890 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1891 ptiRet
->TypeAttr
.cVars
,
1892 tiBase
.memoffset
, & ptiRet
->varlist
);
1893 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
1894 switch(ptiRet
->TypeAttr
.typekind
)
1897 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
1900 case TKIND_DISPATCH
:
1901 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1903 if (tiBase
.datatype1
!= -1)
1905 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1906 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1909 { /* FIXME: This is a really bad hack to add IDispatch */
1910 char* szStdOle
= "stdole2.tlb\0";
1911 int nStdOleLen
= strlen(szStdOle
);
1912 TLBRefType
**ppRef
= &ptiRet
->reflist
;
1915 if((*ppRef
)->reference
== -1)
1917 ppRef
= &(*ppRef
)->next
;
1920 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
1921 (*ppRef
)->guid
= IID_IDispatch
;
1922 (*ppRef
)->reference
= -1;
1923 (*ppRef
)->index
= TLB_REF_USE_GUID
;
1924 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
1925 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
1926 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
1929 MultiByteToWideChar(CP_ACP
,
1933 (*ppRef
)->pImpTLInfo
->name
,
1934 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
1936 (*ppRef
)->pImpTLInfo
->lcid
= 0;
1937 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
1938 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
1943 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1944 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1945 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1950 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
1952 TRACE_(typelib
)("%s guid: %s kind:%s\n",
1953 debugstr_w(ptiRet
->Name
),
1954 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
1955 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
1960 /****************************************************************************
1963 * find the type of the typelib file and map the typelib resource into
1966 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1967 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1968 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
1970 int ret
= TYPE_E_CANTLOADLIBRARY
;
1971 DWORD dwSignature
= 0;
1974 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
1978 /* check the signature of the file */
1979 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
1980 if (INVALID_HANDLE_VALUE
!= hFile
)
1982 HANDLE hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
1985 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
1988 /* retrieve file size */
1989 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
1991 /* first try to load as *.tlb */
1992 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
1993 if ( dwSignature
== MSFT_SIGNATURE
)
1995 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
1997 else if ( dwSignature
== SLTG_SIGNATURE
)
1999 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2001 UnmapViewOfFile(pBase
);
2003 CloseHandle(hMapping
);
2008 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
2010 /* find the typelibrary resource*/
2011 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2012 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
2015 HRSRC hrsrc
= FindResourceA(hinstDLL
, MAKEINTRESOURCEA(index
),
2019 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
2022 LPVOID pBase
= LockResource(hGlobal
);
2023 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
2027 /* try to load as incore resource */
2028 dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2029 if ( dwSignature
== MSFT_SIGNATURE
)
2031 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2033 else if ( dwSignature
== SLTG_SIGNATURE
)
2035 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2039 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
2042 FreeResource( hGlobal
);
2045 FreeLibrary(hinstDLL
);
2052 ERR("Loading of typelib %s failed with error %ld\n",
2053 debugstr_w(pszFileName
), GetLastError());
2058 /*================== ITypeLib(2) Methods ===================================*/
2060 /****************************************************************************
2061 * ITypeLib2_Constructor_MSFT
2063 * loading an MSFT typelib from an in-memory image
2065 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2069 MSFT_Header tlbHeader
;
2070 MSFT_SegDir tlbSegDir
;
2071 ITypeLibImpl
* pTypeLibImpl
;
2073 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2075 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2076 if (!pTypeLibImpl
) return NULL
;
2078 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2079 pTypeLibImpl
->ref
= 1;
2081 /* get pointer to beginning of typelib data */
2085 cx
.pLibInfo
= pTypeLibImpl
;
2086 cx
.length
= dwTLBLength
;
2089 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2091 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2092 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
2093 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2096 /* there is a small amount of information here until the next important
2098 * the segment directory . Try to calculate the amount of data */
2099 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2101 /* now read the segment directory */
2102 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2103 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2104 cx
.pTblDir
= &tlbSegDir
;
2106 /* just check two entries */
2107 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2109 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2110 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2114 /* now fill our internal data */
2115 /* TLIBATTR fields */
2116 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2118 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2119 /* Windows seems to have zero here, is this correct? */
2120 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2121 pTypeLibImpl
->LibAttr
.lcid
= PRIMARYLANGID(tlbHeader
.lcid
);
2123 pTypeLibImpl
->LibAttr
.lcid
= 0;
2125 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2126 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2127 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2128 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2130 /* name, eventually add to a hash table */
2131 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2134 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2135 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2137 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2140 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2141 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2144 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2147 if(tlbHeader
.CustomDataOffset
>= 0)
2149 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2152 /* fill in typedescriptions */
2153 if(tlbSegDir
.pTypdescTab
.length
> 0)
2155 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2157 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2158 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2161 /* FIXME: add several sanity checks here */
2162 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2163 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2165 /* FIXME: check safearray */
2167 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2169 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2171 else if(td
[0] == VT_CARRAY
)
2173 /* array descr table here */
2174 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2176 else if(td
[0] == VT_USERDEFINED
)
2178 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2180 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2183 /* second time around to fill the array subscript info */
2186 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2187 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2189 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2190 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2193 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2195 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2197 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2199 for(j
= 0; j
<td
[2]; j
++)
2201 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2202 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2203 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2204 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2209 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2210 ERR("didn't find array description data\n");
2215 /* imported type libs */
2216 if(tlbSegDir
.pImpFiles
.offset
>0)
2218 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2219 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2222 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2224 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2225 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2226 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
2228 MSFT_ReadLEDWords(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2229 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2230 MSFT_ReadLEWords(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2231 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2234 (*ppImpLib
)->name
= TLB_Alloc(size
+1);
2235 MSFT_Read((*ppImpLib
)->name
, size
, &cx
, DO_NOT_SEEK
);
2236 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2237 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & 0xfffffffc;
2239 ppImpLib
= &(*ppImpLib
)->next
;
2244 if(tlbHeader
.nrtypeinfos
>= 0 )
2246 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2247 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2250 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2252 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2254 ITypeInfo_AddRef((ITypeInfo
*) *ppTI
);
2255 ppTI
= &((*ppTI
)->next
);
2256 (pTypeLibImpl
->TypeInfoCount
)++;
2260 TRACE("(%p)\n", pTypeLibImpl
);
2261 return (ITypeLib2
*) pTypeLibImpl
;
2265 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2271 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2272 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2273 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2274 ret
= SysAllocString(nameW
);
2275 HeapFree(GetProcessHeap(), 0, nameW
);
2279 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2285 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2286 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2290 guid
->Data4
[0] = s
>> 8;
2291 guid
->Data4
[1] = s
& 0xff;
2294 for(i
= 0; i
< 6; i
++) {
2295 memcpy(b
, str
+ 24 + 2 * i
, 2);
2296 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2301 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2308 bytelen
= *(WORD
*)ptr
;
2309 if(bytelen
== 0xffff) return 2;
2310 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2311 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2312 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2313 *pBstr
= SysAllocStringLen(nameW
, len
);
2314 HeapFree(GetProcessHeap(), 0, nameW
);
2318 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2323 bytelen
= *(WORD
*)ptr
;
2324 if(bytelen
== 0xffff) return 2;
2325 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2326 memcpy(*str
, ptr
+ 2, bytelen
);
2327 (*str
)[bytelen
] = '\0';
2331 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2333 char *ptr
= pLibBlk
;
2336 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2337 FIXME("libblk magic = %04x\n", w
);
2342 if((w
= *(WORD
*)ptr
) != 0xffff) {
2343 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2348 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2350 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2352 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2355 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2358 pTypeLibImpl
->LibAttr
.lcid
= *(WORD
*)ptr
;
2361 ptr
+= 4; /* skip res12 */
2363 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2366 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2369 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2372 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2373 ptr
+= sizeof(GUID
);
2375 return ptr
- (char*)pLibBlk
;
2378 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2381 TYPEDESC
*pTD
= &pElem
->tdesc
;
2383 /* Handle [in/out] first */
2384 if((*pType
& 0xc000) == 0xc000)
2385 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2386 else if(*pType
& 0x8000)
2387 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2388 else if(*pType
& 0x4000)
2389 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2391 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2394 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2397 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2400 if((*pType
& 0xe00) == 0xe00) {
2402 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2404 pTD
= pTD
->u
.lptdesc
;
2406 switch(*pType
& 0x7f) {
2409 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2411 pTD
= pTD
->u
.lptdesc
;
2414 case VT_USERDEFINED
:
2415 pTD
->vt
= VT_USERDEFINED
;
2416 pTD
->u
.hreftype
= *(++pType
) / 4;
2422 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2425 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2427 pTD
->vt
= VT_CARRAY
;
2428 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2430 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2431 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2432 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2433 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2435 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2441 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2445 pTD
->vt
= VT_SAFEARRAY
;
2446 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2448 pTD
= pTD
->u
.lptdesc
;
2452 pTD
->vt
= *pType
& 0x7f;
2462 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2467 TLBRefType
**ppRefType
;
2469 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2470 FIXME("Ref magic = %x\n", pRef
->magic
);
2473 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2475 ppRefType
= &pTI
->reflist
;
2476 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2478 unsigned int lib_offs
, type_num
;
2480 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2481 sizeof(**ppRefType
));
2483 name
+= SLTG_ReadStringA(name
, &refname
);
2484 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2485 FIXME("Can't sscanf ref\n");
2486 if(lib_offs
!= 0xffff) {
2487 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2490 if((*import
)->offset
== lib_offs
)
2492 import
= &(*import
)->next
;
2495 char fname
[MAX_PATH
+1];
2498 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2500 (*import
)->offset
= lib_offs
;
2501 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2503 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2504 &(*import
)->wVersionMajor
,
2505 &(*import
)->wVersionMinor
,
2506 &(*import
)->lcid
, fname
) != 4) {
2507 FIXME("can't sscanf ref %s\n",
2508 pNameTable
+ lib_offs
+ 40);
2510 len
= strlen(fname
);
2511 if(fname
[len
-1] != '#')
2512 FIXME("fname = %s\n", fname
);
2513 fname
[len
-1] = '\0';
2514 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2516 (*ppRefType
)->pImpTLInfo
= *import
;
2517 } else { /* internal ref */
2518 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2520 (*ppRefType
)->reference
= ref
;
2521 (*ppRefType
)->index
= type_num
;
2523 HeapFree(GetProcessHeap(), 0, refname
);
2524 ppRefType
= &(*ppRefType
)->next
;
2526 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2527 FIXME("End of ref block magic = %x\n", *name
);
2528 dump_TLBRefType(pTI
->reflist
);
2531 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2534 SLTG_ImplInfo
*info
;
2535 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2536 /* I don't really get this structure, usually it's 0x16 bytes
2537 long, but iuser.tlb contains some that are 0x18 bytes long.
2538 That's ok because we can use the next ptr to jump to the next
2539 one. But how do we know the length of the last one? The WORD
2540 at offs 0x8 might be the clue. For now I'm just assuming that
2541 the last one is the regular 0x16 bytes. */
2543 info
= (SLTG_ImplInfo
*)pBlk
;
2545 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2546 sizeof(**ppImplType
));
2547 (*ppImplType
)->hRef
= info
->ref
;
2548 (*ppImplType
)->implflags
= info
->impltypeflags
;
2549 pTI
->TypeAttr
.cImplTypes
++;
2550 ppImplType
= &(*ppImplType
)->next
;
2552 if(info
->next
== 0xffff)
2555 FIXME("Interface inheriting more than one interface\n");
2556 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2558 info
++; /* see comment at top of function */
2562 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2565 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2566 SLTG_MemberHeader
*pMemHeader
;
2567 char *pFirstItem
, *pNextItem
;
2569 if(pTIHeader
->href_table
!= 0xffffffff) {
2570 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2575 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2577 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2579 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2580 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2583 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2587 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2590 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2591 SLTG_MemberHeader
*pMemHeader
;
2592 SLTG_Function
*pFunc
;
2593 char *pFirstItem
, *pNextItem
;
2594 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2597 if(pTIHeader
->href_table
!= 0xffffffff) {
2598 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2602 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2604 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2606 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2607 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2610 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2611 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2616 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2617 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2618 FIXME("func magic = %02x\n", pFunc
->magic
);
2621 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2622 sizeof(**ppFuncDesc
));
2623 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2625 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2626 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2627 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2628 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2629 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2630 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2632 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2633 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2635 if(pFunc
->retnextopt
& 0x80)
2636 pType
= &pFunc
->rettype
;
2638 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2641 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2643 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2644 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2645 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2646 (*ppFuncDesc
)->pParamDesc
=
2647 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2648 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2650 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2652 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2653 char *paramName
= pNameTable
+ *pArg
;
2655 /* If arg type follows then paramName points to the 2nd
2656 letter of the name, else the next WORD is an offset to
2657 the arg type and paramName points to the first letter.
2658 So let's take one char off paramName and see if we're
2659 pointing at an alpha-numeric char. However if *pArg is
2660 0xffff or 0xfffe then the param has no name, the former
2661 meaning that the next WORD is the type, the latter
2662 meaning the the next WORD is an offset to the type. */
2667 else if(*pArg
== 0xfffe) {
2671 else if(!isalnum(*(paramName
-1)))
2676 if(HaveOffs
) { /* the next word is an offset to type */
2677 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2678 SLTG_DoType(pType
, pFirstItem
,
2679 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2684 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2685 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2688 /* Are we an optional param ? */
2689 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2690 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2691 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2694 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2695 TLB_MultiByteToBSTR(paramName
);
2699 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2700 if(pFunc
->next
== 0xffff) break;
2702 pTI
->TypeAttr
.cFuncs
= num
;
2703 dump_TLBFuncDesc(pTI
->funclist
);
2704 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2707 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2710 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2711 SLTG_MemberHeader
*pMemHeader
;
2712 SLTG_RecordItem
*pItem
;
2714 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2719 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2721 pFirstItem
= (char*)(pMemHeader
+ 1);
2722 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2723 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2724 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2725 FIXME("record magic = %02x\n", pItem
->magic
);
2728 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2729 sizeof(**ppVarDesc
));
2730 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2731 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2732 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2733 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2735 if(pItem
->typepos
== 0x02)
2736 pType
= &pItem
->type
;
2737 else if(pItem
->typepos
== 0x00)
2738 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2740 FIXME("typepos = %02x\n", pItem
->typepos
);
2744 SLTG_DoType(pType
, pFirstItem
,
2745 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2747 /* FIXME("helpcontext, helpstring\n"); */
2749 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2751 ppVarDesc
= &((*ppVarDesc
)->next
);
2752 if(pItem
->next
== 0xffff) break;
2754 pTI
->TypeAttr
.cVars
= num
;
2755 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2758 static SLTG_TypeInfoTail
*SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
2761 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2762 SLTG_MemberHeader
*pMemHeader
;
2763 SLTG_AliasItem
*pItem
;
2766 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2767 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
2770 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2771 for (i
= 0 ; i
<pMemHeader
->cbExtra
/4 ; i
++) {
2772 if (pItem
->vt
== 0xffff) {
2773 if (i
<(pMemHeader
->cbExtra
/4-1))
2774 FIXME("Endmarker too early in process alias data!\n");
2778 FIXME("Chain extends over last entry?\n");
2781 if (pItem
->vt
== VT_USERDEFINED
) {
2782 pTI
->TypeAttr
.tdescAlias
.vt
= pItem
->vt
;
2783 /* guessing here ... */
2784 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem
->res02
);
2785 pTI
->TypeAttr
.tdescAlias
.u
.hreftype
= pItem
->res02
;
2788 FIXME("alias %d: 0x%x\n",i
,pItem
->vt
);
2789 FIXME("alias %d: 0x%x\n",i
,pItem
->res02
);
2793 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
2796 static SLTG_TypeInfoTail
*SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
2799 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2800 SLTG_MemberHeader
*pMemHeader
;
2801 SLTG_AliasItem
*pItem
;
2803 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2804 pItem
= (SLTG_AliasItem
*)(pMemHeader
+ 1);
2805 FIXME("memh.cbExtra is %ld\n",pMemHeader
->cbExtra
);
2806 FIXME("offset 0 0x%x\n",*(WORD
*)pItem
);
2807 return (SLTG_TypeInfoTail
*)((char*)(pMemHeader
+ 1)+pMemHeader
->cbExtra
);
2810 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
2813 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2814 SLTG_MemberHeader
*pMemHeader
;
2815 SLTG_EnumItem
*pItem
;
2817 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2820 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2822 pFirstItem
= (char*)(pMemHeader
+ 1);
2823 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
2824 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2825 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
2826 FIXME("enumitem magic = %04x\n", pItem
->magic
);
2829 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2830 sizeof(**ppVarDesc
));
2831 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2832 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2833 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2835 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2836 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2837 *(INT
*)(pItem
->value
+ pFirstItem
);
2838 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
2839 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2840 /* FIXME("helpcontext, helpstring\n"); */
2842 ppVarDesc
= &((*ppVarDesc
)->next
);
2843 if(pItem
->next
== 0xffff) break;
2845 pTI
->TypeAttr
.cVars
= num
;
2846 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2849 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2850 managable copy of it into this */
2863 } SLTG_InternalOtherTypeInfo
;
2865 /****************************************************************************
2866 * ITypeLib2_Constructor_SLTG
2868 * loading a SLTG typelib from an in-memory image
2870 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
2872 ITypeLibImpl
*pTypeLibImpl
;
2873 SLTG_Header
*pHeader
;
2874 SLTG_BlkEntry
*pBlkEntry
;
2878 LPVOID pBlk
, pFirstBlk
;
2879 SLTG_LibBlk
*pLibBlk
;
2880 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
2881 char *pAfterOTIBlks
= NULL
;
2882 char *pNameTable
, *ptr
;
2885 ITypeInfoImpl
**ppTypeInfoImpl
;
2887 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2889 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2890 if (!pTypeLibImpl
) return NULL
;
2892 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2893 pTypeLibImpl
->ref
= 1;
2898 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
2899 pHeader
->nrOfFileBlks
);
2900 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
2901 FIXME("Header type magic 0x%08lx not supported.\n",
2902 pHeader
->SLTG_magic
);
2906 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2907 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
2909 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2910 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
2912 /* Next we have a magic block */
2913 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
2915 /* Let's see if we're still in sync */
2916 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
2917 sizeof(SLTG_COMPOBJ_MAGIC
))) {
2918 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
2921 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
2922 sizeof(SLTG_DIR_MAGIC
))) {
2923 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
2927 pIndex
= (SLTG_Index
*)(pMagic
+1);
2929 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
2931 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
2933 /* We'll set up a ptr to the main library block, which is the last one. */
2935 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
2936 pBlkEntry
[order
].next
!= 0;
2937 order
= pBlkEntry
[order
].next
- 1, i
++) {
2938 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
2942 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
2944 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2949 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2951 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2952 sizeof(*pOtherTypeInfoBlks
) *
2953 pTypeLibImpl
->TypeInfoCount
);
2956 ptr
= (char*)pLibBlk
+ len
;
2958 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
2962 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
2964 w
= *(WORD
*)(ptr
+ 2);
2967 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
2969 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
2970 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
2972 w
= *(WORD
*)(ptr
+ 4 + len
);
2974 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
2976 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
2978 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
2979 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
2981 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
2982 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
2983 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
2985 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
2987 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
2990 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
2991 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
2992 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
2993 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
2994 len
+= sizeof(SLTG_OtherTypeInfo
);
2998 pAfterOTIBlks
= ptr
;
3000 /* Skip this WORD and get the next DWORD */
3001 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
3003 /* Now add this to pLibBLk look at what we're pointing at and
3004 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3005 dust and we should be pointing at the beginning of the name
3008 pNameTable
= (char*)pLibBlk
+ len
;
3010 switch(*(WORD
*)pNameTable
) {
3017 FIXME("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
3021 pNameTable
+= 0x216;
3025 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
3027 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
3030 /* Hopefully we now have enough ptrs set up to actually read in
3031 some TypeInfos. It's not clear which order to do them in, so
3032 I'll just follow the links along the BlkEntry chain and read
3033 them in in the order in which they're in the file */
3035 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
3037 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3038 pBlkEntry
[order
].next
!= 0;
3039 order
= pBlkEntry
[order
].next
- 1, i
++) {
3041 SLTG_TypeInfoHeader
*pTIHeader
;
3042 SLTG_TypeInfoTail
*pTITail
;
3044 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
3045 pOtherTypeInfoBlks
[i
].index_name
)) {
3046 FIXME("Index strings don't match\n");
3051 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
3052 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
3055 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
3056 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
3057 (*ppTypeInfoImpl
)->index
= i
;
3058 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
3059 pOtherTypeInfoBlks
[i
].name_offs
+
3061 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
3062 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
3064 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
3065 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
3066 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
3067 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
3068 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
3070 if((pTIHeader
->typeflags1
& 7) != 2)
3071 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
3072 if(pTIHeader
->typeflags3
!= 2)
3073 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
3075 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3076 debugstr_w((*ppTypeInfoImpl
)->Name
),
3077 typekind_desc
[pTIHeader
->typekind
],
3078 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
3079 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
3081 switch(pTIHeader
->typekind
) {
3083 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3087 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3090 case TKIND_INTERFACE
:
3091 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3095 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3099 pTITail
= SLTG_ProcessAlias(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3100 if (pTITail
->tdescalias_vt
)
3101 (*ppTypeInfoImpl
)->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3104 case TKIND_DISPATCH
:
3105 pTITail
= SLTG_ProcessDispatch(pBlk
, *ppTypeInfoImpl
, pNameTable
);
3109 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
3115 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
3116 but we've already set those */
3117 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
3118 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
3119 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
3121 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3143 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
3144 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3147 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
3148 FIXME("Somehow processed %d TypeInfos\n", i
);
3152 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
3153 return (ITypeLib2
*)pTypeLibImpl
;
3156 /* ITypeLib::QueryInterface
3158 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3163 ICOM_THIS( ITypeLibImpl
, iface
);
3165 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3168 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3169 IsEqualIID(riid
,&IID_ITypeLib
)||
3170 IsEqualIID(riid
,&IID_ITypeLib2
))
3177 ITypeLib2_AddRef(iface
);
3178 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3181 TRACE("-- Interface: E_NOINTERFACE\n");
3182 return E_NOINTERFACE
;
3187 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3189 ICOM_THIS( ITypeLibImpl
, iface
);
3191 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3193 return ++(This
->ref
);
3196 /* ITypeLib::Release
3198 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3200 ICOM_THIS( ITypeLibImpl
, iface
);
3204 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3208 /* FIXME destroy child objects */
3210 TRACE(" destroying ITypeLib(%p)\n",This
);
3214 SysFreeString(This
->Name
);
3218 if (This
->DocString
)
3220 SysFreeString(This
->DocString
);
3221 This
->DocString
= NULL
;
3226 SysFreeString(This
->HelpFile
);
3227 This
->HelpFile
= NULL
;
3230 if (This
->HelpStringDll
)
3232 SysFreeString(This
->HelpStringDll
);
3233 This
->HelpStringDll
= NULL
;
3236 if (This
->pTypeInfo
) /* can be NULL */
3237 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3238 HeapFree(GetProcessHeap(),0,This
);
3245 /* ITypeLib::GetTypeInfoCount
3247 * Returns the number of type descriptions in the type library
3249 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3251 ICOM_THIS( ITypeLibImpl
, iface
);
3252 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3253 return This
->TypeInfoCount
;
3256 /* ITypeLib::GetTypeInfo
3258 * retrieves the specified type description in the library.
3260 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3263 ITypeInfo
**ppTInfo
)
3267 ICOM_THIS( ITypeLibImpl
, iface
);
3268 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3270 TRACE("(%p)->(index=%d) \n", This
, index
);
3272 if (!ppTInfo
) return E_INVALIDARG
;
3274 /* search element n in list */
3275 for(i
=0; i
< index
; i
++)
3277 pTypeInfo
= pTypeInfo
->next
;
3280 TRACE("-- element not found\n");
3281 return TYPE_E_ELEMENTNOTFOUND
;
3285 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3287 ITypeInfo_AddRef(*ppTInfo
);
3288 TRACE("-- found (%p)\n",*ppTInfo
);
3293 /* ITypeLibs::GetTypeInfoType
3295 * Retrieves the type of a type description.
3297 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3302 ICOM_THIS( ITypeLibImpl
, iface
);
3304 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3306 TRACE("(%p) index %d \n",This
, index
);
3308 if(!pTKind
) return E_INVALIDARG
;
3310 /* search element n in list */
3311 for(i
=0; i
< index
; i
++)
3315 TRACE("-- element not found\n");
3316 return TYPE_E_ELEMENTNOTFOUND
;
3318 pTInfo
= pTInfo
->next
;
3321 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3322 TRACE("-- found Type (%d)\n", *pTKind
);
3326 /* ITypeLib::GetTypeInfoOfGuid
3328 * Retrieves the type description that corresponds to the specified GUID.
3331 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3334 ITypeInfo
**ppTInfo
)
3336 ICOM_THIS( ITypeLibImpl
, iface
);
3337 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3339 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3341 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3343 /* search linked list for guid */
3344 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3346 pTypeInfo
= pTypeInfo
->next
;
3350 /* end of list reached */
3351 TRACE("-- element not found\n");
3352 return TYPE_E_ELEMENTNOTFOUND
;
3356 TRACE("-- found (%p, %s)\n",
3358 debugstr_w(pTypeInfo
->Name
));
3360 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3361 ITypeInfo_AddRef(*ppTInfo
);
3365 /* ITypeLib::GetLibAttr
3367 * Retrieves the structure that contains the library's attributes.
3370 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3372 LPTLIBATTR
*ppTLibAttr
)
3374 ICOM_THIS( ITypeLibImpl
, iface
);
3375 TRACE("(%p)\n",This
);
3376 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3377 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3381 /* ITypeLib::GetTypeComp
3383 * Enables a client compiler to bind to a library's types, variables,
3384 * constants, and global functions.
3387 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3389 ITypeComp
**ppTComp
)
3391 ICOM_THIS( ITypeLibImpl
, iface
);
3392 FIXME("(%p): stub!\n",This
);
3396 /* ITypeLib::GetDocumentation
3398 * Retrieves the library's documentation string, the complete Help file name
3399 * and path, and the context identifier for the library Help topic in the Help
3402 * On a successful return all non-null BSTR pointers will have been set,
3405 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3409 BSTR
*pBstrDocString
,
3410 DWORD
*pdwHelpContext
,
3411 BSTR
*pBstrHelpFile
)
3413 ICOM_THIS( ITypeLibImpl
, iface
);
3415 HRESULT result
= E_INVALIDARG
;
3420 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3422 pBstrName
, pBstrDocString
,
3423 pdwHelpContext
, pBstrHelpFile
);
3427 /* documentation for the typelib */
3431 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3437 if (This
->DocString
)
3438 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3439 else if (This
->Name
)
3440 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3442 *pBstrDocString
= NULL
;
3446 *pdwHelpContext
= This
->dwHelpContext
;
3451 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3453 *pBstrHelpFile
= NULL
;
3460 /* for a typeinfo */
3461 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3463 if(SUCCEEDED(result
))
3465 result
= ITypeInfo_GetDocumentation(pTInfo
,
3469 pdwHelpContext
, pBstrHelpFile
);
3471 ITypeInfo_Release(pTInfo
);
3476 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3478 if (pBstrName
) SysFreeString (*pBstrName
);
3480 return STG_E_INSUFFICIENTMEMORY
;
3485 * Indicates whether a passed-in string contains the name of a type or member
3486 * described in the library.
3489 static HRESULT WINAPI
ITypeLib2_fnIsName(
3495 ICOM_THIS( ITypeLibImpl
, iface
);
3496 ITypeInfoImpl
*pTInfo
;
3497 TLBFuncDesc
*pFInfo
;
3500 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3502 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3506 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3507 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3508 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3509 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3510 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3511 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3512 goto ITypeLib2_fnIsName_exit
;
3514 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3515 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3520 ITypeLib2_fnIsName_exit
:
3521 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3522 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3527 /* ITypeLib::FindName
3529 * Finds occurrences of a type description in a type library. This may be used
3530 * to quickly verify that a name exists in a type library.
3533 static HRESULT WINAPI
ITypeLib2_fnFindName(
3537 ITypeInfo
**ppTInfo
,
3541 ICOM_THIS( ITypeLibImpl
, iface
);
3542 ITypeInfoImpl
*pTInfo
;
3543 TLBFuncDesc
*pFInfo
;
3547 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3549 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3550 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3551 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3552 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3553 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3554 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3555 goto ITypeLib2_fnFindName_exit
;
3557 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3558 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3560 ITypeLib2_fnFindName_exit
:
3561 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3562 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3565 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3566 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3573 /* ITypeLib::ReleaseTLibAttr
3575 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3578 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3580 TLIBATTR
*pTLibAttr
)
3582 ICOM_THIS( ITypeLibImpl
, iface
);
3583 TRACE("freeing (%p)\n",This
);
3584 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3588 /* ITypeLib2::GetCustData
3590 * gets the custom data
3592 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3597 ICOM_THIS( ITypeLibImpl
, iface
);
3598 TLBCustData
*pCData
;
3600 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3602 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3605 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3609 VariantInit( pVarVal
);
3610 VariantCopy( pVarVal
, &pCData
->data
);
3613 return E_INVALIDARG
; /* FIXME: correct? */
3616 /* ITypeLib2::GetLibStatistics
3618 * Returns statistics about a type library that are required for efficient
3619 * sizing of hash tables.
3622 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3624 ULONG
*pcUniqueNames
,
3625 ULONG
*pcchUniqueNames
)
3627 ICOM_THIS( ITypeLibImpl
, iface
);
3629 FIXME("(%p): stub!\n", This
);
3631 if(pcUniqueNames
) *pcUniqueNames
=1;
3632 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3636 /* ITypeLib2::GetDocumentation2
3638 * Retrieves the library's documentation string, the complete Help file name
3639 * and path, the localization context to use, and the context ID for the
3640 * library Help topic in the Help file.
3643 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3647 BSTR
*pbstrHelpString
,
3648 DWORD
*pdwHelpStringContext
,
3649 BSTR
*pbstrHelpStringDll
)
3651 ICOM_THIS( ITypeLibImpl
, iface
);
3655 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3657 /* the help string should be obtained from the helpstringdll,
3658 * using the _DLLGetDocumentation function, based on the supplied
3659 * lcid. Nice to do sometime...
3663 /* documentation for the typelib */
3665 *pbstrHelpString
=SysAllocString(This
->DocString
);
3666 if(pdwHelpStringContext
)
3667 *pdwHelpStringContext
=This
->dwHelpContext
;
3668 if(pbstrHelpStringDll
)
3669 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3675 /* for a typeinfo */
3676 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3678 if(SUCCEEDED(result
))
3680 ITypeInfo2
* pTInfo2
;
3681 result
= ITypeInfo_QueryInterface(pTInfo
,
3683 (LPVOID
*) &pTInfo2
);
3685 if(SUCCEEDED(result
))
3687 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3691 pdwHelpStringContext
,
3692 pbstrHelpStringDll
);
3694 ITypeInfo2_Release(pTInfo2
);
3697 ITypeInfo_Release(pTInfo
);
3703 /* ITypeLib2::GetAllCustData
3705 * Gets all custom data items for the library.
3708 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3710 CUSTDATA
*pCustData
)
3712 ICOM_THIS( ITypeLibImpl
, iface
);
3713 TLBCustData
*pCData
;
3715 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3716 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3717 if(pCustData
->prgCustData
){
3718 pCustData
->cCustData
=This
->ctCustData
;
3719 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3720 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3721 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3724 ERR(" OUT OF MEMORY! \n");
3725 return E_OUTOFMEMORY
;
3730 static ICOM_VTABLE(ITypeLib2
) tlbvt
= {
3731 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3732 ITypeLib2_fnQueryInterface
,
3734 ITypeLib2_fnRelease
,
3735 ITypeLib2_fnGetTypeInfoCount
,
3736 ITypeLib2_fnGetTypeInfo
,
3737 ITypeLib2_fnGetTypeInfoType
,
3738 ITypeLib2_fnGetTypeInfoOfGuid
,
3739 ITypeLib2_fnGetLibAttr
,
3740 ITypeLib2_fnGetTypeComp
,
3741 ITypeLib2_fnGetDocumentation
,
3743 ITypeLib2_fnFindName
,
3744 ITypeLib2_fnReleaseTLibAttr
,
3746 ITypeLib2_fnGetCustData
,
3747 ITypeLib2_fnGetLibStatistics
,
3748 ITypeLib2_fnGetDocumentation2
,
3749 ITypeLib2_fnGetAllCustData
3752 /*================== ITypeInfo(2) Methods ===================================*/
3753 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
3755 ITypeInfoImpl
* pTypeInfoImpl
;
3757 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
3760 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
3761 pTypeInfoImpl
->ref
=1;
3763 TRACE("(%p)\n", pTypeInfoImpl
);
3764 return (ITypeInfo2
*) pTypeInfoImpl
;
3767 /* ITypeInfo::QueryInterface
3769 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
3774 ICOM_THIS( ITypeLibImpl
, iface
);
3776 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3779 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3780 IsEqualIID(riid
,&IID_ITypeInfo
)||
3781 IsEqualIID(riid
,&IID_ITypeInfo2
))
3785 ITypeInfo_AddRef(iface
);
3786 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3789 TRACE("-- Interface: E_NOINTERFACE\n");
3790 return E_NOINTERFACE
;
3793 /* ITypeInfo::AddRef
3795 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
3797 ICOM_THIS( ITypeInfoImpl
, iface
);
3801 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3805 /* ITypeInfo::Release
3807 static ULONG WINAPI
ITypeInfo_fnRelease( ITypeInfo2
*iface
)
3809 ICOM_THIS( ITypeInfoImpl
, iface
);
3813 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3817 FIXME("destroy child objects\n");
3819 TRACE("destroying ITypeInfo(%p)\n",This
);
3822 SysFreeString(This
->Name
);
3826 if (This
->DocString
)
3828 SysFreeString(This
->DocString
);
3829 This
->DocString
= 0;
3834 ITypeInfo_Release((ITypeInfo
*)This
->next
);
3837 HeapFree(GetProcessHeap(),0,This
);
3843 /* ITypeInfo::GetTypeAttr
3845 * Retrieves a TYPEATTR structure that contains the attributes of the type
3849 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
3850 LPTYPEATTR
*ppTypeAttr
)
3852 ICOM_THIS( ITypeInfoImpl
, iface
);
3853 TRACE("(%p)\n",This
);
3854 /* FIXME: must do a copy here */
3855 *ppTypeAttr
=&This
->TypeAttr
;
3859 /* ITypeInfo::GetTypeComp
3861 * Retrieves the ITypeComp interface for the type description, which enables a
3862 * client compiler to bind to the type description's members.
3865 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
3866 ITypeComp
* *ppTComp
)
3868 ICOM_THIS( ITypeInfoImpl
, iface
);
3869 FIXME("(%p) stub!\n", This
);
3873 /* ITypeInfo::GetFuncDesc
3875 * Retrieves the FUNCDESC structure that contains information about a
3876 * specified function.
3879 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
3880 LPFUNCDESC
*ppFuncDesc
)
3882 ICOM_THIS( ITypeInfoImpl
, iface
);
3884 TLBFuncDesc
* pFDesc
;
3885 TRACE("(%p) index %d\n", This
, index
);
3886 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
3889 /* FIXME: must do a copy here */
3890 *ppFuncDesc
=&pFDesc
->funcdesc
;
3893 return E_INVALIDARG
;
3896 /* ITypeInfo::GetVarDesc
3898 * Retrieves a VARDESC structure that describes the specified variable.
3901 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
3902 LPVARDESC
*ppVarDesc
)
3904 ICOM_THIS( ITypeInfoImpl
, iface
);
3906 TLBVarDesc
* pVDesc
;
3907 TRACE("(%p) index %d\n", This
, index
);
3908 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
3911 /* FIXME: must do a copy here */
3912 *ppVarDesc
=&pVDesc
->vardesc
;
3915 return E_INVALIDARG
;
3918 /* ITypeInfo_GetNames
3920 * Retrieves the variable with the specified member ID (or the name of the
3921 * property or method and its parameters) that correspond to the specified
3924 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
3925 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
3927 ICOM_THIS( ITypeInfoImpl
, iface
);
3928 TLBFuncDesc
* pFDesc
;
3929 TLBVarDesc
* pVDesc
;
3931 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
3932 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
3935 /* function found, now return function and parameter names */
3936 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
3939 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
3941 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
3947 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
3950 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
3955 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
)
3957 /* recursive search */
3960 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
3962 if(SUCCEEDED(result
))
3964 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
3965 ITypeInfo_Release(pTInfo
);
3968 WARN("Could not search inherited interface!\n");
3972 WARN("no names found\n");
3975 return TYPE_E_ELEMENTNOTFOUND
;
3982 /* ITypeInfo::GetRefTypeOfImplType
3984 * If a type description describes a COM class, it retrieves the type
3985 * description of the implemented interface types. For an interface,
3986 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3990 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
3995 ICOM_THIS( ITypeInfoImpl
, iface
);
3997 TLBImplType
*pImpl
= This
->impltypelist
;
3999 TRACE("(%p) index %d\n", This
, index
);
4000 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
4004 /* only valid on dual interfaces;
4005 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4007 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
4009 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
4010 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4016 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4017 *pRefType
= pImpl
->hRef
;
4022 /* get element n from linked list */
4023 for(i
=0; pImpl
&& i
<index
; i
++)
4025 pImpl
= pImpl
->next
;
4028 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
4030 *pRefType
= pImpl
->hRef
;
4032 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
4039 /* ITypeInfo::GetImplTypeFlags
4041 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4042 * or base interface in a type description.
4044 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
4045 UINT index
, INT
*pImplTypeFlags
)
4047 ICOM_THIS( ITypeInfoImpl
, iface
);
4051 TRACE("(%p) index %d\n", This
, index
);
4052 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
4053 i
++, pImpl
=pImpl
->next
)
4055 if(i
==index
&& pImpl
){
4056 *pImplTypeFlags
=pImpl
->implflags
;
4060 return TYPE_E_ELEMENTNOTFOUND
;
4064 * Maps between member names and member IDs, and parameter names and
4067 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
4068 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
4070 ICOM_THIS( ITypeInfoImpl
, iface
);
4071 TLBFuncDesc
* pFDesc
;
4072 TLBVarDesc
* pVDesc
;
4075 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
4077 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
4079 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
4080 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
4081 for(i
=1; i
< cNames
; i
++){
4082 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
4083 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
4085 if( j
<pFDesc
->funcdesc
.cParams
)
4088 ret
=DISP_E_UNKNOWNNAME
;
4093 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4094 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
4095 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
4099 /* not found, see if this is and interface with an inheritance */
4100 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&&
4101 This
->TypeAttr
.cImplTypes
){
4102 /* recursive search */
4104 ret
=ITypeInfo_GetRefTypeInfo(iface
,
4105 This
->impltypelist
->hRef
, &pTInfo
);
4107 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
4108 ITypeInfo_Release(pTInfo
);
4111 WARN("Could not search inherited interface!\n");
4113 WARN("no names found\n");
4114 return DISP_E_UNKNOWNNAME
;
4117 /* ITypeInfo::Invoke
4119 * Invokes a method, or accesses a property of an object, that implements the
4120 * interface described by the type description.
4123 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
4126 if (TRACE_ON(ole
)) {
4128 TRACE("Calling %p(",func
);
4129 for (i
=0;i
<nrargs
;i
++) TRACE("%08lx,",args
[i
]);
4141 res
= func(args
[0]);
4144 res
= func(args
[0],args
[1]);
4147 res
= func(args
[0],args
[1],args
[2]);
4150 res
= func(args
[0],args
[1],args
[2],args
[3]);
4153 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4]);
4156 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4159 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4162 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7]);
4165 res
= func(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6],args
[7],args
[8]);
4168 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4174 FIXME("unsupported calling convention %d\n",callconv
);
4178 TRACE("returns %08lx\n",res
);
4182 extern int const _argsize(DWORD vt
);
4184 /****************************************************************************
4185 * Helper functions for Dispcall / Invoke, which copies one variant
4186 * with target type onto the argument stack.
4189 _copy_arg( ITypeInfo2
*tinfo
, TYPEDESC
*tdesc
,
4190 DWORD
*argpos
, VARIANT
*arg
, VARTYPE vt
4192 UINT arglen
= _argsize(vt
)*sizeof(DWORD
);
4195 if ((vt
==VT_PTR
) && tdesc
&& (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
)) {
4196 memcpy(argpos
,&arg
,sizeof(void*));
4200 if (V_VT(arg
) == vt
) {
4201 memcpy(argpos
, &V_UNION(arg
,lVal
), arglen
);
4205 if (vt
== VT_VARIANT
) {
4206 memcpy(argpos
, arg
, arglen
);
4209 /* Deref BYREF vars if there is need */
4210 if(V_ISBYREF(arg
) && ((V_VT(arg
) & ~VT_BYREF
)==vt
)) {
4211 memcpy(argpos
,(void*)V_UNION(arg
,lVal
), arglen
);
4214 if (vt
==VT_UNKNOWN
&& V_VT(arg
)==VT_DISPATCH
) {
4215 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4216 memcpy(argpos
,&V_UNION(arg
,lVal
), arglen
);
4219 if ((vt
== VT_PTR
) && tdesc
)
4220 return _copy_arg(tinfo
, tdesc
->u
.lptdesc
, argpos
, arg
, tdesc
->u
.lptdesc
->vt
);
4221 if ((vt
== VT_USERDEFINED
) && tdesc
&& tinfo
) {
4226 hres
= ITypeInfo_GetRefTypeInfo(tinfo
,tdesc
->u
.hreftype
,&tinfo2
);
4228 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
));
4229 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4232 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4233 switch (tattr
->typekind
) {
4235 switch ( V_VT( arg
) ) {
4237 *argpos
= V_UNION(arg
,iVal
);
4240 memcpy(argpos
, &V_UNION(arg
,lVal
), 4);
4243 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg
));
4248 tdesc
= &(tattr
->tdescAlias
);
4249 hres
= _copy_arg((ITypeInfo2
*)tinfo2
, tdesc
, argpos
, arg
, tdesc
->vt
);
4250 ITypeInfo_Release(tinfo2
);
4253 case TKIND_INTERFACE
:
4254 if (V_VT(arg
) == VT_DISPATCH
) {
4256 if (IsEqualIID(&IID_IDispatch
,&(tattr
->guid
))) {
4257 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4260 hres
=IUnknown_QueryInterface(V_UNION(arg
,pdispVal
),&IID_IDispatch
,(LPVOID
*)&disp
);
4261 if (SUCCEEDED(hres
)) {
4262 memcpy(argpos
,&disp
,4);
4263 IUnknown_Release(V_UNION(arg
,pdispVal
));
4266 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr
->guid
)));
4269 if (V_VT(arg
) == VT_UNKNOWN
) {
4270 memcpy(argpos
, &V_UNION(arg
,punkVal
), 4);
4273 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg
),debugstr_guid(&(tattr
->guid
)));
4275 case TKIND_DISPATCH
:
4276 if (V_VT(arg
) == VT_DISPATCH
) {
4277 memcpy(argpos
, &V_UNION(arg
,pdispVal
), 4);
4280 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg
));
4283 FIXME("TKIND_RECORD unhandled.\n");
4286 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4292 if (VariantChangeType(arg
,arg
,0,vt
)==S_OK
) {
4293 FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt
, vt
);
4294 memcpy(argpos
,&V_UNION(arg
,lVal
), arglen
);
4297 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg
),vt
);
4301 /***********************************************************************
4302 * DispCallFunc (OLEAUT32.@)
4306 void* pvInstance
, ULONG oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
4307 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
4309 int i
, argsize
, argspos
;
4313 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4314 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
)
4316 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4317 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4319 for (i
=0;i
<cActuals
;i
++) {
4320 TRACE("arg %d: type %d, size %d\n",i
,prgvt
[i
],_argsize(prgvt
[i
]));
4321 dump_Variant(prgpvarg
[i
]);
4322 argsize
+= _argsize(prgvt
[i
]);
4324 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*argsize
);
4325 args
[0] = (DWORD
)pvInstance
; /* this is the fake IDispatch interface pointer */
4327 for (i
=0;i
<cActuals
;i
++) {
4328 VARIANT
*arg
= prgpvarg
[i
];
4329 TRACE("Storing arg %d (%d as %d)\n",i
,V_VT(arg
),prgvt
[i
]);
4330 _copy_arg(NULL
, NULL
, &args
[argspos
], arg
, prgvt
[i
]);
4331 argspos
+= _argsize(prgvt
[i
]);
4334 if(pvargResult
!=NULL
&& V_VT(pvargResult
)==VT_EMPTY
)
4336 _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4341 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult
);
4342 hres
= _invoke((*(FARPROC
**)pvInstance
)[oVft
/4],cc
,argsize
,args
);
4343 FIXME("Method returned %lx\n",hres
);
4345 HeapFree(GetProcessHeap(),0,args
);
4349 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4354 DISPPARAMS
*pDispParams
,
4355 VARIANT
*pVarResult
,
4356 EXCEPINFO
*pExcepInfo
,
4359 ICOM_THIS( ITypeInfoImpl
, iface
);
4360 TLBFuncDesc
* pFDesc
;
4361 TLBVarDesc
* pVDesc
;
4365 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4366 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4368 dump_DispParms(pDispParams
);
4370 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4371 if (pFDesc
->funcdesc
.memid
== memid
) {
4372 if (pFDesc
->funcdesc
.invkind
& dwFlags
)
4376 if (TRACE_ON(typelib
)) dump_TLBFuncDescOne(pFDesc
);
4377 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4378 switch (pFDesc
->funcdesc
.funckind
) {
4379 case FUNC_PUREVIRTUAL
:
4380 case FUNC_VIRTUAL
: {
4382 int numargs
, numargs2
, argspos
, args2pos
;
4383 DWORD
*args
, *args2
;
4386 numargs
= 1; numargs2
= 0;
4387 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4388 if (i
<pDispParams
->cArgs
)
4389 numargs
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4391 numargs
+= 1; /* sizeof(lpvoid) */
4392 numargs2
+= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4396 args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs
);
4397 args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*numargs2
);
4399 args
[0] = (DWORD
)pIUnk
;
4400 argspos
= 1; args2pos
= 0;
4401 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4402 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4403 if (i
<pDispParams
->cArgs
) {
4404 VARIANT
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1];
4405 TYPEDESC
*tdesc
= &pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
;
4406 hres
= _copy_arg(iface
, tdesc
, &args
[argspos
], arg
, tdesc
->vt
);
4407 if (FAILED(hres
)) return hres
;
4410 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
4411 if (tdesc
->vt
!= VT_PTR
)
4412 FIXME("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4413 /*FIXME: give pointers for the rest, so propertyget works*/
4414 args
[argspos
] = (DWORD
)&args2
[args2pos
];
4416 /* If pointer to variant, pass reference it. */
4417 if ((tdesc
->vt
== VT_PTR
) &&
4418 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4421 args
[argspos
]= (DWORD
)pVarResult
;
4426 if (pFDesc
->funcdesc
.cParamsOpt
)
4427 FIXME("Does not support optional parameters (%d)\n",
4428 pFDesc
->funcdesc
.cParamsOpt
4431 res
= _invoke((*(FARPROC
**)pIUnk
)[pFDesc
->funcdesc
.oVft
/4],
4432 pFDesc
->funcdesc
.callconv
,
4436 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4438 for (i
=0;i
<pFDesc
->funcdesc
.cParams
-pDispParams
->cArgs
;i
++) {
4439 int arglen
= _argsize(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
);
4440 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
+pDispParams
->cArgs
].tdesc
);
4442 i4_tdesc
.vt
= VT_I4
;
4444 /* If we are a pointer to a variant, we are done already */
4445 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4448 VariantInit(pVarResult
);
4449 memcpy(&V_UNION(pVarResult
,intVal
),&args2
[args2pos
],arglen
*sizeof(DWORD
));
4451 if (tdesc
->vt
== VT_PTR
)
4452 tdesc
= tdesc
->u
.lptdesc
;
4453 if (tdesc
->vt
== VT_USERDEFINED
) {
4457 hres
= ITypeInfo_GetRefTypeInfo(iface
,tdesc
->u
.hreftype
,&tinfo2
);
4459 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc
->u
.hreftype
);
4462 ITypeInfo_GetTypeAttr(tinfo2
,&tattr
);
4463 switch (tattr
->typekind
) {
4465 /* force the return type to be VT_I4 */
4469 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr
->tdescAlias
.vt
);
4470 tdesc
= &(tattr
->tdescAlias
);
4473 case TKIND_INTERFACE
:
4474 FIXME("TKIND_INTERFACE unhandled.\n");
4476 case TKIND_DISPATCH
:
4477 FIXME("TKIND_DISPATCH unhandled.\n");
4480 FIXME("TKIND_RECORD unhandled.\n");
4483 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
4486 ITypeInfo_Release(tinfo2
);
4488 V_VT(pVarResult
) = tdesc
->vt
;
4490 /* HACK: VB5 likes this.
4491 * I do not know why. There is 1 example in MSDN which uses
4492 * this which appears broken (mixes int vals and
4495 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4496 V_VT(pVarResult
) = VT_DISPATCH
;
4497 TRACE("storing into variant:\n");
4498 dump_Variant(pVarResult
);
4502 HeapFree(GetProcessHeap(),0,args2
);
4503 HeapFree(GetProcessHeap(),0,args
);
4506 case FUNC_DISPATCH
: {
4510 hr
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4512 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4515 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4516 hr
= IDispatch_Invoke(
4517 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4518 pVarResult
,pExcepInfo
,pArgErr
4521 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr
);
4522 IDispatch_Release(disp
);
4526 FIXME("Unknown function invocation type %d\n",pFDesc
->funcdesc
.funckind
);
4530 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4531 if (pVDesc
->vardesc
.memid
== memid
) {
4532 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR
)pVDesc
->Name
)));
4533 dump_TLBVarDesc(pVDesc
);
4538 /* not found, look for it in inherited interfaces */
4539 if (This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
) {
4540 /* recursive search */
4543 hr
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
4545 hr
=ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4546 ITypeInfo_Release(pTInfo
);
4549 WARN("Could not search inherited interface!\n");
4551 ERR("did not find member id %d, flags %d!\n", (int)memid
, dwFlags
);
4552 return DISP_E_MEMBERNOTFOUND
;
4555 /* ITypeInfo::GetDocumentation
4557 * Retrieves the documentation string, the complete Help file name and path,
4558 * and the context ID for the Help topic for a specified type description.
4560 * (Can be tested by the Visual Basic Editor in Word for instance.)
4562 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4563 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4564 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4566 ICOM_THIS( ITypeInfoImpl
, iface
);
4567 TLBFuncDesc
* pFDesc
;
4568 TLBVarDesc
* pVDesc
;
4569 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4570 " HelpContext(%p) HelpFile(%p)\n",
4571 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4572 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4574 *pBstrName
=SysAllocString(This
->Name
);
4576 *pBstrDocString
=SysAllocString(This
->DocString
);
4578 *pdwHelpContext
=This
->dwHelpContext
;
4580 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4582 }else {/* for a member */
4583 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4584 if(pFDesc
->funcdesc
.memid
==memid
){
4586 *pBstrName
= SysAllocString(pFDesc
->Name
);
4588 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4590 *pdwHelpContext
=pFDesc
->helpcontext
;
4593 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4594 if(pVDesc
->vardesc
.memid
==memid
){
4596 *pBstrName
= SysAllocString(pVDesc
->Name
);
4598 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
4600 *pdwHelpContext
=pVDesc
->HelpContext
;
4604 return TYPE_E_ELEMENTNOTFOUND
;
4607 /* ITypeInfo::GetDllEntry
4609 * Retrieves a description or specification of an entry point for a function
4612 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
4613 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
4616 ICOM_THIS( ITypeInfoImpl
, iface
);
4617 TLBFuncDesc
*pFDesc
;
4619 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
4621 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4622 if(pFDesc
->funcdesc
.memid
==memid
){
4623 dump_TypeInfo(This
);
4624 dump_TLBFuncDescOne(pFDesc
);
4626 /* FIXME: This is wrong, but how do you find that out? */
4628 const WCHAR oleaut32W
[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4629 *pBstrDllName
= SysAllocString(oleaut32W
);
4632 if (HIWORD(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
4634 *pBstrName
= SysAllocString(pFDesc
->Entry
);
4642 *pwOrdinal
= (DWORD
)pFDesc
->Entry
;
4648 /* ITypeInfo::GetRefTypeInfo
4650 * If a type description references other type descriptions, it retrieves
4651 * the referenced type descriptions.
4653 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
4656 ITypeInfo
**ppTInfo
)
4658 ICOM_THIS( ITypeInfoImpl
, iface
);
4659 HRESULT result
= E_FAIL
;
4662 if (hRefType
== -1 &&
4663 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
4664 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
4666 /* when we meet a DUAL dispinterface, we must create the interface
4669 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
4672 /* the interface version contains the same information as the dispinterface
4673 * copy the contents of the structs.
4675 *pTypeInfoImpl
= *This
;
4676 pTypeInfoImpl
->ref
= 1;
4678 /* change the type to interface */
4679 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
4681 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
4683 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
4688 TLBRefType
*pRefType
;
4689 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
4690 if(pRefType
->reference
== hRefType
)
4694 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
4695 if(pRefType
&& hRefType
!= -1) {
4696 ITypeLib
*pTLib
= NULL
;
4698 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
4700 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
4702 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
4703 TRACE("typeinfo in imported typelib that is already loaded\n");
4704 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
4705 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
4708 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4709 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
4710 pRefType
->pImpTLInfo
->wVersionMajor
,
4711 pRefType
->pImpTLInfo
->wVersionMinor
,
4712 pRefType
->pImpTLInfo
->lcid
,
4715 if(!SUCCEEDED(result
)) {
4716 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
4717 result
=LoadTypeLib(libnam
, &pTLib
);
4718 SysFreeString(libnam
);
4720 if(SUCCEEDED(result
)) {
4721 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
4722 ITypeLib2_AddRef(pTLib
);
4726 if(SUCCEEDED(result
)) {
4727 if(pRefType
->index
== TLB_REF_USE_GUID
)
4728 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
4732 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
4736 ITypeLib2_Release(pTLib
);
4740 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
4741 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
4745 /* ITypeInfo::AddressOfMember
4747 * Retrieves the addresses of static functions or variables, such as those
4750 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
4751 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
4753 ICOM_THIS( ITypeInfoImpl
, iface
);
4754 FIXME("(%p) stub!\n", This
);
4758 /* ITypeInfo::CreateInstance
4760 * Creates a new instance of a type that describes a component object class
4763 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
4764 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
4766 ICOM_THIS( ITypeInfoImpl
, iface
);
4767 FIXME("(%p) stub!\n", This
);
4771 /* ITypeInfo::GetMops
4773 * Retrieves marshalling information.
4775 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
4778 ICOM_THIS( ITypeInfoImpl
, iface
);
4779 FIXME("(%p) stub!\n", This
);
4783 /* ITypeInfo::GetContainingTypeLib
4785 * Retrieves the containing type library and the index of the type description
4786 * within that type library.
4788 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
4789 ITypeLib
* *ppTLib
, UINT
*pIndex
)
4791 ICOM_THIS( ITypeInfoImpl
, iface
);
4793 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4795 *pIndex
=This
->index
;
4796 TRACE("returning pIndex=%d", *pIndex
);
4800 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
4801 ITypeLib2_AddRef(*ppTLib
);
4802 TRACE("returning ppTLib=%p", *ppTLib
);
4808 /* ITypeInfo::ReleaseTypeAttr
4810 * Releases a TYPEATTR previously returned by GetTypeAttr.
4813 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
4814 TYPEATTR
* pTypeAttr
)
4816 ICOM_THIS( ITypeInfoImpl
, iface
);
4817 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
4820 /* ITypeInfo::ReleaseFuncDesc
4822 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4824 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
4826 FUNCDESC
*pFuncDesc
)
4828 ICOM_THIS( ITypeInfoImpl
, iface
);
4829 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
4832 /* ITypeInfo::ReleaseVarDesc
4834 * Releases a VARDESC previously returned by GetVarDesc.
4836 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
4839 ICOM_THIS( ITypeInfoImpl
, iface
);
4840 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
4843 /* ITypeInfo2::GetTypeKind
4845 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4848 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
4849 TYPEKIND
*pTypeKind
)
4851 ICOM_THIS( ITypeInfoImpl
, iface
);
4852 *pTypeKind
=This
->TypeAttr
.typekind
;
4853 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
4857 /* ITypeInfo2::GetTypeFlags
4859 * Returns the type flags without any allocations. This returns a DWORD type
4860 * flag, which expands the type flags without growing the TYPEATTR (type
4864 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
4866 ICOM_THIS( ITypeInfoImpl
, iface
);
4867 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
4868 TRACE("(%p) flags 0x%lx\n", This
,*pTypeFlags
);
4872 /* ITypeInfo2::GetFuncIndexOfMemId
4873 * Binds to a specific member based on a known DISPID, where the member name
4874 * is not known (for example, when binding to a default member).
4877 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
4878 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
4880 ICOM_THIS( ITypeInfoImpl
, iface
);
4881 TLBFuncDesc
*pFuncInfo
;
4884 /* FIXME: should check for invKind??? */
4885 for(i
=0, pFuncInfo
=This
->funclist
;pFuncInfo
&&
4886 memid
!= pFuncInfo
->funcdesc
.memid
; i
++, pFuncInfo
=pFuncInfo
->next
);
4892 result
=E_INVALIDARG
;
4894 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
4895 memid
, invKind
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4899 /* TypeInfo2::GetVarIndexOfMemId
4901 * Binds to a specific member based on a known DISPID, where the member name
4902 * is not known (for example, when binding to a default member).
4905 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
4906 MEMBERID memid
, UINT
*pVarIndex
)
4908 ICOM_THIS( ITypeInfoImpl
, iface
);
4909 TLBVarDesc
*pVarInfo
;
4912 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
4913 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
4920 result
=E_INVALIDARG
;
4922 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
4923 memid
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4927 /* ITypeInfo2::GetCustData
4929 * Gets the custom data
4931 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
4936 ICOM_THIS( ITypeInfoImpl
, iface
);
4937 TLBCustData
*pCData
;
4939 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4940 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4942 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4946 VariantInit( pVarVal
);
4947 VariantCopy( pVarVal
, &pCData
->data
);
4950 return E_INVALIDARG
; /* FIXME: correct? */
4953 /* ITypeInfo2::GetFuncCustData
4955 * Gets the custom data
4957 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
4963 ICOM_THIS( ITypeInfoImpl
, iface
);
4964 TLBCustData
*pCData
=NULL
;
4965 TLBFuncDesc
* pFDesc
;
4967 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4968 pFDesc
=pFDesc
->next
);
4971 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4972 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4974 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4977 VariantInit( pVarVal
);
4978 VariantCopy( pVarVal
, &pCData
->data
);
4981 return E_INVALIDARG
; /* FIXME: correct? */
4984 /* ITypeInfo2::GetParamCustData
4986 * Gets the custom data
4988 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
4995 ICOM_THIS( ITypeInfoImpl
, iface
);
4996 TLBCustData
*pCData
=NULL
;
4997 TLBFuncDesc
* pFDesc
;
5000 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
5002 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
5003 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
5004 pCData
= pCData
->next
)
5005 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5007 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5011 VariantInit( pVarVal
);
5012 VariantCopy( pVarVal
, &pCData
->data
);
5015 return E_INVALIDARG
; /* FIXME: correct? */
5018 /* ITypeInfo2::GetVarCustData
5020 * Gets the custom data
5022 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
5028 ICOM_THIS( ITypeInfoImpl
, iface
);
5029 TLBCustData
*pCData
=NULL
;
5030 TLBVarDesc
* pVDesc
;
5033 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
5037 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5039 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5043 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5047 VariantInit( pVarVal
);
5048 VariantCopy( pVarVal
, &pCData
->data
);
5051 return E_INVALIDARG
; /* FIXME: correct? */
5054 /* ITypeInfo2::GetImplCustData
5056 * Gets the custom data
5058 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
5064 ICOM_THIS( ITypeInfoImpl
, iface
);
5065 TLBCustData
*pCData
=NULL
;
5066 TLBImplType
* pRDesc
;
5069 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
5073 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
5075 if( IsEqualIID(guid
, &pCData
->guid
)) break;
5079 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
5083 VariantInit( pVarVal
);
5084 VariantCopy( pVarVal
, &pCData
->data
);
5087 return E_INVALIDARG
; /* FIXME: correct? */
5090 /* ITypeInfo2::GetDocumentation2
5092 * Retrieves the documentation string, the complete Help file name and path,
5093 * the localization context to use, and the context ID for the library Help
5094 * topic in the Help file.
5097 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
5101 BSTR
*pbstrHelpString
,
5102 DWORD
*pdwHelpStringContext
,
5103 BSTR
*pbstrHelpStringDll
)
5105 ICOM_THIS( ITypeInfoImpl
, iface
);
5106 TLBFuncDesc
* pFDesc
;
5107 TLBVarDesc
* pVDesc
;
5108 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5109 "HelpStringContext(%p) HelpStringDll(%p)\n",
5110 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
5111 pbstrHelpStringDll
);
5112 /* the help string should be obtained from the helpstringdll,
5113 * using the _DLLGetDocumentation function, based on the supplied
5114 * lcid. Nice to do sometime...
5116 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
5118 *pbstrHelpString
=SysAllocString(This
->Name
);
5119 if(pdwHelpStringContext
)
5120 *pdwHelpStringContext
=This
->dwHelpStringContext
;
5121 if(pbstrHelpStringDll
)
5122 *pbstrHelpStringDll
=
5123 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5125 }else {/* for a member */
5126 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
5127 if(pFDesc
->funcdesc
.memid
==memid
){
5129 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
5130 if(pdwHelpStringContext
)
5131 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
5132 if(pbstrHelpStringDll
)
5133 *pbstrHelpStringDll
=
5134 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5137 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
5138 if(pVDesc
->vardesc
.memid
==memid
){
5140 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
5141 if(pdwHelpStringContext
)
5142 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
5143 if(pbstrHelpStringDll
)
5144 *pbstrHelpStringDll
=
5145 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
5149 return TYPE_E_ELEMENTNOTFOUND
;
5152 /* ITypeInfo2::GetAllCustData
5154 * Gets all custom data items for the Type info.
5157 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
5159 CUSTDATA
*pCustData
)
5161 ICOM_THIS( ITypeInfoImpl
, iface
);
5162 TLBCustData
*pCData
;
5165 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
5167 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
5168 if(pCustData
->prgCustData
){
5169 pCustData
->cCustData
=This
->ctCustData
;
5170 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
5171 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5172 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
5175 ERR(" OUT OF MEMORY! \n");
5176 return E_OUTOFMEMORY
;
5181 /* ITypeInfo2::GetAllFuncCustData
5183 * Gets all custom data items for the specified Function
5186 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
5189 CUSTDATA
*pCustData
)
5191 ICOM_THIS( ITypeInfoImpl
, iface
);
5192 TLBCustData
*pCData
;
5193 TLBFuncDesc
* pFDesc
;
5195 TRACE("(%p) index %d\n", This
, index
);
5196 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
5197 pFDesc
=pFDesc
->next
)
5200 pCustData
->prgCustData
=
5201 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5202 if(pCustData
->prgCustData
){
5203 pCustData
->cCustData
=pFDesc
->ctCustData
;
5204 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
5205 pCData
= pCData
->next
){
5206 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5207 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5211 ERR(" OUT OF MEMORY! \n");
5212 return E_OUTOFMEMORY
;
5216 return TYPE_E_ELEMENTNOTFOUND
;
5219 /* ITypeInfo2::GetAllParamCustData
5221 * Gets all custom data items for the Functions
5224 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
5225 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
5227 ICOM_THIS( ITypeInfoImpl
, iface
);
5228 TLBCustData
*pCData
=NULL
;
5229 TLBFuncDesc
* pFDesc
;
5231 TRACE("(%p) index %d\n", This
, indexFunc
);
5232 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
5233 pFDesc
=pFDesc
->next
)
5235 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
5236 pCustData
->prgCustData
=
5237 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
5238 sizeof(CUSTDATAITEM
));
5239 if(pCustData
->prgCustData
){
5240 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
5241 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
5242 pCData
; i
++, pCData
= pCData
->next
){
5243 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5244 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5248 ERR(" OUT OF MEMORY! \n");
5249 return E_OUTOFMEMORY
;
5253 return TYPE_E_ELEMENTNOTFOUND
;
5256 /* ITypeInfo2::GetAllVarCustData
5258 * Gets all custom data items for the specified Variable
5261 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
5262 UINT index
, CUSTDATA
*pCustData
)
5264 ICOM_THIS( ITypeInfoImpl
, iface
);
5265 TLBCustData
*pCData
;
5266 TLBVarDesc
* pVDesc
;
5268 TRACE("(%p) index %d\n", This
, index
);
5269 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
5270 pVDesc
=pVDesc
->next
)
5273 pCustData
->prgCustData
=
5274 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5275 if(pCustData
->prgCustData
){
5276 pCustData
->cCustData
=pVDesc
->ctCustData
;
5277 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
5278 pCData
= pCData
->next
){
5279 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5280 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5284 ERR(" OUT OF MEMORY! \n");
5285 return E_OUTOFMEMORY
;
5289 return TYPE_E_ELEMENTNOTFOUND
;
5292 /* ITypeInfo2::GetAllImplCustData
5294 * Gets all custom data items for the specified implementation type
5297 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
5300 CUSTDATA
*pCustData
)
5302 ICOM_THIS( ITypeInfoImpl
, iface
);
5303 TLBCustData
*pCData
;
5304 TLBImplType
* pRDesc
;
5306 TRACE("(%p) index %d\n", This
, index
);
5307 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
5308 pRDesc
=pRDesc
->next
)
5311 pCustData
->prgCustData
=
5312 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
5313 if(pCustData
->prgCustData
){
5314 pCustData
->cCustData
=pRDesc
->ctCustData
;
5315 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
5316 pCData
= pCData
->next
){
5317 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
5318 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
5322 ERR(" OUT OF MEMORY! \n");
5323 return E_OUTOFMEMORY
;
5327 return TYPE_E_ELEMENTNOTFOUND
;
5330 static ICOM_VTABLE(ITypeInfo2
) tinfvt
=
5332 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5334 ITypeInfo_fnQueryInterface
,
5336 ITypeInfo_fnRelease
,
5338 ITypeInfo_fnGetTypeAttr
,
5339 ITypeInfo_fnGetTypeComp
,
5340 ITypeInfo_fnGetFuncDesc
,
5341 ITypeInfo_fnGetVarDesc
,
5342 ITypeInfo_fnGetNames
,
5343 ITypeInfo_fnGetRefTypeOfImplType
,
5344 ITypeInfo_fnGetImplTypeFlags
,
5345 ITypeInfo_fnGetIDsOfNames
,
5347 ITypeInfo_fnGetDocumentation
,
5348 ITypeInfo_fnGetDllEntry
,
5349 ITypeInfo_fnGetRefTypeInfo
,
5350 ITypeInfo_fnAddressOfMember
,
5351 ITypeInfo_fnCreateInstance
,
5352 ITypeInfo_fnGetMops
,
5353 ITypeInfo_fnGetContainingTypeLib
,
5354 ITypeInfo_fnReleaseTypeAttr
,
5355 ITypeInfo_fnReleaseFuncDesc
,
5356 ITypeInfo_fnReleaseVarDesc
,
5358 ITypeInfo2_fnGetTypeKind
,
5359 ITypeInfo2_fnGetTypeFlags
,
5360 ITypeInfo2_fnGetFuncIndexOfMemId
,
5361 ITypeInfo2_fnGetVarIndexOfMemId
,
5362 ITypeInfo2_fnGetCustData
,
5363 ITypeInfo2_fnGetFuncCustData
,
5364 ITypeInfo2_fnGetParamCustData
,
5365 ITypeInfo2_fnGetVarCustData
,
5366 ITypeInfo2_fnGetImplTypeCustData
,
5367 ITypeInfo2_fnGetDocumentation2
,
5368 ITypeInfo2_fnGetAllCustData
,
5369 ITypeInfo2_fnGetAllFuncCustData
,
5370 ITypeInfo2_fnGetAllParamCustData
,
5371 ITypeInfo2_fnGetAllVarCustData
,
5372 ITypeInfo2_fnGetAllImplTypeCustData
,