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.
63 #include "winnls.h" /* for PRIMARYLANGID */
64 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
67 #include "wine/unicode.h"
68 #include "wine/obj_base.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
77 /****************************************************************************
78 * QueryPathOfRegTypeLib [TYPELIB.14]
80 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
85 QueryPathOfRegTypeLib16(
86 REFGUID guid
, /* [in] referenced guid */
87 WORD wMaj
, /* [in] major version */
88 WORD wMin
, /* [in] minor version */
89 LCID lcid
, /* [in] locale id */
90 LPBSTR16 path
/* [out] path of typelib */
93 char typelibkey
[100],pathname
[260];
99 sprintf( typelibkey
, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
100 guid
->Data1
, guid
->Data2
, guid
->Data3
,
101 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
102 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
105 sprintf(xguid
,"<guid 0x%08lx>",(DWORD
)guid
);
106 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid
,wMaj
,wMin
,(DWORD
)lcid
,path
);
109 plen
= sizeof(pathname
);
110 if (RegQueryValueA(HKEY_LOCAL_MACHINE
,typelibkey
,pathname
,&plen
)) {
111 /* try again without lang specific id */
113 return QueryPathOfRegTypeLib16(guid
,wMaj
,wMin
,PRIMARYLANGID(lcid
),path
);
114 FIXME("key %s not found\n",typelibkey
);
117 *path
= SysAllocString16(pathname
);
121 /****************************************************************************
122 * QueryPathOfRegTypeLib [OLEAUT32.164]
127 QueryPathOfRegTypeLib(
128 REFGUID guid
, /* [in] referenced guid */
129 WORD wMaj
, /* [in] major version */
130 WORD wMin
, /* [in] minor version */
131 LCID lcid
, /* [in] locale id */
132 LPBSTR path
) /* [out] path of typelib */
134 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
135 string termination character on output strings */
142 char szTypeLibKey
[100];
143 char szPath
[MAX_PATH
];
144 DWORD dwPathLen
= sizeof(szPath
);
152 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID
, wMaj
, wMin
, (DWORD
)lcid
, path
);
158 sprintf(szTypeLibKey
,
159 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
160 guid
->Data1
, guid
->Data2
, guid
->Data3
,
161 guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
162 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7],
167 if (RegQueryValueA(HKEY_LOCAL_MACHINE
, szTypeLibKey
, szPath
, &dwPathLen
))
171 else if (myLCID
== lcid
)
173 /* try with sub-langid */
174 myLCID
= SUBLANGID(lcid
);
176 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
178 /* try with system langid */
188 DWORD len
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, szPath
, dwPathLen
, NULL
, 0 );
189 BSTR bstrPath
= SysAllocStringLen(NULL
,len
);
191 MultiByteToWideChar(CP_ACP
,
203 TRACE_(typelib
)("%s not found\n", szTypeLibKey
);
208 /******************************************************************************
209 * CreateTypeLib [OLEAUT32.160] creates a typelib
215 HRESULT WINAPI
CreateTypeLib(
216 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
218 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
221 /******************************************************************************
222 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
224 * Docs: OLECHAR FAR* szFile
225 * Docs: iTypeLib FAR* FAR* pptLib
231 HRESULT WINAPI
LoadTypeLib16(
232 LPOLESTR szFile
, /* [in] Name of file to load from */
233 ITypeLib
** pptLib
) /* [out] Pointer to pointer to loaded type library */
235 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR
)szFile
),pptLib
);
243 /******************************************************************************
244 * LoadTypeLib [OLEAUT32.161]
245 * Loads and registers a type library
247 * Docs: OLECHAR FAR* szFile
248 * Docs: iTypeLib FAR* FAR* pptLib
254 int TLB_ReadTypeLib(LPCWSTR file
, INT index
, ITypeLib2
**ppTypelib
);
256 HRESULT WINAPI
LoadTypeLib(
257 const OLECHAR
*szFile
,/* [in] Name of file to load from */
258 ITypeLib
* *pptLib
) /* [out] Pointer to pointer to loaded type library */
261 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
264 /******************************************************************************
265 * LoadTypeLibEx [OLEAUT32.183]
266 * Loads and optionally registers a type library
272 HRESULT WINAPI
LoadTypeLibEx(
273 LPCOLESTR szFile
, /* [in] Name of file to load from */
274 REGKIND regkind
, /* [in] Specify kind of registration */
275 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
277 WCHAR szPath
[MAX_PATH
+1], szFileCopy
[MAX_PATH
+1];
281 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
283 if(!SearchPathW(NULL
,szFile
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),szPath
,
286 /* Look for a trailing '\\' followed by an index */
287 pIndexStr
= strrchrW(szFile
, '\\');
288 if(pIndexStr
&& pIndexStr
!= szFile
&& *++pIndexStr
!= '\0') {
289 index
= atoiW(pIndexStr
);
290 memcpy(szFileCopy
, szFile
,
291 (pIndexStr
- szFile
- 1) * sizeof(WCHAR
));
292 szFileCopy
[pIndexStr
- szFile
- 1] = '\0';
293 if(!SearchPathW(NULL
,szFileCopy
,NULL
,sizeof(szPath
)/sizeof(WCHAR
),
295 return TYPE_E_CANTLOADLIBRARY
;
296 if (GetFileAttributesW(szFileCopy
) & FILE_ATTRIBUTE_DIRECTORY
)
297 return TYPE_E_CANTLOADLIBRARY
;
299 return TYPE_E_CANTLOADLIBRARY
;
302 TRACE("File %s index %d\n", debugstr_w(szPath
), index
);
304 res
= TLB_ReadTypeLib(szPath
, index
, (ITypeLib2
**)pptLib
);
309 case REGKIND_DEFAULT
:
310 /* FIXME: is this correct? */
311 if (!szFile
|| !szFile
[0] ||
312 (szFile
[0] != '\\' && szFile
[0] != '/' && szFile
[1] != ':'))
314 /* else fall-through */
315 case REGKIND_REGISTER
:
316 /* FIXME: Help path? */
317 if (!SUCCEEDED(res
= RegisterTypeLib(*pptLib
, (LPOLESTR
)szFile
, NULL
)))
319 IUnknown_Release(*pptLib
);
327 TRACE(" returns %08lx\n",res
);
331 /******************************************************************************
332 * LoadRegTypeLib [OLEAUT32.162]
334 HRESULT WINAPI
LoadRegTypeLib(
335 REFGUID rguid
, /* [in] referenced guid */
336 WORD wVerMajor
, /* [in] major version */
337 WORD wVerMinor
, /* [in] minor version */
338 LCID lcid
, /* [in] locale id */
339 ITypeLib
**ppTLib
) /* [out] path of typelib */
342 HRESULT res
=QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
346 res
= LoadTypeLib(bstr
, ppTLib
);
350 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
356 /******************************************************************************
357 * RegisterTypeLib [OLEAUT32.163]
358 * Adds information about a type library to the System Registry
360 * Docs: ITypeLib FAR * ptlib
361 * Docs: OLECHAR FAR* szFullPath
362 * Docs: OLECHAR FAR* szHelpDir
368 HRESULT WINAPI
RegisterTypeLib(
369 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
370 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
371 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
382 static const char *PSOA
= "{00020424-0000-0000-C000-000000000046}";
384 if (ptlib
== NULL
|| szFullPath
== NULL
)
387 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
390 StringFromGUID2(&attr
->guid
, guid
, 80);
391 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
392 snprintf(keyName
, sizeof(keyName
), "TypeLib\\%s\\%x.%x",
393 guidA
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
394 HeapFree(GetProcessHeap(), 0, guidA
);
397 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
398 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
402 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
404 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
405 (BYTE
*)doc
, lstrlenW(doc
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
413 /* FIXME: This *seems* to be 0 always, not sure though */
414 if (res
== S_OK
&& RegCreateKeyExA(key
, "0\\win32", 0, NULL
, 0,
415 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
417 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
418 (BYTE
*)szFullPath
, lstrlenW(szFullPath
) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
426 if (res
== S_OK
&& RegCreateKeyExA(key
, "FLAGS", 0, NULL
, 0,
427 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
430 /* FIXME: is %u correct? */
431 snprintf(buf
, sizeof(buf
), "%u", attr
->wLibFlags
);
432 if (RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
433 buf
, lstrlenA(buf
) + 1) != ERROR_SUCCESS
)
441 /* register OLE Automation-compatible interfaces for this typelib */
442 types
= ITypeLib_GetTypeInfoCount(ptlib
);
443 for (tidx
=0; tidx
<types
; tidx
++) {
444 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
445 LPOLESTR name
= NULL
;
446 ITypeInfo
*tinfo
= NULL
;
448 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
450 case TKIND_INTERFACE
:
451 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
452 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
455 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
456 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
459 TRACE_(typelib
)("%d: coclass %s\n", tidx
, debugstr_w(name
));
460 /* coclasses should probably not be registered? */
463 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
467 TYPEATTR
*tattr
= NULL
;
468 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
470 TRACE_(typelib
)("guid=%s, flags=%04x (",
471 debugstr_guid(&tattr
->guid
),
473 if (TRACE_ON(typelib
)) {
474 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
494 * FIXME: The 1 is just here until we implement rpcrt4
495 * stub/proxy handling. Until then it helps IShield
498 if (1 || (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
))
500 /* register interface<->typelib coupling */
501 StringFromGUID2(&tattr
->guid
, guid
, 80);
502 guidA
= HEAP_strdupWtoA(GetProcessHeap(), 0, guid
);
503 snprintf(keyName
, sizeof(keyName
), "Interface\\%s", guidA
);
504 HeapFree(GetProcessHeap(), 0, guidA
);
506 if (RegCreateKeyExA(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
507 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
) {
509 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
510 (BYTE
*)name
, lstrlenW(name
) * sizeof(OLECHAR
));
512 if (RegCreateKeyExA(key
, "ProxyStubClsid", 0, NULL
, 0,
513 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
514 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
518 if (RegCreateKeyExA(key
, "ProxyStubClsid32", 0, NULL
, 0,
519 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
520 RegSetValueExA(subKey
, NULL
, 0, REG_SZ
,
525 if (RegCreateKeyExA(key
, "TypeLib", 0, NULL
, 0,
526 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
528 StringFromGUID2(&attr
->guid
, guid
, 80);
529 snprintf(ver
, sizeof(ver
), "%x.%x",
530 attr
->wMajorVerNum
, attr
->wMinorVerNum
);
531 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
532 (BYTE
*)guid
, lstrlenW(guid
) * sizeof(OLECHAR
));
533 RegSetValueExA(subKey
, "Version", 0, REG_SZ
,
540 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
542 ITypeInfo_Release(tinfo
);
549 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
555 /******************************************************************************
556 * UnRegisterTypeLib [OLEAUT32.186]
557 * Removes information about a type library from the System Registry
564 HRESULT WINAPI
UnRegisterTypeLib(
565 REFGUID libid
, /* [in] Guid of the library */
566 WORD wVerMajor
, /* [in] major version */
567 WORD wVerMinor
, /* [in] minor version */
568 LCID lcid
, /* [in] locale id */
571 TRACE("(IID: %s): stub\n",debugstr_guid(libid
));
572 return S_OK
; /* FIXME: pretend everything is OK */
575 /****************************************************************************
576 * OaBuildVersion (TYPELIB.15)
578 * known TYPELIB.DLL versions:
580 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
581 * OLE 2.02 1993-94 02 3002
584 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
585 * OLE 2.1 NT 1993-95 ?? ???
586 * OLE 2.3.1 W95 23 700
587 * OLE2 4.0 NT4SP6 1993-98 40 4277
589 DWORD WINAPI
OaBuildVersion16(void)
591 /* FIXME: I'd like to return the highest currently known version value
592 * in case the user didn't force a --winver, but I don't know how
593 * to retrieve the "versionForced" info from misc/version.c :(
594 * (this would be useful in other places, too) */
595 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
596 switch(GetVersion() & 0x8000ffff) /* mask off build number */
598 case 0x80000a03: /* WIN31 */
599 return MAKELONG(3027, 3); /* WfW 3.11 */
600 case 0x80000004: /* WIN95 */
601 return MAKELONG(700, 23); /* Win95A */
602 case 0x80000a04: /* WIN98 */
603 return MAKELONG(3024, 10); /* W98 SE */
604 case 0x00000004: /* NT4 */
605 return MAKELONG(4277, 40); /* NT4 SP6 */
607 FIXME("Version value not known yet. Please investigate it!\n");
612 /* for better debugging info leave the static out for the time being */
615 /*======================= ITypeLib implementation =======================*/
617 typedef struct tagTLBCustData
621 struct tagTLBCustData
* next
;
624 /* data structure for import typelibs */
625 typedef struct tagTLBImpLib
627 int offset
; /* offset in the file (MSFT)
628 offset in nametable (SLTG)
629 just used to identify library while reading
631 GUID guid
; /* libid */
632 BSTR name
; /* name */
634 LCID lcid
; /* lcid of imported typelib */
636 WORD wVersionMajor
; /* major version number */
637 WORD wVersionMinor
; /* minor version number */
639 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
640 NULL if not yet loaded */
641 struct tagTLBImpLib
* next
;
644 /* internal ITypeLib data */
645 typedef struct tagITypeLibImpl
647 ICOM_VFIELD(ITypeLib2
);
649 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
651 /* strings can be stored in tlb as multibyte strings BUT they are *always*
652 * exported to the application as a UNICODE string.
658 unsigned long dwHelpContext
;
659 int TypeInfoCount
; /* nr of typeinfo's in librarry */
660 struct tagITypeInfoImpl
*pTypeInfo
; /* linked list of type info data */
661 int ctCustData
; /* number of items in cust data list */
662 TLBCustData
* pCustData
; /* linked list to cust data */
663 TLBImpLib
* pImpLibs
; /* linked list to all imported typelibs */
664 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
665 libary. Only used while read MSFT
669 static struct ICOM_VTABLE(ITypeLib2
) tlbvt
;
671 /* ITypeLib methods */
672 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
673 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
675 /*======================= ITypeInfo implementation =======================*/
677 /* data for refernced types */
678 typedef struct tagTLBRefType
680 INT index
; /* Type index for internal ref or for external ref
681 it the format is SLTG. -2 indicates to
684 GUID guid
; /* guid of the referenced type */
685 /* if index == TLB_REF_USE_GUID */
687 HREFTYPE reference
; /* The href of this ref */
688 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
689 TLB_REF_INTERNAL for internal refs
690 TLB_REF_NOT_FOUND for broken refs */
692 struct tagTLBRefType
* next
;
695 #define TLB_REF_USE_GUID -2
697 #define TLB_REF_INTERNAL (void*)-2
698 #define TLB_REF_NOT_FOUND (void*)-1
700 /* internal Parameter data */
701 typedef struct tagTLBParDesc
705 TLBCustData
* pCustData
; /* linked list to cust data */
708 /* internal Function data */
709 typedef struct tagTLBFuncDesc
711 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
712 BSTR Name
; /* the name of this function */
713 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
715 int HelpStringContext
;
717 BSTR Entry
; /* if its Hiword==0, it numeric; -1 is not present*/
719 TLBCustData
* pCustData
; /* linked list to cust data; */
720 struct tagTLBFuncDesc
* next
;
723 /* internal Variable data */
724 typedef struct tagTLBVarDesc
726 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
727 BSTR Name
; /* the name of this variable */
729 int HelpStringContext
; /* FIXME: where? */
732 TLBCustData
* pCustData
;/* linked list to cust data; */
733 struct tagTLBVarDesc
* next
;
736 /* internal implemented interface data */
737 typedef struct tagTLBImplType
739 HREFTYPE hRef
; /* hRef of interface */
740 int implflags
; /* IMPLFLAG_*s */
742 TLBCustData
* pCustData
;/* linked list to custom data; */
743 struct tagTLBImplType
*next
;
746 /* internal TypeInfo data */
747 typedef struct tagITypeInfoImpl
749 ICOM_VFIELD(ITypeInfo2
);
751 TYPEATTR TypeAttr
; /* _lots_ of type information. */
752 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
753 int index
; /* index in this typelib; */
754 /* type libs seem to store the doc strings in ascii
755 * so why should we do it in unicode?
759 unsigned long dwHelpContext
;
760 unsigned long dwHelpStringContext
;
763 TLBFuncDesc
* funclist
; /* linked list with function descriptions */
766 TLBVarDesc
* varlist
; /* linked list with variable descriptions */
768 /* Implemented Interfaces */
769 TLBImplType
* impltypelist
;
771 TLBRefType
* reflist
;
773 TLBCustData
* pCustData
; /* linked list to cust data; */
774 struct tagITypeInfoImpl
* next
;
777 static struct ICOM_VTABLE(ITypeInfo2
) tinfvt
;
779 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor();
781 typedef struct tagTLBContext
783 unsigned int oStart
; /* start of TLB in file */
784 unsigned int pos
; /* current pos */
785 unsigned int length
; /* total length */
786 void *mapping
; /* memory mapping */
787 MSFT_SegDir
* pTblDir
;
788 ITypeLibImpl
* pLibInfo
;
792 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int offset
);
797 static void dump_VarType(VARTYPE vt
,char *szVarType
) {
798 /* FIXME : we could have better trace here, depending on the VARTYPE
801 if (vt
& VT_RESERVED
)
802 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
804 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
806 szVarType
+= strlen(strcpy(szVarType
, "array of "));
808 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
809 switch(vt
& VT_TYPEMASK
) {
810 case VT_UI1
: sprintf(szVarType
, "VT_UI"); break;
811 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
812 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
813 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
814 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
815 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
816 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
817 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
818 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
819 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
820 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
821 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
822 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
823 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
824 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
825 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
826 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
827 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
828 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
829 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED\n"); break;
830 default: sprintf(szVarType
, "unknown(%d)", vt
& VT_TYPEMASK
); break;
834 static void dump_TypeDesc(TYPEDESC
*pTD
,char *szVarType
) {
835 if (pTD
->vt
& VT_RESERVED
)
836 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
837 if (pTD
->vt
& VT_BYREF
)
838 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
839 if (pTD
->vt
& VT_ARRAY
)
840 szVarType
+= strlen(strcpy(szVarType
, "array of "));
841 if (pTD
->vt
& VT_VECTOR
)
842 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
843 switch(pTD
->vt
& VT_TYPEMASK
) {
844 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
845 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
846 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
847 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
848 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
849 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
850 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
851 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
852 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
853 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
854 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
855 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
856 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
857 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
858 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
859 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
860 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
861 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
862 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
863 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx",
864 pTD
->u
.hreftype
); break;
865 case VT_PTR
: sprintf(szVarType
, "ptr to ");
866 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
868 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
869 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
871 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
872 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
873 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
876 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
880 static void dump_ELEMDESC(ELEMDESC
*edesc
) {
882 dump_TypeDesc(&edesc
->tdesc
,buf
);
883 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
884 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc
->u
.paramdesc
.wParamFlags
);
885 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
887 static void dump_FUNCDESC(FUNCDESC
*funcdesc
) {
889 MESSAGE("memid is %08lx\n",funcdesc
->memid
);
890 for (i
=0;i
<funcdesc
->cParams
;i
++) {
891 MESSAGE("Param %d:\n",i
);
892 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
894 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
895 switch (funcdesc
->funckind
) {
896 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
897 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
898 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
899 case FUNC_STATIC
: MESSAGE("static");break;
900 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
901 default: MESSAGE("unknown");break;
903 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
904 switch (funcdesc
->invkind
) {
905 case INVOKE_FUNC
: MESSAGE("func");break;
906 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
907 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
908 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
910 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
911 switch (funcdesc
->callconv
) {
912 case CC_CDECL
: MESSAGE("cdecl");break;
913 case CC_PASCAL
: MESSAGE("pascal");break;
914 case CC_STDCALL
: MESSAGE("stdcall");break;
915 case CC_SYSCALL
: MESSAGE("syscall");break;
918 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
919 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
920 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
922 static void dump_TLBFuncDescOne(TLBFuncDesc
* pfd
)
925 if (!TRACE_ON(typelib
))
927 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
928 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
929 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
932 dump_FUNCDESC(&(pfd
->funcdesc
));
934 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
935 MESSAGE("\tentry: %s\n", debugstr_w(pfd
->Entry
));
937 static void dump_TLBFuncDesc(TLBFuncDesc
* pfd
)
941 dump_TLBFuncDescOne(pfd
);
945 static void dump_TLBVarDesc(TLBVarDesc
* pvd
)
949 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
954 static void dump_TLBImpLib(TLBImpLib
*import
)
956 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
957 debugstr_w(import
->name
));
958 TRACE_(typelib
)("v%d.%d lcid=%lx offset=%x\n", import
->wVersionMajor
,
959 import
->wVersionMinor
, import
->lcid
, import
->offset
);
962 static void dump_TLBRefType(TLBRefType
* prt
)
966 TRACE_(typelib
)("href:0x%08lx\n", prt
->reference
);
968 TRACE_(typelib
)("%s\n", debugstr_guid(&(prt
->guid
)));
970 TRACE_(typelib
)("type no: %d\n", prt
->index
);
972 if(prt
->pImpTLInfo
!= TLB_REF_INTERNAL
&&
973 prt
->pImpTLInfo
!= TLB_REF_NOT_FOUND
) {
974 TRACE_(typelib
)("in lib\n");
975 dump_TLBImpLib(prt
->pImpTLInfo
);
981 static void dump_TLBImplType(TLBImplType
* impl
)
985 "implementing/inheriting interface hRef = %lx implflags %x\n",
986 impl
->hRef
, impl
->implflags
);
991 static void dump_Variant(VARIANT
* pvar
)
996 TRACE("(%p)\n", pvar
);
1000 ZeroMemory(szVarType
, sizeof(szVarType
));
1002 /* FIXME : we could have better trace here, depending on the VARTYPE
1005 dump_VarType(V_VT(pvar
),szVarType
);
1007 TRACE("VARTYPE: %s\n", szVarType
);
1009 if (V_VT(pvar
) & VT_BYREF
) {
1010 ref
= V_UNION(pvar
, byref
);
1013 else ref
= &V_UNION(pvar
, cVal
);
1015 if (V_VT(pvar
) & VT_ARRAY
) {
1019 if (V_VT(pvar
) & VT_VECTOR
) {
1027 TRACE("%d\n", *(short*)ref
);
1031 TRACE("%d\n", *(INT
*)ref
);
1035 TRACE("%3.3e\n", *(float*)ref
);
1039 TRACE("%3.3e\n", *(double*)ref
);
1043 TRACE("%s\n", *(VARIANT_BOOL
*)ref
? "TRUE" : "FALSE");
1047 TRACE("%s\n", debugstr_w(*(BSTR
*)ref
));
1052 TRACE("%p\n", *(LPVOID
*)ref
);
1056 if (V_VT(pvar
) & VT_BYREF
) dump_Variant(ref
);
1060 TRACE("(?)%ld\n", *(long*)ref
);
1065 static void dump_DispParms(DISPPARAMS
* pdp
)
1069 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1071 while (index
< pdp
->cArgs
)
1073 dump_Variant( &pdp
->rgvarg
[index
] );
1078 static char * typekind_desc
[] =
1091 static void dump_TypeInfo(ITypeInfoImpl
* pty
)
1093 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1094 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1095 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1096 TRACE("fct:%u var:%u impl:%u\n",
1097 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1098 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1099 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1100 dump_TLBFuncDesc(pty
->funclist
);
1101 dump_TLBVarDesc(pty
->varlist
);
1102 dump_TLBImplType(pty
->impltypelist
);
1105 static TYPEDESC stndTypeDesc
[VT_LPWSTR
+1]=
1107 /* VT_LPWSTR is largest type that */
1108 /* may appear in type description*/
1109 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1110 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1111 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1112 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1113 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1114 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1118 static void TLB_abort()
1122 static void * TLB_Alloc(unsigned size
)
1125 if((ret
=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,size
))==NULL
){
1127 ERR("cannot allocate memory\n");
1132 static void TLB_Free(void * ptr
)
1134 HeapFree(GetProcessHeap(), 0, ptr
);
1138 /**********************************************************************
1140 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1143 DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, long where
)
1145 TRACE_(typelib
)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1146 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1148 if (where
!= DO_NOT_SEEK
)
1150 where
+= pcx
->oStart
;
1151 if (where
> pcx
->length
)
1154 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
1159 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1160 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1165 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1167 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1169 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1170 memset(pGuid
,0, sizeof(GUID
));
1173 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1176 BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1179 MSFT_NameIntro niName
;
1181 WCHAR
* pwstring
= NULL
;
1182 BSTR bstrName
= NULL
;
1184 MSFT_Read(&niName
, sizeof(niName
), pcx
,
1185 pcx
->pTblDir
->pNametab
.offset
+offset
);
1186 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1187 name
=TLB_Alloc((niName
.namelen
& 0xff) +1);
1188 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1189 name
[niName
.namelen
& 0xff]='\0';
1191 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1194 /* no invalid characters in string */
1197 pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1199 /* don't check for invalid character since this has been done previously */
1200 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, pwstring
, lengthInChars
);
1202 bstrName
= SysAllocStringLen(pwstring
, lengthInChars
);
1203 lengthInChars
= SysStringLen(bstrName
);
1204 HeapFree(GetProcessHeap(), 0, pwstring
);
1207 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1211 BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1218 if(offset
<0) return NULL
;
1219 MSFT_Read(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1220 if(length
<= 0) return 0;
1221 string
=TLB_Alloc(length
+1);
1222 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1223 string
[length
]='\0';
1225 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1226 string
, -1, NULL
, 0);
1228 /* no invalid characters in string */
1231 WCHAR
* pwstring
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*lengthInChars
);
1233 /* don't check for invalid character since this has been done previously */
1234 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, pwstring
, lengthInChars
);
1236 bstr
= SysAllocStringLen(pwstring
, lengthInChars
);
1237 lengthInChars
= SysStringLen(bstr
);
1238 HeapFree(GetProcessHeap(), 0, pwstring
);
1241 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1245 * read a value and fill a VARIANT structure
1247 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1251 TRACE_(typelib
)("\n");
1253 if(offset
<0) { /* data are packed in here */
1254 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1255 V_UNION(pVar
, iVal
) = offset
& 0xffff;
1258 MSFT_Read(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1259 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1260 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1261 switch (V_VT(pVar
)){
1262 case VT_EMPTY
: /* FIXME: is this right? */
1263 case VT_NULL
: /* FIXME: is this right? */
1264 case VT_I2
: /* this should not happen */
1275 case VT_VOID
: /* FIXME: is this right? */
1283 case VT_DECIMAL
: /* FIXME: is this right? */
1286 /* pointer types with known behaviour */
1289 MSFT_Read(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1291 FIXME("BSTR length = %d?\n", size
);
1293 ptr
=TLB_Alloc(size
);/* allocate temp buffer */
1294 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1295 V_UNION(pVar
, bstrVal
)=SysAllocStringLen(NULL
,size
);
1296 /* FIXME: do we need a AtoW conversion here? */
1297 V_UNION(pVar
, bstrVal
[size
])=L
'\0';
1298 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1303 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1310 case VT_USERDEFINED
:
1316 case VT_STREAMED_OBJECT
:
1317 case VT_STORED_OBJECT
:
1318 case VT_BLOB_OBJECT
:
1323 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1327 if(size
>0) /* (big|small) endian correct? */
1328 MSFT_Read(&(V_UNION(pVar
, iVal
)), size
, pcx
, DO_NOT_SEEK
);
1332 * create a linked list with custom data
1334 static int MSFT_CustData( TLBContext
*pcx
, int offset
, TLBCustData
** ppCustData
)
1340 TRACE_(typelib
)("\n");
1344 pNew
=TLB_Alloc(sizeof(TLBCustData
));
1345 MSFT_Read(&entry
, sizeof(entry
), pcx
,
1346 pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1347 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1348 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1349 /* add new custom data at head of the list */
1350 pNew
->next
=*ppCustData
;
1352 offset
= entry
.next
;
1357 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1361 pTd
->vt
=type
& VT_TYPEMASK
;
1363 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1365 if(pTd
->vt
== VT_USERDEFINED
)
1366 MSFT_DoRefType(pcx
, pTI
, pTd
->u
.hreftype
);
1368 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1372 MSFT_DoFuncs(TLBContext
* pcx
,
1377 TLBFuncDesc
** pptfd
)
1380 * member information is stored in a data structure at offset
1381 * indicated by the memoffset field of the typeinfo structure
1382 * There are several distinctive parts.
1383 * the first part starts with a field that holds the total length
1384 * of this (first) part excluding this field. Then follow the records,
1385 * for each member there is one record.
1387 * First entry is always the length of the record (excluding this
1389 * Rest of the record depends on the type of the member. If there is
1390 * a field indicating the member type (function variable intereface etc)
1391 * I have not found it yet. At this time we depend on the information
1392 * in the type info and the usual order how things are stored.
1394 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1397 * Third is a equal sized array with file offsets to the name entry
1400 * Forth and last (?) part is an array with offsets to the records in the
1401 * first part of this file segment.
1404 int infolen
, nameoffset
, reclength
, nrattributes
, i
;
1405 int recoffset
= offset
+ sizeof(INT
);
1408 MSFT_FuncRecord
* pFuncRec
=(MSFT_FuncRecord
*) recbuf
;
1410 TRACE_(typelib
)("\n");
1412 MSFT_Read(&infolen
, sizeof(INT
), pcx
, offset
);
1414 for ( i
= 0; i
< cFuncs
; i
++ )
1416 *pptfd
= TLB_Alloc(sizeof(TLBFuncDesc
));
1418 /* name, eventually add to a hash table */
1419 MSFT_Read(&nameoffset
,
1422 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1424 (*pptfd
)->Name
= MSFT_ReadName(pcx
, nameoffset
);
1426 /* read the function information record */
1427 MSFT_Read(&reclength
, sizeof(INT
), pcx
, recoffset
);
1431 MSFT_Read(pFuncRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
) ;
1433 /* do the attributes */
1434 nrattributes
= (reclength
- pFuncRec
->nrargs
* 3 * sizeof(int) - 0x18)
1437 if ( nrattributes
> 0 )
1439 (*pptfd
)->helpcontext
= pFuncRec
->OptAttr
[0] ;
1441 if ( nrattributes
> 1 )
1443 (*pptfd
)->HelpString
= MSFT_ReadString(pcx
,
1444 pFuncRec
->OptAttr
[1]) ;
1446 if ( nrattributes
> 2 )
1448 if ( pFuncRec
->FKCCIC
& 0x2000 )
1450 (*pptfd
)->Entry
= (WCHAR
*) pFuncRec
->OptAttr
[2] ;
1454 (*pptfd
)->Entry
= MSFT_ReadString(pcx
,
1455 pFuncRec
->OptAttr
[2]);
1457 if( nrattributes
> 5 )
1459 (*pptfd
)->HelpStringContext
= pFuncRec
->OptAttr
[5] ;
1461 if ( nrattributes
> 6 && pFuncRec
->FKCCIC
& 0x80 )
1464 pFuncRec
->OptAttr
[6],
1465 &(*pptfd
)->pCustData
);
1472 /* fill the FuncDesc Structure */
1473 MSFT_Read( & (*pptfd
)->funcdesc
.memid
,
1475 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1477 (*pptfd
)->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
1478 (*pptfd
)->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
1479 (*pptfd
)->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
1480 (*pptfd
)->funcdesc
.cParams
= pFuncRec
->nrargs
;
1481 (*pptfd
)->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
1482 (*pptfd
)->funcdesc
.oVft
= pFuncRec
->VtableOffset
;
1483 (*pptfd
)->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
1487 &(*pptfd
)->funcdesc
.elemdescFunc
.tdesc
,
1490 /* do the parameters/arguments */
1491 if(pFuncRec
->nrargs
)
1494 MSFT_ParameterInfo paraminfo
;
1496 (*pptfd
)->funcdesc
.lprgelemdescParam
=
1497 TLB_Alloc(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
1499 (*pptfd
)->pParamDesc
=
1500 TLB_Alloc(pFuncRec
->nrargs
* sizeof(TLBParDesc
));
1502 MSFT_Read(¶minfo
,
1505 recoffset
+ reclength
-
1506 pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
1508 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
1510 TYPEDESC
* lpArgTypeDesc
= 0;
1514 &(*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
,
1517 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
1519 (*pptfd
)->pParamDesc
[j
].Name
= (void *) paraminfo
.oName
;
1521 /* SEEK value = jump to offset,
1522 * from there jump to the end of record,
1523 * go back by (j-1) arguments
1525 MSFT_Read( ¶minfo
,
1526 sizeof(MSFT_ParameterInfo
), pcx
,
1527 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
1528 * sizeof(MSFT_ParameterInfo
)));
1530 & ((*pptfd
)->funcdesc
.lprgelemdescParam
[j
].tdesc
);
1532 while ( lpArgTypeDesc
!= NULL
)
1534 switch ( lpArgTypeDesc
->vt
)
1537 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1541 lpArgTypeDesc
= & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1544 case VT_USERDEFINED
:
1545 MSFT_DoRefType(pcx
, pTI
,
1546 lpArgTypeDesc
->u
.hreftype
);
1548 lpArgTypeDesc
= NULL
;
1552 lpArgTypeDesc
= NULL
;
1558 /* parameter is the return value! */
1559 if ( paraminfo
.Flags
& PARAMFLAG_FRETVAL
)
1561 TYPEDESC
* lpArgTypeDesc
;
1563 (*pptfd
)->funcdesc
.elemdescFunc
=
1564 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
];
1566 lpArgTypeDesc
= & ((*pptfd
)->funcdesc
.elemdescFunc
.tdesc
) ;
1568 while ( lpArgTypeDesc
!= NULL
)
1570 switch ( lpArgTypeDesc
->vt
)
1573 lpArgTypeDesc
= lpArgTypeDesc
->u
.lptdesc
;
1577 & (lpArgTypeDesc
->u
.lpadesc
->tdescElem
);
1581 case VT_USERDEFINED
:
1584 lpArgTypeDesc
->u
.hreftype
);
1586 lpArgTypeDesc
= NULL
;
1590 lpArgTypeDesc
= NULL
;
1595 /* second time around */
1596 for(j
=0;j
<pFuncRec
->nrargs
;j
++)
1599 (*pptfd
)->pParamDesc
[j
].Name
=
1600 MSFT_ReadName( pcx
, (int)(*pptfd
)->pParamDesc
[j
].Name
);
1603 if ( (PARAMFLAG_FHASDEFAULT
&
1604 (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
) &&
1605 ((pFuncRec
->FKCCIC
) & 0x1000) )
1607 INT
* pInt
= (INT
*)((char *)pFuncRec
+
1609 (pFuncRec
->nrargs
* 4 + 1) * sizeof(INT
) );
1611 PARAMDESC
* pParamDesc
= & (*pptfd
)->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
;
1613 pParamDesc
->pparamdescex
= TLB_Alloc(sizeof(PARAMDESCEX
));
1614 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
1616 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
1620 if ( nrattributes
> 7 + j
&& pFuncRec
->FKCCIC
& 0x80 )
1623 pFuncRec
->OptAttr
[7+j
],
1624 &(*pptfd
)->pParamDesc
[j
].pCustData
);
1629 /* scode is not used: archaic win16 stuff FIXME: right? */
1630 (*pptfd
)->funcdesc
.cScodes
= 0 ;
1631 (*pptfd
)->funcdesc
.lprgscode
= NULL
;
1633 pptfd
= & ((*pptfd
)->next
);
1634 recoffset
+= reclength
;
1637 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
1638 int cVars
, int offset
, TLBVarDesc
** pptvd
)
1640 int infolen
, nameoffset
, reclength
;
1642 MSFT_VarRecord
* pVarRec
=(MSFT_VarRecord
*) recbuf
;
1646 TRACE_(typelib
)("\n");
1648 MSFT_Read(&infolen
,sizeof(INT
), pcx
, offset
);
1649 MSFT_Read(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
1650 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
1651 recoffset
+= offset
+sizeof(INT
);
1652 for(i
=0;i
<cVars
;i
++){
1653 *pptvd
=TLB_Alloc(sizeof(TLBVarDesc
));
1654 /* name, eventually add to a hash table */
1655 MSFT_Read(&nameoffset
, sizeof(INT
), pcx
,
1656 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
1657 (*pptvd
)->Name
=MSFT_ReadName(pcx
, nameoffset
);
1658 /* read the variable information record */
1659 MSFT_Read(&reclength
, sizeof(INT
), pcx
, recoffset
);
1661 MSFT_Read(pVarRec
, reclength
- sizeof(INT
), pcx
, DO_NOT_SEEK
) ;
1663 if(reclength
>(6*sizeof(INT
)) )
1664 (*pptvd
)->HelpContext
=pVarRec
->HelpContext
;
1665 if(reclength
>(7*sizeof(INT
)) )
1666 (*pptvd
)->HelpString
= MSFT_ReadString(pcx
, pVarRec
->oHelpString
) ;
1667 if(reclength
>(8*sizeof(INT
)) )
1668 if(reclength
>(9*sizeof(INT
)) )
1669 (*pptvd
)->HelpStringContext
=pVarRec
->HelpStringContext
;
1670 /* fill the VarDesc Structure */
1671 MSFT_Read(&(*pptvd
)->vardesc
.memid
, sizeof(INT
), pcx
,
1672 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
1673 (*pptvd
)->vardesc
.varkind
= pVarRec
->VarKind
;
1674 (*pptvd
)->vardesc
.wVarFlags
= pVarRec
->Flags
;
1675 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
1676 &(*pptvd
)->vardesc
.elemdescVar
.tdesc
, pTI
);
1677 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1678 if(pVarRec
->VarKind
== VAR_CONST
){
1679 (*pptvd
)->vardesc
.u
.lpvarValue
=TLB_Alloc(sizeof(VARIANT
));
1680 MSFT_ReadValue((*pptvd
)->vardesc
.u
.lpvarValue
,
1681 pVarRec
->OffsValue
, pcx
);
1683 (*pptvd
)->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
1684 pptvd
=&((*pptvd
)->next
);
1685 recoffset
+= reclength
;
1688 /* fill in data for a hreftype (offset). When the refernced type is contained
1689 * in the typelib, it's just an (file) offset in the type info base dir.
1690 * If comes from import, it's an offset+1 in the ImpInfo table
1692 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeInfoImpl
*pTI
,
1696 TLBRefType
**ppRefType
= &pTI
->reflist
;
1698 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
1701 if((*ppRefType
)->reference
== offset
)
1703 ppRefType
= &(*ppRefType
)->next
;
1706 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1707 sizeof(**ppRefType
));
1709 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
1710 /* external typelib */
1711 MSFT_ImpInfo impinfo
;
1712 TLBImpLib
*pImpLib
=(pcx
->pLibInfo
->pImpLibs
);
1714 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
1716 MSFT_Read(&impinfo
, sizeof(impinfo
), pcx
,
1717 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
1718 for(j
=0;pImpLib
;j
++){ /* search the known offsets of all import libraries */
1719 if(pImpLib
->offset
==impinfo
.oImpFile
) break;
1720 pImpLib
=pImpLib
->next
;
1723 (*ppRefType
)->reference
=offset
;
1724 (*ppRefType
)->pImpTLInfo
= pImpLib
;
1725 MSFT_ReadGuid(&(*ppRefType
)->guid
, impinfo
.oGuid
, pcx
);
1726 (*ppRefType
)->index
= TLB_REF_USE_GUID
;
1728 ERR("Cannot find a reference\n");
1729 (*ppRefType
)->reference
=-1;
1730 (*ppRefType
)->pImpTLInfo
=TLB_REF_NOT_FOUND
;
1733 /* in this typelib */
1734 (*ppRefType
)->index
= MSFT_HREFTYPE_INDEX(offset
);
1735 (*ppRefType
)->reference
=offset
;
1736 (*ppRefType
)->pImpTLInfo
=TLB_REF_INTERNAL
;
1740 /* process Implemented Interfaces of a com class */
1741 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
1745 MSFT_RefRecord refrec
;
1746 TLBImplType
**ppImpl
= &pTI
->impltypelist
;
1748 TRACE_(typelib
)("\n");
1750 for(i
=0;i
<count
;i
++){
1751 if(offset
<0) break; /* paranoia */
1752 *ppImpl
=TLB_Alloc(sizeof(**ppImpl
));
1753 MSFT_Read(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
1754 MSFT_DoRefType(pcx
, pTI
, refrec
.reftype
);
1755 (*ppImpl
)->hRef
= refrec
.reftype
;
1756 (*ppImpl
)->implflags
=refrec
.flags
;
1757 (*ppImpl
)->ctCustData
=
1758 MSFT_CustData(pcx
, refrec
.oCustData
, &(*ppImpl
)->pCustData
);
1759 offset
=refrec
.onext
;
1760 ppImpl
=&((*ppImpl
)->next
);
1764 * process a typeinfo record
1766 ITypeInfoImpl
* MSFT_DoTypeInfo(
1769 ITypeLibImpl
* pLibInfo
)
1771 MSFT_TypeInfoBase tiBase
;
1772 ITypeInfoImpl
*ptiRet
;
1774 TRACE_(typelib
)("count=%u\n", count
);
1776 ptiRet
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
1777 MSFT_Read(&tiBase
, sizeof(tiBase
) ,pcx
,
1778 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
1779 /* this is where we are coming from */
1780 ptiRet
->pTypeLib
= pLibInfo
;
1781 ITypeLib2_AddRef((ITypeLib2
*)pLibInfo
);
1782 ptiRet
->index
=count
;
1783 /* fill in the typeattr fields */
1784 FIXME("Assign constructor/destructor memid\n");
1786 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
1787 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
1788 ptiRet
->TypeAttr
.memidConstructor
=MEMBERID_NIL
;/* FIXME */
1789 ptiRet
->TypeAttr
.memidDestructor
=MEMBERID_NIL
; /* FIXME */
1790 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
1791 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
1792 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
1793 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
1794 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
1795 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
1796 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
1797 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
1798 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
1799 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
1800 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
1801 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
1802 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
1803 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
1806 /* IDLDESC idldescType; *//* never saw this one != zero */
1808 /* name, eventually add to a hash table */
1809 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
1810 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
1812 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
1813 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
1814 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
1815 /* note: InfoType's Help file and HelpStringDll come from the containing
1816 * library. Further HelpString and Docstring appear to be the same thing :(
1819 if(ptiRet
->TypeAttr
.cFuncs
>0 )
1820 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1821 ptiRet
->TypeAttr
.cVars
,
1822 tiBase
.memoffset
, & ptiRet
->funclist
);
1824 if(ptiRet
->TypeAttr
.cVars
>0 )
1825 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
1826 ptiRet
->TypeAttr
.cVars
,
1827 tiBase
.memoffset
, & ptiRet
->varlist
);
1828 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
1829 switch(ptiRet
->TypeAttr
.typekind
)
1832 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
1835 case TKIND_DISPATCH
:
1836 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1838 if (tiBase
.datatype1
!= -1)
1840 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1841 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1844 { /* FIXME: This is a really bad hack to add IDispatch */
1845 char* szStdOle
= "stdole2.tlb\0";
1846 int nStdOleLen
= strlen(szStdOle
);
1847 TLBRefType
**ppRef
= &ptiRet
->reflist
;
1850 if((*ppRef
)->reference
== -1)
1852 ppRef
= &(*ppRef
)->next
;
1855 *ppRef
= TLB_Alloc(sizeof(**ppRef
));
1856 (*ppRef
)->guid
= IID_IDispatch
;
1857 (*ppRef
)->reference
= -1;
1858 (*ppRef
)->index
= TLB_REF_USE_GUID
;
1859 (*ppRef
)->pImpTLInfo
= TLB_Alloc(sizeof(TLBImpLib
));
1860 (*ppRef
)->pImpTLInfo
->guid
= IID_StdOle
;
1861 (*ppRef
)->pImpTLInfo
->name
= SysAllocStringLen(NULL
,
1864 MultiByteToWideChar(CP_ACP
,
1868 (*ppRef
)->pImpTLInfo
->name
,
1869 SysStringLen((*ppRef
)->pImpTLInfo
->name
));
1871 (*ppRef
)->pImpTLInfo
->lcid
= 0;
1872 (*ppRef
)->pImpTLInfo
->wVersionMajor
= 2;
1873 (*ppRef
)->pImpTLInfo
->wVersionMinor
= 0;
1878 ptiRet
->impltypelist
=TLB_Alloc(sizeof(TLBImplType
));
1879 MSFT_DoRefType(pcx
, ptiRet
, tiBase
.datatype1
);
1880 ptiRet
->impltypelist
->hRef
= tiBase
.datatype1
;
1885 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->pCustData
);
1887 TRACE_(typelib
)("%s guid: %s kind:%s\n",
1888 debugstr_w(ptiRet
->Name
),
1889 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
1890 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
1895 /****************************************************************************
1898 * find the type of the typelib file and map the typelib resource into
1901 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1902 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1903 int TLB_ReadTypeLib(LPCWSTR pszFileName
, INT index
, ITypeLib2
**ppTypeLib
)
1905 int ret
= TYPE_E_CANTLOADLIBRARY
;
1906 DWORD dwSignature
= 0;
1909 TRACE_(typelib
)("%s:%d\n", debugstr_w(pszFileName
), index
);
1913 /* check the signature of the file */
1914 hFile
= CreateFileW( pszFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0 );
1915 if (INVALID_HANDLE_VALUE
!= hFile
)
1917 HANDLE hMapping
= CreateFileMappingA( hFile
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
1920 LPVOID pBase
= MapViewOfFile(hMapping
, FILE_MAP_READ
, 0, 0, 0);
1923 /* retrieve file size */
1924 DWORD dwTLBLength
= GetFileSize(hFile
, NULL
);
1926 /* first try to load as *.tlb */
1927 dwSignature
= *((DWORD
*) pBase
);
1928 if ( dwSignature
== MSFT_SIGNATURE
)
1930 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
1932 else if ( dwSignature
== SLTG_SIGNATURE
)
1934 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
1936 UnmapViewOfFile(pBase
);
1938 CloseHandle(hMapping
);
1943 if( (WORD
)dwSignature
== IMAGE_DOS_SIGNATURE
)
1945 /* find the typelibrary resource*/
1946 HINSTANCE hinstDLL
= LoadLibraryExW(pszFileName
, 0, DONT_RESOLVE_DLL_REFERENCES
|
1947 LOAD_LIBRARY_AS_DATAFILE
|LOAD_WITH_ALTERED_SEARCH_PATH
);
1950 HRSRC hrsrc
= FindResourceA(hinstDLL
, MAKEINTRESOURCEA(index
),
1954 HGLOBAL hGlobal
= LoadResource(hinstDLL
, hrsrc
);
1957 LPVOID pBase
= LockResource(hGlobal
);
1958 DWORD dwTLBLength
= SizeofResource(hinstDLL
, hrsrc
);
1962 /* try to load as incore resource */
1963 dwSignature
= *((DWORD
*) pBase
);
1964 if ( dwSignature
== MSFT_SIGNATURE
)
1966 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
1968 else if ( dwSignature
== SLTG_SIGNATURE
)
1970 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
1974 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature
);
1977 FreeResource( hGlobal
);
1980 FreeLibrary(hinstDLL
);
1987 ERR("Loading of typelib %s failed with error %ld\n",
1988 debugstr_w(pszFileName
), GetLastError());
1993 /*================== ITypeLib(2) Methods ===================================*/
1995 /****************************************************************************
1996 * ITypeLib2_Constructor_MSFT
1998 * loading an MSFT typelib from an in-memory image
2000 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2004 MSFT_Header tlbHeader
;
2005 MSFT_SegDir tlbSegDir
;
2006 ITypeLibImpl
* pTypeLibImpl
;
2008 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2010 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2011 if (!pTypeLibImpl
) return NULL
;
2013 ICOM_VTBL(pTypeLibImpl
) = &tlbvt
;
2014 pTypeLibImpl
->ref
= 1;
2016 /* get pointer to beginning of typelib data */
2020 cx
.pLibInfo
= pTypeLibImpl
;
2021 cx
.length
= dwTLBLength
;
2024 MSFT_Read((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
2026 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
2027 if (memcmp(&tlbHeader
.magic1
,TLBMAGIC2
,4)) {
2028 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
2031 /* there is a small amount of information here until the next important
2033 * the segment directory . Try to calculate the amount of data */
2034 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
2036 /* now read the segment directory */
2037 TRACE("read segment directory (at %ld)\n",lPSegDir
);
2038 MSFT_Read((void*)&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
2039 cx
.pTblDir
= &tlbSegDir
;
2041 /* just check two entries */
2042 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
2044 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir
);
2045 HeapFree(GetProcessHeap(),0,pTypeLibImpl
);
2049 /* now fill our internal data */
2050 /* TLIBATTR fields */
2051 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
2053 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2054 /* Windows seems to have zero here, is this correct? */
2055 if(SUBLANGID(tlbHeader
.lcid
) == SUBLANG_NEUTRAL
)
2056 pTypeLibImpl
->LibAttr
.lcid
= PRIMARYLANGID(tlbHeader
.lcid
);
2058 pTypeLibImpl
->LibAttr
.lcid
= 0;
2060 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
2061 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
2062 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
2063 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
2065 /* name, eventually add to a hash table */
2066 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
2069 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
2070 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
2072 if( tlbHeader
.varflags
& HELPDLLFLAG
)
2075 MSFT_Read(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
2076 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
2079 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
2082 if(tlbHeader
.CustomDataOffset
>= 0)
2084 pTypeLibImpl
->ctCustData
= MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->pCustData
);
2087 /* fill in typedescriptions */
2088 if(tlbSegDir
.pTypdescTab
.length
> 0)
2090 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
2092 pTypeLibImpl
->pTypeDesc
= TLB_Alloc( cTD
* sizeof(TYPEDESC
));
2093 MSFT_Read(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
2096 /* FIXME: add several sanity checks here */
2097 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
2098 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
2100 /* FIXME: check safearray */
2102 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & stndTypeDesc
[td
[2]];
2104 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= & pTypeLibImpl
->pTypeDesc
[td
[2]/8];
2106 else if(td
[0] == VT_CARRAY
)
2108 /* array descr table here */
2109 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)((int) td
[2]); /* temp store offset in*/
2111 else if(td
[0] == VT_USERDEFINED
)
2113 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
2115 if(++i
<cTD
) MSFT_Read(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
2118 /* second time around to fill the array subscript info */
2121 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
2122 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
2124 MSFT_Read(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (int) pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
2125 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= TLB_Alloc(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
2128 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
2130 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= stndTypeDesc
[td
[0]/8];
2132 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
2134 for(j
= 0; j
<td
[2]; j
++)
2136 MSFT_Read(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
2137 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2138 MSFT_Read(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
2139 sizeof(INT
), &cx
, DO_NOT_SEEK
);
2144 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
2145 ERR("didn't find array description data\n");
2150 /* imported type libs */
2151 if(tlbSegDir
.pImpFiles
.offset
>0)
2153 TLBImpLib
**ppImpLib
= &(pTypeLibImpl
->pImpLibs
);
2154 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
2157 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
2159 *ppImpLib
= TLB_Alloc(sizeof(TLBImpLib
));
2160 (*ppImpLib
)->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
2161 MSFT_Read(&oGuid
, sizeof(INT
), &cx
, offset
);
2163 MSFT_Read(&(*ppImpLib
)->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
2164 MSFT_Read(&(*ppImpLib
)->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2165 MSFT_Read(&(*ppImpLib
)->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
2166 MSFT_Read(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
2169 (*ppImpLib
)->name
= TLB_Alloc(size
+1);
2170 MSFT_Read((*ppImpLib
)->name
, size
, &cx
, DO_NOT_SEEK
);
2171 MSFT_ReadGuid(&(*ppImpLib
)->guid
, oGuid
, &cx
);
2172 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & 0xfffffffc;
2174 ppImpLib
= &(*ppImpLib
)->next
;
2179 if(tlbHeader
.nrtypeinfos
>= 0 )
2181 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2182 ITypeInfoImpl
**ppTI
= &(pTypeLibImpl
->pTypeInfo
);
2185 for(i
= 0; i
<(int)tlbHeader
.nrtypeinfos
; i
++)
2187 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
2189 ITypeInfo_AddRef((ITypeInfo
*) *ppTI
);
2190 ppTI
= &((*ppTI
)->next
);
2191 (pTypeLibImpl
->TypeInfoCount
)++;
2195 TRACE("(%p)\n", pTypeLibImpl
);
2196 return (ITypeLib2
*) pTypeLibImpl
;
2200 static BSTR
TLB_MultiByteToBSTR(char *ptr
)
2206 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
2207 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2208 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, nameW
, len
);
2209 ret
= SysAllocString(nameW
);
2210 HeapFree(GetProcessHeap(), 0, nameW
);
2214 static BOOL
TLB_GUIDFromString(char *str
, GUID
*guid
)
2220 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
2221 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
2225 guid
->Data4
[0] = s
>> 8;
2226 guid
->Data4
[1] = s
& 0xff;
2229 for(i
= 0; i
< 6; i
++) {
2230 memcpy(b
, str
+ 24 + 2 * i
, 2);
2231 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
2236 static WORD
SLTG_ReadString(char *ptr
, BSTR
*pBstr
)
2243 bytelen
= *(WORD
*)ptr
;
2244 if(bytelen
== 0xffff) return 2;
2245 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
2246 nameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2247 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, nameW
, len
);
2248 *pBstr
= SysAllocStringLen(nameW
, len
);
2249 HeapFree(GetProcessHeap(), 0, nameW
);
2253 static WORD
SLTG_ReadStringA(char *ptr
, char **str
)
2258 bytelen
= *(WORD
*)ptr
;
2259 if(bytelen
== 0xffff) return 2;
2260 *str
= HeapAlloc(GetProcessHeap(), 0, bytelen
+ 1);
2261 memcpy(*str
, ptr
+ 2, bytelen
);
2262 (*str
)[bytelen
] = '\0';
2266 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
2268 char *ptr
= pLibBlk
;
2271 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
2272 FIXME("libblk magic = %04x\n", w
);
2277 if((w
= *(WORD
*)ptr
) != 0xffff) {
2278 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
2283 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
2285 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
2287 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
2290 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
2293 pTypeLibImpl
->LibAttr
.lcid
= *(WORD
*)ptr
;
2296 ptr
+= 4; /* skip res12 */
2298 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
2301 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
2304 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
2307 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
2308 ptr
+= sizeof(GUID
);
2310 return ptr
- (char*)pLibBlk
;
2313 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, ELEMDESC
*pElem
)
2316 TYPEDESC
*pTD
= &pElem
->tdesc
;
2318 /* Handle [in/out] first */
2319 if((*pType
& 0xc000) == 0xc000)
2320 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
2321 else if(*pType
& 0x8000)
2322 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
2323 else if(*pType
& 0x4000)
2324 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
2326 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
2329 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
2332 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
2335 if((*pType
& 0xe00) == 0xe00) {
2337 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2339 pTD
= pTD
->u
.lptdesc
;
2341 switch(*pType
& 0x7f) {
2344 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2346 pTD
= pTD
->u
.lptdesc
;
2349 case VT_USERDEFINED
:
2350 pTD
->vt
= VT_USERDEFINED
;
2351 pTD
->u
.hreftype
= *(++pType
) / 4;
2357 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2360 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
2362 pTD
->vt
= VT_CARRAY
;
2363 pTD
->u
.lpadesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2365 (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
2366 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
2367 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
2368 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
2370 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
2376 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2380 pTD
->vt
= VT_SAFEARRAY
;
2381 pTD
->u
.lptdesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2383 pTD
= pTD
->u
.lptdesc
;
2387 pTD
->vt
= *pType
& 0x7f;
2397 static void SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeInfoImpl
*pTI
,
2402 TLBRefType
**ppRefType
;
2404 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
2405 FIXME("Ref magic = %x\n", pRef
->magic
);
2408 name
= ( (char*)(&pRef
->names
) + pRef
->number
);
2410 ppRefType
= &pTI
->reflist
;
2411 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
2413 unsigned int lib_offs
, type_num
;
2415 *ppRefType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2416 sizeof(**ppRefType
));
2418 name
+= SLTG_ReadStringA(name
, &refname
);
2419 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
2420 FIXME("Can't sscanf ref\n");
2421 if(lib_offs
!= 0xffff) {
2422 TLBImpLib
**import
= &pTI
->pTypeLib
->pImpLibs
;
2425 if((*import
)->offset
== lib_offs
)
2427 import
= &(*import
)->next
;
2430 char fname
[MAX_PATH
+1];
2433 *import
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2435 (*import
)->offset
= lib_offs
;
2436 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
2438 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
2439 &(*import
)->wVersionMajor
,
2440 &(*import
)->wVersionMinor
,
2441 &(*import
)->lcid
, fname
) != 4) {
2442 FIXME("can't sscanf ref %s\n",
2443 pNameTable
+ lib_offs
+ 40);
2445 len
= strlen(fname
);
2446 if(fname
[len
-1] != '#')
2447 FIXME("fname = %s\n", fname
);
2448 fname
[len
-1] = '\0';
2449 (*import
)->name
= TLB_MultiByteToBSTR(fname
);
2451 (*ppRefType
)->pImpTLInfo
= *import
;
2452 } else { /* internal ref */
2453 (*ppRefType
)->pImpTLInfo
= TLB_REF_INTERNAL
;
2455 (*ppRefType
)->reference
= ref
;
2456 (*ppRefType
)->index
= type_num
;
2458 HeapFree(GetProcessHeap(), 0, refname
);
2459 ppRefType
= &(*ppRefType
)->next
;
2461 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
2462 FIXME("End of ref block magic = %x\n", *name
);
2463 dump_TLBRefType(pTI
->reflist
);
2466 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
2469 SLTG_ImplInfo
*info
;
2470 TLBImplType
**ppImplType
= &pTI
->impltypelist
;
2471 /* I don't really get this structure, usually it's 0x16 bytes
2472 long, but iuser.tlb contains some that are 0x18 bytes long.
2473 That's ok because we can use the next ptr to jump to the next
2474 one. But how do we know the length of the last one? The WORD
2475 at offs 0x8 might be the clue. For now I'm just assuming that
2476 the last one is the regular 0x16 bytes. */
2478 info
= (SLTG_ImplInfo
*)pBlk
;
2480 *ppImplType
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2481 sizeof(**ppImplType
));
2482 (*ppImplType
)->hRef
= info
->ref
;
2483 (*ppImplType
)->implflags
= info
->impltypeflags
;
2484 pTI
->TypeAttr
.cImplTypes
++;
2485 ppImplType
= &(*ppImplType
)->next
;
2487 if(info
->next
== 0xffff)
2490 FIXME("Interface inheriting more than one interface\n");
2491 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
2493 info
++; /* see comment at top of function */
2497 static SLTG_TypeInfoTail
*SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
2500 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2501 SLTG_MemberHeader
*pMemHeader
;
2502 char *pFirstItem
, *pNextItem
;
2504 if(pTIHeader
->href_table
!= 0xffffffff) {
2505 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2510 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2512 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2514 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2515 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, FALSE
);
2518 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2522 static SLTG_TypeInfoTail
*SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
2525 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2526 SLTG_MemberHeader
*pMemHeader
;
2527 SLTG_Function
*pFunc
;
2528 char *pFirstItem
, *pNextItem
;
2529 TLBFuncDesc
**ppFuncDesc
= &pTI
->funclist
;
2532 if(pTIHeader
->href_table
!= 0xffffffff) {
2533 SLTG_DoRefs((SLTG_RefInfo
*)(pBlk
+ pTIHeader
->href_table
), pTI
,
2537 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2539 pFirstItem
= pNextItem
= (char*)(pMemHeader
+ 1);
2541 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
2542 pNextItem
= SLTG_DoImpls(pFirstItem
, pTI
, TRUE
);
2545 for(pFunc
= (SLTG_Function
*)pNextItem
, num
= 1; 1;
2546 pFunc
= (SLTG_Function
*)(pFirstItem
+ pFunc
->next
), num
++) {
2551 if(pFunc
->magic
!= SLTG_FUNCTION_MAGIC
&&
2552 pFunc
->magic
!= SLTG_FUNCTION_WITH_FLAGS_MAGIC
) {
2553 FIXME("func magic = %02x\n", pFunc
->magic
);
2556 *ppFuncDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2557 sizeof(**ppFuncDesc
));
2558 (*ppFuncDesc
)->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
2560 (*ppFuncDesc
)->funcdesc
.memid
= pFunc
->dispid
;
2561 (*ppFuncDesc
)->funcdesc
.invkind
= pFunc
->inv
>> 4;
2562 (*ppFuncDesc
)->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
2563 (*ppFuncDesc
)->funcdesc
.cParams
= pFunc
->nacc
>> 3;
2564 (*ppFuncDesc
)->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
2565 (*ppFuncDesc
)->funcdesc
.oVft
= pFunc
->vtblpos
;
2567 if(pFunc
->magic
== SLTG_FUNCTION_WITH_FLAGS_MAGIC
)
2568 (*ppFuncDesc
)->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
2570 if(pFunc
->retnextopt
& 0x80)
2571 pType
= &pFunc
->rettype
;
2573 pType
= (WORD
*)(pFirstItem
+ pFunc
->rettype
);
2576 SLTG_DoType(pType
, pFirstItem
, &(*ppFuncDesc
)->funcdesc
.elemdescFunc
);
2578 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
=
2579 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2580 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(ELEMDESC
));
2581 (*ppFuncDesc
)->pParamDesc
=
2582 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2583 (*ppFuncDesc
)->funcdesc
.cParams
* sizeof(TLBParDesc
));
2585 pArg
= (WORD
*)(pFirstItem
+ pFunc
->arg_off
);
2587 for(param
= 0; param
< (*ppFuncDesc
)->funcdesc
.cParams
; param
++) {
2588 char *paramName
= pNameTable
+ *pArg
;
2590 /* If arg type follows then paramName points to the 2nd
2591 letter of the name, else the next WORD is an offset to
2592 the arg type and paramName points to the first letter.
2593 So let's take one char off paramName and see if we're
2594 pointing at an alpha-numeric char. However if *pArg is
2595 0xffff or 0xfffe then the param has no name, the former
2596 meaning that the next WORD is the type, the latter
2597 meaning the the next WORD is an offset to the type. */
2602 else if(*pArg
== 0xfffe) {
2606 else if(!isalnum(*(paramName
-1)))
2611 if(HaveOffs
) { /* the next word is an offset to type */
2612 pType
= (WORD
*)(pFirstItem
+ *pArg
);
2613 SLTG_DoType(pType
, pFirstItem
,
2614 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2619 pArg
= SLTG_DoType(pArg
, pFirstItem
,
2620 &(*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
]);
2623 /* Are we an optional param ? */
2624 if((*ppFuncDesc
)->funcdesc
.cParams
- param
<=
2625 (*ppFuncDesc
)->funcdesc
.cParamsOpt
)
2626 (*ppFuncDesc
)->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
2629 (*ppFuncDesc
)->pParamDesc
[param
].Name
=
2630 TLB_MultiByteToBSTR(paramName
);
2634 ppFuncDesc
= &((*ppFuncDesc
)->next
);
2635 if(pFunc
->next
== 0xffff) break;
2637 pTI
->TypeAttr
.cFuncs
= num
;
2638 dump_TLBFuncDesc(pTI
->funclist
);
2639 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2642 static SLTG_TypeInfoTail
*SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
2645 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2646 SLTG_MemberHeader
*pMemHeader
;
2647 SLTG_RecordItem
*pItem
;
2649 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2654 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2656 pFirstItem
= (char*)(pMemHeader
+ 1);
2657 for(pItem
= (SLTG_RecordItem
*)pFirstItem
, num
= 1; 1;
2658 pItem
= (SLTG_RecordItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2659 if(pItem
->magic
!= SLTG_RECORD_MAGIC
) {
2660 FIXME("record magic = %02x\n", pItem
->magic
);
2663 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2664 sizeof(**ppVarDesc
));
2665 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2666 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2667 (*ppVarDesc
)->vardesc
.u
.oInst
= pItem
->byte_offs
;
2668 (*ppVarDesc
)->vardesc
.varkind
= VAR_PERINSTANCE
;
2670 if(pItem
->typepos
== 0x02)
2671 pType
= &pItem
->type
;
2672 else if(pItem
->typepos
== 0x00)
2673 pType
= (WORD
*)(pFirstItem
+ pItem
->type
);
2675 FIXME("typepos = %02x\n", pItem
->typepos
);
2679 SLTG_DoType(pType
, pFirstItem
,
2680 &(*ppVarDesc
)->vardesc
.elemdescVar
);
2682 /* FIXME("helpcontext, helpstring\n"); */
2684 dump_TypeDesc(&(*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
, buf
);
2686 ppVarDesc
= &((*ppVarDesc
)->next
);
2687 if(pItem
->next
== 0xffff) break;
2689 pTI
->TypeAttr
.cVars
= num
;
2690 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2693 static SLTG_TypeInfoTail
*SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
2696 SLTG_TypeInfoHeader
*pTIHeader
= (SLTG_TypeInfoHeader
*)pBlk
;
2697 SLTG_MemberHeader
*pMemHeader
;
2698 SLTG_EnumItem
*pItem
;
2700 TLBVarDesc
**ppVarDesc
= &pTI
->varlist
;
2703 pMemHeader
= (SLTG_MemberHeader
*)(pBlk
+ pTIHeader
->elem_table
);
2705 pFirstItem
= (char*)(pMemHeader
+ 1);
2706 for(pItem
= (SLTG_EnumItem
*)pFirstItem
, num
= 1; 1;
2707 pItem
= (SLTG_EnumItem
*)(pFirstItem
+ pItem
->next
), num
++) {
2708 if(pItem
->magic
!= SLTG_ENUMITEM_MAGIC
) {
2709 FIXME("enumitem magic = %04x\n", pItem
->magic
);
2712 *ppVarDesc
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2713 sizeof(**ppVarDesc
));
2714 (*ppVarDesc
)->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
2715 (*ppVarDesc
)->vardesc
.memid
= pItem
->memid
;
2716 (*ppVarDesc
)->vardesc
.u
.lpvarValue
= HeapAlloc(GetProcessHeap(), 0,
2718 V_VT((*ppVarDesc
)->vardesc
.u
.lpvarValue
) = VT_INT
;
2719 V_UNION((*ppVarDesc
)->vardesc
.u
.lpvarValue
, intVal
) =
2720 *(INT
*)(pItem
->value
+ pFirstItem
);
2721 (*ppVarDesc
)->vardesc
.elemdescVar
.tdesc
.vt
= VT_I4
;
2722 (*ppVarDesc
)->vardesc
.varkind
= VAR_CONST
;
2723 /* FIXME("helpcontext, helpstring\n"); */
2725 ppVarDesc
= &((*ppVarDesc
)->next
);
2726 if(pItem
->next
== 0xffff) break;
2728 pTI
->TypeAttr
.cVars
= num
;
2729 return (SLTG_TypeInfoTail
*)(pFirstItem
+ pMemHeader
->cbExtra
);
2732 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2733 managable copy of it into this */
2746 } SLTG_InternalOtherTypeInfo
;
2748 /****************************************************************************
2749 * ITypeLib2_Constructor_SLTG
2751 * loading a SLTG typelib from an in-memory image
2753 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
2755 ITypeLibImpl
*pTypeLibImpl
;
2756 SLTG_Header
*pHeader
;
2757 SLTG_BlkEntry
*pBlkEntry
;
2761 LPVOID pBlk
, pFirstBlk
;
2762 SLTG_LibBlk
*pLibBlk
;
2763 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
2764 char *pAfterOTIBlks
= NULL
;
2765 char *pNameTable
, *ptr
;
2768 ITypeInfoImpl
**ppTypeInfoImpl
;
2770 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
2772 pTypeLibImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeLibImpl
));
2773 if (!pTypeLibImpl
) return NULL
;
2775 ICOM_VTBL(pTypeLibImpl
) = &tlbvt
;
2776 pTypeLibImpl
->ref
= 1;
2781 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader
->SLTG_magic
,
2782 pHeader
->nrOfFileBlks
);
2783 if (memcmp(&pHeader
->SLTG_magic
, TLBMAGIC1
, 4)) {
2784 FIXME("Header type magic 0x%08lx not supported.\n",
2785 pHeader
->SLTG_magic
);
2789 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2790 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
2792 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2793 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
2795 /* Next we have a magic block */
2796 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
2798 /* Let's see if we're still in sync */
2799 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
2800 sizeof(SLTG_COMPOBJ_MAGIC
))) {
2801 FIXME("CompObj magic = %s\n", pMagic
->CompObj_magic
);
2804 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
2805 sizeof(SLTG_DIR_MAGIC
))) {
2806 FIXME("dir magic = %s\n", pMagic
->dir_magic
);
2810 pIndex
= (SLTG_Index
*)(pMagic
+1);
2812 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
2814 pFirstBlk
= (LPVOID
)(pPad9
+ 1);
2816 /* We'll set up a ptr to the main library block, which is the last one. */
2818 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
2819 pBlkEntry
[order
].next
!= 0;
2820 order
= pBlkEntry
[order
].next
- 1, i
++) {
2821 pBlk
+= pBlkEntry
[order
].len
;
2825 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
2827 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2832 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2834 pOtherTypeInfoBlks
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
2835 sizeof(*pOtherTypeInfoBlks
) *
2836 pTypeLibImpl
->TypeInfoCount
);
2839 ptr
= (char*)pLibBlk
+ len
;
2841 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
2845 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
2847 w
= *(WORD
*)(ptr
+ 2);
2850 pOtherTypeInfoBlks
[i
].index_name
= HeapAlloc(GetProcessHeap(),0,
2852 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
2853 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
2855 w
= *(WORD
*)(ptr
+ 4 + len
);
2857 TRACE("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
2859 pOtherTypeInfoBlks
[i
].other_name
= HeapAlloc(GetProcessHeap(),0,
2861 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
2862 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
2864 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
2865 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
2866 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
2868 pOtherTypeInfoBlks
[i
].extra
= HeapAlloc(GetProcessHeap(),0,
2870 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
2873 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
2874 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
2875 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
2876 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
2877 len
+= sizeof(SLTG_OtherTypeInfo
);
2881 pAfterOTIBlks
= ptr
;
2883 /* Skip this WORD and get the next DWORD */
2884 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
2886 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2887 magic dust and we should be pointing at the beginning of the name
2890 pNameTable
= (char*)pLibBlk
+ len
+ 0x216;
2894 TRACE("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
2896 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
2899 /* Hopefully we now have enough ptrs set up to actually read in
2900 some TypeInfos. It's not clear which order to do them in, so
2901 I'll just follow the links along the BlkEntry chain and read
2902 them in in the order in which they're in the file */
2904 ppTypeInfoImpl
= &(pTypeLibImpl
->pTypeInfo
);
2906 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
2907 pBlkEntry
[order
].next
!= 0;
2908 order
= pBlkEntry
[order
].next
- 1, i
++) {
2910 SLTG_TypeInfoHeader
*pTIHeader
;
2911 SLTG_TypeInfoTail
*pTITail
;
2913 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
2914 pOtherTypeInfoBlks
[i
].index_name
)) {
2915 FIXME("Index strings don't match\n");
2920 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
2921 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
2924 *ppTypeInfoImpl
= (ITypeInfoImpl
*)ITypeInfo_Constructor();
2925 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
2926 ITypeLib2_AddRef((ITypeLib2
*)pTypeLibImpl
);
2927 (*ppTypeInfoImpl
)->index
= i
;
2928 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
2929 pOtherTypeInfoBlks
[i
].name_offs
+
2931 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
2932 memcpy(&((*ppTypeInfoImpl
)->TypeAttr
.guid
), &pOtherTypeInfoBlks
[i
].uuid
,
2934 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
2935 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
2936 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
2937 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
2938 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
2940 if((pTIHeader
->typeflags1
& 7) != 2)
2941 FIXME("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
2942 if(pTIHeader
->typeflags3
!= 2)
2943 FIXME("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
2945 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2946 debugstr_w((*ppTypeInfoImpl
)->Name
),
2947 typekind_desc
[pTIHeader
->typekind
],
2948 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
2949 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
2951 switch(pTIHeader
->typekind
) {
2953 pTITail
= SLTG_ProcessEnum(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2957 pTITail
= SLTG_ProcessRecord(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2960 case TKIND_INTERFACE
:
2961 pTITail
= SLTG_ProcessInterface(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2965 pTITail
= SLTG_ProcessCoClass(pBlk
, *ppTypeInfoImpl
, pNameTable
);
2969 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
2975 if(pTITail
) { /* could get cFuncs, cVars and cImplTypes from here
2976 but we've already set those */
2977 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
2978 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
2979 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
2981 ppTypeInfoImpl
= &((*ppTypeInfoImpl
)->next
);
2982 pBlk
+= pBlkEntry
[order
].len
;
2985 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
2986 FIXME("Somehow processed %d TypeInfos\n", i
);
2990 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks
);
2991 return (ITypeLib2
*)pTypeLibImpl
;
2994 /* ITypeLib::QueryInterface
2996 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
3001 ICOM_THIS( ITypeLibImpl
, iface
);
3003 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3006 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3007 IsEqualIID(riid
,&IID_ITypeLib
)||
3008 IsEqualIID(riid
,&IID_ITypeLib2
))
3015 ITypeLib2_AddRef(iface
);
3016 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3019 TRACE("-- Interface: E_NOINTERFACE\n");
3020 return E_NOINTERFACE
;
3025 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
3027 ICOM_THIS( ITypeLibImpl
, iface
);
3029 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3031 return ++(This
->ref
);
3034 /* ITypeLib::Release
3036 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
3038 ICOM_THIS( ITypeLibImpl
, iface
);
3042 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3046 /* FIXME destroy child objects */
3048 TRACE(" destroying ITypeLib(%p)\n",This
);
3052 SysFreeString(This
->Name
);
3056 if (This
->DocString
)
3058 SysFreeString(This
->DocString
);
3059 This
->DocString
= NULL
;
3064 SysFreeString(This
->HelpFile
);
3065 This
->HelpFile
= NULL
;
3068 if (This
->HelpStringDll
)
3070 SysFreeString(This
->HelpStringDll
);
3071 This
->HelpStringDll
= NULL
;
3074 ITypeInfo_Release((ITypeInfo
*) This
->pTypeInfo
);
3075 HeapFree(GetProcessHeap(),0,This
);
3082 /* ITypeLib::GetTypeInfoCount
3084 * Returns the number of type descriptions in the type library
3086 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
3088 ICOM_THIS( ITypeLibImpl
, iface
);
3089 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
3090 return This
->TypeInfoCount
;
3093 /* ITypeLib::GetTypeInfo
3095 * retrieves the specified type description in the library.
3097 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
3100 ITypeInfo
**ppTInfo
)
3104 ICOM_THIS( ITypeLibImpl
, iface
);
3105 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
;
3107 TRACE("(%p)->(index=%d) \n", This
, index
);
3109 if (!ppTInfo
) return E_INVALIDARG
;
3111 /* search element n in list */
3112 for(i
=0; i
< index
; i
++)
3114 pTypeInfo
= pTypeInfo
->next
;
3117 TRACE("-- element not found\n");
3118 return TYPE_E_ELEMENTNOTFOUND
;
3122 *ppTInfo
= (ITypeInfo
*) pTypeInfo
;
3124 ITypeInfo_AddRef(*ppTInfo
);
3125 TRACE("-- found (%p)\n",*ppTInfo
);
3130 /* ITypeLibs::GetTypeInfoType
3132 * Retrieves the type of a type description.
3134 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
3139 ICOM_THIS( ITypeLibImpl
, iface
);
3141 ITypeInfoImpl
*pTInfo
= This
->pTypeInfo
;
3143 TRACE("(%p) index %d \n",This
, index
);
3145 if(!pTKind
) return E_INVALIDARG
;
3147 /* search element n in list */
3148 for(i
=0; i
< index
; i
++)
3152 TRACE("-- element not found\n");
3153 return TYPE_E_ELEMENTNOTFOUND
;
3155 pTInfo
= pTInfo
->next
;
3158 *pTKind
= pTInfo
->TypeAttr
.typekind
;
3159 TRACE("-- found Type (%d)\n", *pTKind
);
3163 /* ITypeLib::GetTypeInfoOfGuid
3165 * Retrieves the type description that corresponds to the specified GUID.
3168 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
3171 ITypeInfo
**ppTInfo
)
3173 ICOM_THIS( ITypeLibImpl
, iface
);
3174 ITypeInfoImpl
*pTypeInfo
= This
->pTypeInfo
; /* head of list */
3176 TRACE("(%p)\n\tguid:\t%s)\n",This
,debugstr_guid(guid
));
3178 if (!pTypeInfo
) return TYPE_E_ELEMENTNOTFOUND
;
3180 /* search linked list for guid */
3181 while( !IsEqualIID(guid
,&pTypeInfo
->TypeAttr
.guid
) )
3183 pTypeInfo
= pTypeInfo
->next
;
3187 /* end of list reached */
3188 TRACE("-- element not found\n");
3189 return TYPE_E_ELEMENTNOTFOUND
;
3193 TRACE("-- found (%p, %s)\n",
3195 debugstr_w(pTypeInfo
->Name
));
3197 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
3198 ITypeInfo_AddRef(*ppTInfo
);
3202 /* ITypeLib::GetLibAttr
3204 * Retrieves the structure that contains the library's attributes.
3207 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
3209 LPTLIBATTR
*ppTLibAttr
)
3211 ICOM_THIS( ITypeLibImpl
, iface
);
3212 TRACE("(%p)\n",This
);
3213 *ppTLibAttr
= HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr
));
3214 memcpy(*ppTLibAttr
, &This
->LibAttr
, sizeof(**ppTLibAttr
));
3218 /* ITypeLib::GetTypeComp
3220 * Enables a client compiler to bind to a library's types, variables,
3221 * constants, and global functions.
3224 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
3226 ITypeComp
**ppTComp
)
3228 ICOM_THIS( ITypeLibImpl
, iface
);
3229 FIXME("(%p): stub!\n",This
);
3233 /* ITypeLib::GetDocumentation
3235 * Retrieves the library's documentation string, the complete Help file name
3236 * and path, and the context identifier for the library Help topic in the Help
3239 * On a successful return all non-null BSTR pointers will have been set,
3242 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
3246 BSTR
*pBstrDocString
,
3247 DWORD
*pdwHelpContext
,
3248 BSTR
*pBstrHelpFile
)
3250 ICOM_THIS( ITypeLibImpl
, iface
);
3252 HRESULT result
= E_INVALIDARG
;
3257 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3259 pBstrName
, pBstrDocString
,
3260 pdwHelpContext
, pBstrHelpFile
);
3264 /* documentation for the typelib */
3268 if(!(*pBstrName
= SysAllocString(This
->Name
))) goto memerr1
;else;
3274 if (This
->DocString
)
3275 if(!(*pBstrDocString
= SysAllocString(This
->DocString
))) goto memerr2
;else;
3276 else if (This
->Name
)
3277 if(!(*pBstrDocString
= SysAllocString(This
->Name
))) goto memerr2
;else;
3279 *pBstrDocString
= NULL
;
3283 *pdwHelpContext
= This
->dwHelpContext
;
3288 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
))) goto memerr3
;else;
3290 *pBstrHelpFile
= NULL
;
3297 /* for a typeinfo */
3298 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
3300 if(SUCCEEDED(result
))
3302 result
= ITypeInfo_GetDocumentation(pTInfo
,
3306 pdwHelpContext
, pBstrHelpFile
);
3308 ITypeInfo_Release(pTInfo
);
3313 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
3315 if (pBstrName
) SysFreeString (*pBstrName
);
3317 return STG_E_INSUFFICIENTMEMORY
;
3322 * Indicates whether a passed-in string contains the name of a type or member
3323 * described in the library.
3326 static HRESULT WINAPI
ITypeLib2_fnIsName(
3332 ICOM_THIS( ITypeLibImpl
, iface
);
3333 ITypeInfoImpl
*pTInfo
;
3334 TLBFuncDesc
*pFInfo
;
3337 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3339 TRACE("(%p)->(%s,%08lx,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
3343 for(pTInfo
=This
->pTypeInfo
;pTInfo
;pTInfo
=pTInfo
->next
){
3344 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3345 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3346 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3347 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3348 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
, nNameBufLen
))
3349 goto ITypeLib2_fnIsName_exit
;
3351 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3352 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
3357 ITypeLib2_fnIsName_exit
:
3358 TRACE("(%p)slow! search for %s: %s found!\n", This
,
3359 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
3364 /* ITypeLib::FindName
3366 * Finds occurrences of a type description in a type library. This may be used
3367 * to quickly verify that a name exists in a type library.
3370 static HRESULT WINAPI
ITypeLib2_fnFindName(
3374 ITypeInfo
**ppTInfo
,
3378 ICOM_THIS( ITypeLibImpl
, iface
);
3379 ITypeInfoImpl
*pTInfo
;
3380 TLBFuncDesc
*pFInfo
;
3384 UINT nNameBufLen
= SysStringLen(szNameBuf
);
3386 for(pTInfo
=This
->pTypeInfo
;pTInfo
&& j
<*pcFound
; pTInfo
=pTInfo
->next
){
3387 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3388 for(pFInfo
=pTInfo
->funclist
;pFInfo
;pFInfo
=pFInfo
->next
) {
3389 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3390 for(i
=0;i
<pFInfo
->funcdesc
.cParams
;i
++)
3391 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[i
].Name
,nNameBufLen
))
3392 goto ITypeLib2_fnFindName_exit
;
3394 for(pVInfo
=pTInfo
->varlist
;pVInfo
;pVInfo
=pVInfo
->next
)
3395 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
3397 ITypeLib2_fnFindName_exit
:
3398 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
3399 ppTInfo
[j
]=(LPTYPEINFO
)pTInfo
;
3402 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3403 This
, *pcFound
, debugstr_w(szNameBuf
), j
);
3410 /* ITypeLib::ReleaseTLibAttr
3412 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3415 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
3417 TLIBATTR
*pTLibAttr
)
3419 ICOM_THIS( ITypeLibImpl
, iface
);
3420 TRACE("freeing (%p)\n",This
);
3421 HeapFree(GetProcessHeap(),0,pTLibAttr
);
3425 /* ITypeLib2::GetCustData
3427 * gets the custom data
3429 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
3434 ICOM_THIS( ITypeLibImpl
, iface
);
3435 TLBCustData
*pCData
;
3437 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
3439 if( IsEqualIID(guid
, &pCData
->guid
)) break;
3442 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
3446 VariantInit( pVarVal
);
3447 VariantCopy( pVarVal
, &pCData
->data
);
3450 return E_INVALIDARG
; /* FIXME: correct? */
3453 /* ITypeLib2::GetLibStatistics
3455 * Returns statistics about a type library that are required for efficient
3456 * sizing of hash tables.
3459 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
3461 ULONG
*pcUniqueNames
,
3462 ULONG
*pcchUniqueNames
)
3464 ICOM_THIS( ITypeLibImpl
, iface
);
3466 FIXME("(%p): stub!\n", This
);
3468 if(pcUniqueNames
) *pcUniqueNames
=1;
3469 if(pcchUniqueNames
) *pcchUniqueNames
=1;
3473 /* ITypeLib2::GetDocumentation2
3475 * Retrieves the library's documentation string, the complete Help file name
3476 * and path, the localization context to use, and the context ID for the
3477 * library Help topic in the Help file.
3480 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
3484 BSTR
*pbstrHelpString
,
3485 DWORD
*pdwHelpStringContext
,
3486 BSTR
*pbstrHelpStringDll
)
3488 ICOM_THIS( ITypeLibImpl
, iface
);
3492 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This
, index
, lcid
);
3494 /* the help string should be obtained from the helpstringdll,
3495 * using the _DLLGetDocumentation function, based on the supplied
3496 * lcid. Nice to do sometime...
3500 /* documentation for the typelib */
3502 *pbstrHelpString
=SysAllocString(This
->DocString
);
3503 if(pdwHelpStringContext
)
3504 *pdwHelpStringContext
=This
->dwHelpContext
;
3505 if(pbstrHelpStringDll
)
3506 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
3512 /* for a typeinfo */
3513 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
3515 if(SUCCEEDED(result
))
3517 ITypeInfo2
* pTInfo2
;
3518 result
= ITypeInfo_QueryInterface(pTInfo
,
3520 (LPVOID
*) &pTInfo2
);
3522 if(SUCCEEDED(result
))
3524 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
3528 pdwHelpStringContext
,
3529 pbstrHelpStringDll
);
3531 ITypeInfo2_Release(pTInfo2
);
3534 ITypeInfo_Release(pTInfo
);
3540 /* ITypeLib2::GetAllCustData
3542 * Gets all custom data items for the library.
3545 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
3547 CUSTDATA
*pCustData
)
3549 ICOM_THIS( ITypeLibImpl
, iface
);
3550 TLBCustData
*pCData
;
3552 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
3553 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
3554 if(pCustData
->prgCustData
){
3555 pCustData
->cCustData
=This
->ctCustData
;
3556 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
3557 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
3558 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
3561 ERR(" OUT OF MEMORY! \n");
3562 return E_OUTOFMEMORY
;
3567 static ICOM_VTABLE(ITypeLib2
) tlbvt
= {
3568 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3569 ITypeLib2_fnQueryInterface
,
3571 ITypeLib2_fnRelease
,
3572 ITypeLib2_fnGetTypeInfoCount
,
3573 ITypeLib2_fnGetTypeInfo
,
3574 ITypeLib2_fnGetTypeInfoType
,
3575 ITypeLib2_fnGetTypeInfoOfGuid
,
3576 ITypeLib2_fnGetLibAttr
,
3577 ITypeLib2_fnGetTypeComp
,
3578 ITypeLib2_fnGetDocumentation
,
3580 ITypeLib2_fnFindName
,
3581 ITypeLib2_fnReleaseTLibAttr
,
3583 ITypeLib2_fnGetCustData
,
3584 ITypeLib2_fnGetLibStatistics
,
3585 ITypeLib2_fnGetDocumentation2
,
3586 ITypeLib2_fnGetAllCustData
3589 /*================== ITypeInfo(2) Methods ===================================*/
3590 static ITypeInfo2
* WINAPI
ITypeInfo_Constructor(void)
3592 ITypeInfoImpl
* pTypeInfoImpl
;
3594 pTypeInfoImpl
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ITypeInfoImpl
));
3597 ICOM_VTBL(pTypeInfoImpl
) = &tinfvt
;
3598 pTypeInfoImpl
->ref
=1;
3600 TRACE("(%p)\n", pTypeInfoImpl
);
3601 return (ITypeInfo2
*) pTypeInfoImpl
;
3604 /* ITypeInfo::QueryInterface
3606 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
3611 ICOM_THIS( ITypeLibImpl
, iface
);
3613 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
3616 if(IsEqualIID(riid
, &IID_IUnknown
) ||
3617 IsEqualIID(riid
,&IID_ITypeInfo
)||
3618 IsEqualIID(riid
,&IID_ITypeInfo2
))
3622 ITypeInfo_AddRef(iface
);
3623 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
3626 TRACE("-- Interface: E_NOINTERFACE\n");
3627 return E_NOINTERFACE
;
3630 /* ITypeInfo::AddRef
3632 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
3634 ICOM_THIS( ITypeInfoImpl
, iface
);
3638 TRACE("(%p)->ref is %u\n",This
, This
->ref
);
3642 /* ITypeInfo::Release
3644 static ULONG WINAPI
ITypeInfo_fnRelease( ITypeInfo2
*iface
)
3646 ICOM_THIS( ITypeInfoImpl
, iface
);
3650 TRACE("(%p)->(%u)\n",This
, This
->ref
);
3654 FIXME("destroy child objects\n");
3656 TRACE("destroying ITypeInfo(%p)\n",This
);
3659 SysFreeString(This
->Name
);
3663 if (This
->DocString
)
3665 SysFreeString(This
->DocString
);
3666 This
->DocString
= 0;
3671 ITypeInfo_Release((ITypeInfo
*)This
->next
);
3674 HeapFree(GetProcessHeap(),0,This
);
3680 /* ITypeInfo::GetTypeAttr
3682 * Retrieves a TYPEATTR structure that contains the attributes of the type
3686 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
3687 LPTYPEATTR
*ppTypeAttr
)
3689 ICOM_THIS( ITypeInfoImpl
, iface
);
3690 TRACE("(%p)\n",This
);
3691 /* FIXME: must do a copy here */
3692 *ppTypeAttr
=&This
->TypeAttr
;
3696 /* ITypeInfo::GetTypeComp
3698 * Retrieves the ITypeComp interface for the type description, which enables a
3699 * client compiler to bind to the type description's members.
3702 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
3703 ITypeComp
* *ppTComp
)
3705 ICOM_THIS( ITypeInfoImpl
, iface
);
3706 FIXME("(%p) stub!\n", This
);
3710 /* ITypeInfo::GetFuncDesc
3712 * Retrieves the FUNCDESC structure that contains information about a
3713 * specified function.
3716 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
3717 LPFUNCDESC
*ppFuncDesc
)
3719 ICOM_THIS( ITypeInfoImpl
, iface
);
3721 TLBFuncDesc
* pFDesc
;
3722 TRACE("(%p) index %d\n", This
, index
);
3723 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++, pFDesc
=pFDesc
->next
)
3726 /* FIXME: must do a copy here */
3727 *ppFuncDesc
=&pFDesc
->funcdesc
;
3730 return E_INVALIDARG
;
3733 /* ITypeInfo::GetVarDesc
3735 * Retrieves a VARDESC structure that describes the specified variable.
3738 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
3739 LPVARDESC
*ppVarDesc
)
3741 ICOM_THIS( ITypeInfoImpl
, iface
);
3743 TLBVarDesc
* pVDesc
;
3744 TRACE("(%p) index %d\n", This
, index
);
3745 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
)
3748 /* FIXME: must do a copy here */
3749 *ppVarDesc
=&pVDesc
->vardesc
;
3752 return E_INVALIDARG
;
3755 /* ITypeInfo_GetNames
3757 * Retrieves the variable with the specified member ID (or the name of the
3758 * property or method and its parameters) that correspond to the specified
3761 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
3762 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
3764 ICOM_THIS( ITypeInfoImpl
, iface
);
3765 TLBFuncDesc
* pFDesc
;
3766 TLBVarDesc
* pVDesc
;
3768 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This
, memid
, cMaxNames
);
3769 for(pFDesc
=This
->funclist
; pFDesc
&& pFDesc
->funcdesc
.memid
!= memid
; pFDesc
=pFDesc
->next
);
3772 /* function found, now return function and parameter names */
3773 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
3776 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
3778 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
3784 for(pVDesc
=This
->varlist
; pVDesc
&& pVDesc
->vardesc
.memid
!= memid
; pVDesc
=pVDesc
->next
);
3787 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
3792 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
)
3794 /* recursive search */
3797 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
,
3799 if(SUCCEEDED(result
))
3801 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
3802 ITypeInfo_Release(pTInfo
);
3805 WARN("Could not search inherited interface!\n");
3809 WARN("no names found\n");
3812 return TYPE_E_ELEMENTNOTFOUND
;
3819 /* ITypeInfo::GetRefTypeOfImplType
3821 * If a type description describes a COM class, it retrieves the type
3822 * description of the implemented interface types. For an interface,
3823 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3827 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
3832 ICOM_THIS( ITypeInfoImpl
, iface
);
3834 TLBImplType
*pImpl
= This
->impltypelist
;
3836 TRACE("(%p) index %d\n", This
, index
);
3837 dump_TypeInfo(This
);
3841 /* only valid on dual interfaces;
3842 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3844 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
3846 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDISPATCHABLE
&&
3847 This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
3853 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
3854 *pRefType
= pImpl
->hRef
;
3859 /* get element n from linked list */
3860 for(i
=0; pImpl
&& i
<index
; i
++)
3862 pImpl
= pImpl
->next
;
3865 if (!pImpl
) return TYPE_E_ELEMENTNOTFOUND
;
3867 *pRefType
= pImpl
->hRef
;
3869 TRACE("-- 0x%08lx\n", pImpl
->hRef
);
3876 /* ITypeInfo::GetImplTypeFlags
3878 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3879 * or base interface in a type description.
3881 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
3882 UINT index
, INT
*pImplTypeFlags
)
3884 ICOM_THIS( ITypeInfoImpl
, iface
);
3888 TRACE("(%p) index %d\n", This
, index
);
3889 for(i
=0, pImpl
=This
->impltypelist
; i
<index
&& pImpl
;
3890 i
++, pImpl
=pImpl
->next
)
3892 if(i
==index
&& pImpl
){
3893 *pImplTypeFlags
=pImpl
->implflags
;
3897 return TYPE_E_ELEMENTNOTFOUND
;
3901 * Maps between member names and member IDs, and parameter names and
3904 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
3905 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
3907 ICOM_THIS( ITypeInfoImpl
, iface
);
3908 TLBFuncDesc
* pFDesc
;
3909 TLBVarDesc
* pVDesc
;
3912 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
3914 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
) {
3916 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
3917 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
3918 for(i
=1; i
< cNames
; i
++){
3919 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
3920 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
3922 if( j
<pFDesc
->funcdesc
.cParams
)
3925 ret
=DISP_E_UNKNOWNNAME
;
3930 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
3931 if(!lstrcmpiW(*rgszNames
, pVDesc
->Name
)) {
3932 if(cNames
) *pMemId
=pVDesc
->vardesc
.memid
;
3936 /* not found, see if this is and interface with an inheritance */
3937 if(This
->TypeAttr
.typekind
==TKIND_INTERFACE
&&
3938 This
->TypeAttr
.cImplTypes
){
3939 /* recursive search */
3941 ret
=ITypeInfo_GetRefTypeInfo(iface
,
3942 This
->impltypelist
->hRef
, &pTInfo
);
3944 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
3945 ITypeInfo_Release(pTInfo
);
3948 WARN("Could not search inherited interface!\n");
3950 WARN("no names found\n");
3951 return DISP_E_UNKNOWNNAME
;
3954 /* ITypeInfo::Invoke
3956 * Invokes a method, or accesses a property of an object, that implements the
3957 * interface described by the type description.
3960 _invoke(LPVOID func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
3963 if (TRACE_ON(ole
)) {
3965 MESSAGE("Calling %p(",func
);
3966 for (i
=0;i
<nrargs
;i
++) MESSAGE("%08lx,",args
[i
]);
3975 DWORD (WINAPI
*xfunc
)() = func
;
3980 DWORD (WINAPI
*xfunc
)(DWORD
) = func
;
3981 res
= xfunc(args
[0]);
3985 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
) = func
;
3986 res
= xfunc(args
[0],args
[1]);
3990 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
) = func
;
3991 res
= xfunc(args
[0],args
[1],args
[2]);
3995 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
) = func
;
3996 res
= xfunc(args
[0],args
[1],args
[2],args
[3]);
4000 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4001 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4]);
4005 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4006 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5]);
4010 DWORD (WINAPI
*xfunc
)(DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
,DWORD
) = func
;
4011 res
= xfunc(args
[0],args
[1],args
[2],args
[3],args
[4],args
[5],args
[6]);
4015 FIXME("unsupported number of arguments %d in stdcall\n",nrargs
);
4021 FIXME("unsupported calling convention %d\n",callconv
);
4025 TRACE("returns %08lx\n",res
);
4029 static HRESULT WINAPI
ITypeInfo_fnInvoke(
4034 DISPPARAMS
*pDispParams
,
4035 VARIANT
*pVarResult
,
4036 EXCEPINFO
*pExcepInfo
,
4039 ICOM_THIS( ITypeInfoImpl
, iface
);
4040 TLBFuncDesc
* pFDesc
;
4041 TLBVarDesc
* pVDesc
;
4044 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4045 This
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
4047 dump_DispParms(pDispParams
);
4049 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4050 if (pFDesc
->funcdesc
.memid
== memid
) {
4051 if (pFDesc
->funcdesc
.invkind
& dwFlags
)
4055 dump_TLBFuncDescOne(pFDesc
);
4056 switch (pFDesc
->funcdesc
.funckind
) {
4057 case FUNC_PUREVIRTUAL
:
4058 case FUNC_VIRTUAL
: {
4060 DWORD
*args
= (DWORD
*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD
)*(pFDesc
->funcdesc
.cParams
+1));
4061 DWORD
*args2
= (DWORD
*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(DWORD
)*(pFDesc
->funcdesc
.cParams
));
4062 args
[0] = (DWORD
)pIUnk
;
4064 for (i
=0;i
<pFDesc
->funcdesc
.cParams
;i
++) {
4065 if (i
<pDispParams
->cArgs
) {
4066 TRACE("set %d to disparg type %d vs %d\n",i
,
4067 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1]),
4068 pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
4070 args
[i
+1] = V_UNION(&pDispParams
->rgvarg
[pDispParams
->cArgs
-i
-1],lVal
);
4072 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
].tdesc
);
4073 TRACE("set %d to pointer for get (type is %d)\n",i
,tdesc
->vt
);
4074 /*FIXME: give pointers for the rest, so propertyget works*/
4075 args
[i
+1] = (DWORD
)&args2
[i
];
4077 /* If pointer to variant, pass reference to variant
4078 * in result variant array.
4080 if ((tdesc
->vt
== VT_PTR
) &&
4081 (tdesc
->u
.lptdesc
->vt
== VT_VARIANT
) &&
4084 args
[i
+1] = (DWORD
)(pVarResult
+(i
-pDispParams
->cArgs
));
4087 if (pFDesc
->funcdesc
.cParamsOpt
)
4088 FIXME("Does not support optional parameters (%d)\n",
4089 pFDesc
->funcdesc
.cParamsOpt
4092 res
= _invoke((*(DWORD
***)pIUnk
)[pFDesc
->funcdesc
.oVft
/4],
4093 pFDesc
->funcdesc
.callconv
,
4094 pFDesc
->funcdesc
.cParams
+1,
4097 if (pVarResult
&& (dwFlags
& (DISPATCH_PROPERTYGET
))) {
4098 for (i
=0;i
<pFDesc
->funcdesc
.cParams
-pDispParams
->cArgs
;i
++) {
4099 TYPEDESC
*tdesc
= &(pFDesc
->funcdesc
.lprgelemdescParam
[i
+pDispParams
->cArgs
].tdesc
);
4100 /* If we are a pointer to a variant, we are done already */
4101 if ((tdesc
->vt
==VT_PTR
)&&(tdesc
->u
.lptdesc
->vt
==VT_VARIANT
))
4104 VariantInit(&pVarResult
[i
]);
4105 V_UNION(pVarResult
+i
,intVal
) = args2
[i
+pDispParams
->cArgs
];
4107 if (tdesc
->vt
== VT_PTR
)
4108 tdesc
= tdesc
->u
.lptdesc
;
4109 V_VT(pVarResult
+i
) = tdesc
->vt
;
4111 /* HACK: VB5 likes this.
4112 * I do not know why. There is 1 example in MSDN which uses
4113 * this which appears broken (mixes int vals and
4116 if ((tdesc
->vt
== VT_PTR
) && (dwFlags
& DISPATCH_METHOD
))
4117 V_VT(pVarResult
+i
) = VT_DISPATCH
;
4118 TRACE("storing into variant: [%d]\n", i
);
4119 dump_Variant(pVarResult
+i
);
4122 HeapFree(GetProcessHeap(),0,args2
);
4123 HeapFree(GetProcessHeap(),0,args
);
4126 case FUNC_DISPATCH
: {
4130 hr
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
4132 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4135 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4136 hr
= IDispatch_Invoke(
4137 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,dwFlags
,pDispParams
,
4138 pVarResult
,pExcepInfo
,pArgErr
4141 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr
);
4142 IDispatch_Release(disp
);
4146 FIXME("Unknown function invocation type %d\n",pFDesc
->funcdesc
.funckind
);
4150 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
) {
4151 if (pVDesc
->vardesc
.memid
== memid
) {
4152 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR
)pVDesc
->Name
)));
4153 dump_TLBVarDesc(pVDesc
);
4158 /* not found, look for it in inherited interfaces */
4159 if (This
->TypeAttr
.typekind
==TKIND_INTERFACE
&& This
->TypeAttr
.cImplTypes
) {
4160 /* recursive search */
4163 hr
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypelist
->hRef
, &pTInfo
);
4165 hr
=ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,dwFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
4166 ITypeInfo_Release(pTInfo
);
4169 WARN("Could not search inherited interface!\n");
4171 ERR("did not find member id %d, flags %d!\n", (int)memid
, dwFlags
);
4172 return DISP_E_MEMBERNOTFOUND
;
4175 /* ITypeInfo::GetDocumentation
4177 * Retrieves the documentation string, the complete Help file name and path,
4178 * and the context ID for the Help topic for a specified type description.
4180 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
4181 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
4182 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
4184 ICOM_THIS( ITypeInfoImpl
, iface
);
4185 TLBFuncDesc
* pFDesc
;
4186 TLBVarDesc
* pVDesc
;
4187 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4188 " HelpContext(%p) HelpFile(%p)\n",
4189 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
4190 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4192 *pBstrName
=SysAllocString(This
->Name
);
4194 *pBstrDocString
=SysAllocString(This
->DocString
);
4196 *pdwHelpContext
=This
->dwHelpContext
;
4198 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
4200 }else {/* for a member */
4201 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4202 if(pFDesc
->funcdesc
.memid
==memid
){
4204 *pBstrName
= SysAllocString(pFDesc
->Name
);
4206 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
4208 *pdwHelpContext
=pFDesc
->helpcontext
;
4211 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4212 if(pVDesc
->vardesc
.memid
==memid
){
4213 FIXME("Not implemented\n");
4217 return TYPE_E_ELEMENTNOTFOUND
;
4220 /* ITypeInfo::GetDllEntry
4222 * Retrieves a description or specification of an entry point for a function
4225 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
4226 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
4229 ICOM_THIS( ITypeInfoImpl
, iface
);
4230 FIXME("(%p) stub!\n", This
);
4234 /* ITypeInfo::GetRefTypeInfo
4236 * If a type description references other type descriptions, it retrieves
4237 * the referenced type descriptions.
4239 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
4242 ITypeInfo
**ppTInfo
)
4244 ICOM_THIS( ITypeInfoImpl
, iface
);
4245 HRESULT result
= E_FAIL
;
4248 if (hRefType
== -1 &&
4249 (((ITypeInfoImpl
*) This
)->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
4250 (((ITypeInfoImpl
*) This
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
4252 /* when we meet a DUAL dispinterface, we must create the interface
4255 ITypeInfoImpl
* pTypeInfoImpl
= (ITypeInfoImpl
*) ITypeInfo_Constructor();
4258 /* the interface version contains the same information as the dispinterface
4259 * copy the contents of the structs.
4261 *pTypeInfoImpl
= *This
;
4262 pTypeInfoImpl
->ref
= 1;
4264 /* change the type to interface */
4265 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
4267 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
4269 ITypeInfo_AddRef((ITypeInfo
*) pTypeInfoImpl
);
4274 TLBRefType
*pRefType
;
4275 for(pRefType
= This
->reflist
; pRefType
; pRefType
= pRefType
->next
) {
4276 if(pRefType
->reference
== hRefType
)
4280 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
4281 if(pRefType
&& hRefType
!= -1) {
4282 ITypeLib
*pTLib
= NULL
;
4284 if(pRefType
->pImpTLInfo
== TLB_REF_INTERNAL
) {
4286 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
4288 if(pRefType
->pImpTLInfo
->pImpTypeLib
) {
4289 TRACE("typeinfo in imported typelib that is already loaded\n");
4290 pTLib
= (ITypeLib
*)pRefType
->pImpTLInfo
->pImpTypeLib
;
4291 ITypeLib2_AddRef((ITypeLib
*) pTLib
);
4294 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4295 result
= LoadRegTypeLib( &pRefType
->pImpTLInfo
->guid
,
4296 pRefType
->pImpTLInfo
->wVersionMajor
,
4297 pRefType
->pImpTLInfo
->wVersionMinor
,
4298 pRefType
->pImpTLInfo
->lcid
,
4301 if(!SUCCEEDED(result
)) {
4302 BSTR libnam
=SysAllocString(pRefType
->pImpTLInfo
->name
);
4303 result
=LoadTypeLib(libnam
, &pTLib
);
4304 SysFreeString(libnam
);
4306 if(SUCCEEDED(result
)) {
4307 pRefType
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
4308 ITypeLib2_AddRef(pTLib
);
4312 if(SUCCEEDED(result
)) {
4313 if(pRefType
->index
== TLB_REF_USE_GUID
)
4314 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
4318 result
= ITypeLib2_GetTypeInfo(pTLib
, pRefType
->index
,
4322 ITypeLib2_Release(pTLib
);
4326 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This
, hRefType
,
4327 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
4331 /* ITypeInfo::AddressOfMember
4333 * Retrieves the addresses of static functions or variables, such as those
4336 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
4337 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
4339 ICOM_THIS( ITypeInfoImpl
, iface
);
4340 FIXME("(%p) stub!\n", This
);
4344 /* ITypeInfo::CreateInstance
4346 * Creates a new instance of a type that describes a component object class
4349 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
4350 IUnknown
*pUnk
, REFIID riid
, VOID
**ppvObj
)
4352 ICOM_THIS( ITypeInfoImpl
, iface
);
4353 FIXME("(%p) stub!\n", This
);
4357 /* ITypeInfo::GetMops
4359 * Retrieves marshaling information.
4361 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
4364 ICOM_THIS( ITypeInfoImpl
, iface
);
4365 FIXME("(%p) stub!\n", This
);
4369 /* ITypeInfo::GetContainingTypeLib
4371 * Retrieves the containing type library and the index of the type description
4372 * within that type library.
4374 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
4375 ITypeLib
* *ppTLib
, UINT
*pIndex
)
4377 ICOM_THIS( ITypeInfoImpl
, iface
);
4379 return E_INVALIDARG
;
4380 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
4381 *pIndex
=This
->index
;
4382 ITypeLib2_AddRef(*ppTLib
);
4383 TRACE("(%p) returns (%p) index %d!\n", This
, *ppTLib
, *pIndex
);
4387 /* ITypeInfo::ReleaseTypeAttr
4389 * Releases a TYPEATTR previously returned by GetTypeAttr.
4392 static HRESULT WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
4393 TYPEATTR
* pTypeAttr
)
4395 ICOM_THIS( ITypeInfoImpl
, iface
);
4396 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
4400 /* ITypeInfo::ReleaseFuncDesc
4402 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4404 static HRESULT WINAPI
ITypeInfo_fnReleaseFuncDesc(
4406 FUNCDESC
*pFuncDesc
)
4408 ICOM_THIS( ITypeInfoImpl
, iface
);
4409 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
4413 /* ITypeInfo::ReleaseVarDesc
4415 * Releases a VARDESC previously returned by GetVarDesc.
4417 static HRESULT WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
4420 ICOM_THIS( ITypeInfoImpl
, iface
);
4421 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
4425 /* ITypeInfo2::GetTypeKind
4427 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4430 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
4431 TYPEKIND
*pTypeKind
)
4433 ICOM_THIS( ITypeInfoImpl
, iface
);
4434 *pTypeKind
=This
->TypeAttr
.typekind
;
4435 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
4439 /* ITypeInfo2::GetTypeFlags
4441 * Returns the type flags without any allocations. This returns a DWORD type
4442 * flag, which expands the type flags without growing the TYPEATTR (type
4446 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
* iface
,
4449 ICOM_THIS( ITypeInfoImpl
, iface
);
4450 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
4451 TRACE("(%p) flags 0x%04x\n", This
,*pTypeFlags
);
4455 /* ITypeInfo2::GetFuncIndexOfMemId
4456 * Binds to a specific member based on a known DISPID, where the member name
4457 * is not known (for example, when binding to a default member).
4460 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
4461 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
4463 ICOM_THIS( ITypeInfoImpl
, iface
);
4464 TLBFuncDesc
*pFuncInfo
;
4467 /* FIXME: should check for invKind??? */
4468 for(i
=0, pFuncInfo
=This
->funclist
;pFuncInfo
&&
4469 memid
!= pFuncInfo
->funcdesc
.memid
; i
++, pFuncInfo
=pFuncInfo
->next
);
4475 result
=E_INVALIDARG
;
4477 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This
,
4478 memid
, invKind
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4482 /* TypeInfo2::GetVarIndexOfMemId
4484 * Binds to a specific member based on a known DISPID, where the member name
4485 * is not known (for example, when binding to a default member).
4488 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
4489 MEMBERID memid
, UINT
*pVarIndex
)
4491 ICOM_THIS( ITypeInfoImpl
, iface
);
4492 TLBVarDesc
*pVarInfo
;
4495 for(i
=0, pVarInfo
=This
->varlist
; pVarInfo
&&
4496 memid
!= pVarInfo
->vardesc
.memid
; i
++, pVarInfo
=pVarInfo
->next
)
4503 result
=E_INVALIDARG
;
4505 TRACE("(%p) memid 0x%08lx -> %s\n", This
,
4506 memid
, SUCCEEDED(result
)? "SUCCES":"FAILED");
4510 /* ITypeInfo2::GetCustData
4512 * Gets the custom data
4514 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
4519 ICOM_THIS( ITypeInfoImpl
, iface
);
4520 TLBCustData
*pCData
;
4522 for(pCData
=This
->pCustData
; pCData
; pCData
= pCData
->next
)
4523 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4525 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4529 VariantInit( pVarVal
);
4530 VariantCopy( pVarVal
, &pCData
->data
);
4533 return E_INVALIDARG
; /* FIXME: correct? */
4536 /* ITypeInfo2::GetFuncCustData
4538 * Gets the custom data
4540 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
4546 ICOM_THIS( ITypeInfoImpl
, iface
);
4547 TLBCustData
*pCData
=NULL
;
4548 TLBFuncDesc
* pFDesc
;
4550 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4551 pFDesc
=pFDesc
->next
);
4554 for(pCData
=pFDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4555 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4557 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4560 VariantInit( pVarVal
);
4561 VariantCopy( pVarVal
, &pCData
->data
);
4564 return E_INVALIDARG
; /* FIXME: correct? */
4567 /* ITypeInfo2::GetParamCustData
4569 * Gets the custom data
4571 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
4578 ICOM_THIS( ITypeInfoImpl
, iface
);
4579 TLBCustData
*pCData
=NULL
;
4580 TLBFuncDesc
* pFDesc
;
4583 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,pFDesc
=pFDesc
->next
);
4585 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
)
4586 for(pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
; pCData
;
4587 pCData
= pCData
->next
)
4588 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4590 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4594 VariantInit( pVarVal
);
4595 VariantCopy( pVarVal
, &pCData
->data
);
4598 return E_INVALIDARG
; /* FIXME: correct? */
4601 /* ITypeInfo2::GetVarCustData
4603 * Gets the custom data
4605 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
4611 ICOM_THIS( ITypeInfoImpl
, iface
);
4612 TLBCustData
*pCData
=NULL
;
4613 TLBVarDesc
* pVDesc
;
4616 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++, pVDesc
=pVDesc
->next
);
4620 for(pCData
=pVDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4622 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4626 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4630 VariantInit( pVarVal
);
4631 VariantCopy( pVarVal
, &pCData
->data
);
4634 return E_INVALIDARG
; /* FIXME: correct? */
4637 /* ITypeInfo2::GetImplCustData
4639 * Gets the custom data
4641 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
4647 ICOM_THIS( ITypeInfoImpl
, iface
);
4648 TLBCustData
*pCData
=NULL
;
4649 TLBImplType
* pRDesc
;
4652 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++, pRDesc
=pRDesc
->next
);
4656 for(pCData
=pRDesc
->pCustData
; pCData
; pCData
= pCData
->next
)
4658 if( IsEqualIID(guid
, &pCData
->guid
)) break;
4662 TRACE("(%p) guid %s %s found!x)\n", This
, debugstr_guid(guid
), pCData
? "" : "NOT");
4666 VariantInit( pVarVal
);
4667 VariantCopy( pVarVal
, &pCData
->data
);
4670 return E_INVALIDARG
; /* FIXME: correct? */
4673 /* ITypeInfo2::GetDocumentation2
4675 * Retrieves the documentation string, the complete Help file name and path,
4676 * the localization context to use, and the context ID for the library Help
4677 * topic in the Help file.
4680 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
4684 BSTR
*pbstrHelpString
,
4685 DWORD
*pdwHelpStringContext
,
4686 BSTR
*pbstrHelpStringDll
)
4688 ICOM_THIS( ITypeInfoImpl
, iface
);
4689 TLBFuncDesc
* pFDesc
;
4690 TLBVarDesc
* pVDesc
;
4691 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4692 "HelpStringContext(%p) HelpStringDll(%p)\n",
4693 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
4694 pbstrHelpStringDll
);
4695 /* the help string should be obtained from the helpstringdll,
4696 * using the _DLLGetDocumentation function, based on the supplied
4697 * lcid. Nice to do sometime...
4699 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
4701 *pbstrHelpString
=SysAllocString(This
->Name
);
4702 if(pdwHelpStringContext
)
4703 *pdwHelpStringContext
=This
->dwHelpStringContext
;
4704 if(pbstrHelpStringDll
)
4705 *pbstrHelpStringDll
=
4706 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4708 }else {/* for a member */
4709 for(pFDesc
=This
->funclist
; pFDesc
; pFDesc
=pFDesc
->next
)
4710 if(pFDesc
->funcdesc
.memid
==memid
){
4712 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
4713 if(pdwHelpStringContext
)
4714 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
4715 if(pbstrHelpStringDll
)
4716 *pbstrHelpStringDll
=
4717 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4720 for(pVDesc
=This
->varlist
; pVDesc
; pVDesc
=pVDesc
->next
)
4721 if(pVDesc
->vardesc
.memid
==memid
){
4723 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
4724 if(pdwHelpStringContext
)
4725 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
4726 if(pbstrHelpStringDll
)
4727 *pbstrHelpStringDll
=
4728 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
4732 return TYPE_E_ELEMENTNOTFOUND
;
4735 /* ITypeInfo2::GetAllCustData
4737 * Gets all custom data items for the Type info.
4740 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
4742 CUSTDATA
*pCustData
)
4744 ICOM_THIS( ITypeInfoImpl
, iface
);
4745 TLBCustData
*pCData
;
4748 TRACE("(%p) returning %d items\n", This
, This
->ctCustData
);
4750 pCustData
->prgCustData
= TLB_Alloc(This
->ctCustData
* sizeof(CUSTDATAITEM
));
4751 if(pCustData
->prgCustData
){
4752 pCustData
->cCustData
=This
->ctCustData
;
4753 for(i
=0, pCData
=This
->pCustData
; pCData
; i
++, pCData
= pCData
->next
){
4754 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4755 VariantCopy(& pCustData
->prgCustData
[i
].varValue
, & pCData
->data
);
4758 ERR(" OUT OF MEMORY! \n");
4759 return E_OUTOFMEMORY
;
4764 /* ITypeInfo2::GetAllFuncCustData
4766 * Gets all custom data items for the specified Function
4769 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
4772 CUSTDATA
*pCustData
)
4774 ICOM_THIS( ITypeInfoImpl
, iface
);
4775 TLBCustData
*pCData
;
4776 TLBFuncDesc
* pFDesc
;
4778 TRACE("(%p) index %d\n", This
, index
);
4779 for(i
=0, pFDesc
=This
->funclist
; i
!=index
&& pFDesc
; i
++,
4780 pFDesc
=pFDesc
->next
)
4783 pCustData
->prgCustData
=
4784 TLB_Alloc(pFDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4785 if(pCustData
->prgCustData
){
4786 pCustData
->cCustData
=pFDesc
->ctCustData
;
4787 for(i
=0, pCData
=pFDesc
->pCustData
; pCData
; i
++,
4788 pCData
= pCData
->next
){
4789 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4790 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4794 ERR(" OUT OF MEMORY! \n");
4795 return E_OUTOFMEMORY
;
4799 return TYPE_E_ELEMENTNOTFOUND
;
4802 /* ITypeInfo2::GetAllParamCustData
4804 * Gets all custom data items for the Functions
4807 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
4808 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
4810 ICOM_THIS( ITypeInfoImpl
, iface
);
4811 TLBCustData
*pCData
=NULL
;
4812 TLBFuncDesc
* pFDesc
;
4814 TRACE("(%p) index %d\n", This
, indexFunc
);
4815 for(i
=0, pFDesc
=This
->funclist
; i
!=indexFunc
&& pFDesc
; i
++,
4816 pFDesc
=pFDesc
->next
)
4818 if(pFDesc
&& indexParam
>=0 && indexParam
<pFDesc
->funcdesc
.cParams
){
4819 pCustData
->prgCustData
=
4820 TLB_Alloc(pFDesc
->pParamDesc
[indexParam
].ctCustData
*
4821 sizeof(CUSTDATAITEM
));
4822 if(pCustData
->prgCustData
){
4823 pCustData
->cCustData
=pFDesc
->pParamDesc
[indexParam
].ctCustData
;
4824 for(i
=0, pCData
=pFDesc
->pParamDesc
[indexParam
].pCustData
;
4825 pCData
; i
++, pCData
= pCData
->next
){
4826 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4827 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4831 ERR(" OUT OF MEMORY! \n");
4832 return E_OUTOFMEMORY
;
4836 return TYPE_E_ELEMENTNOTFOUND
;
4839 /* ITypeInfo2::GetAllVarCustData
4841 * Gets all custom data items for the specified Variable
4844 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
4845 UINT index
, CUSTDATA
*pCustData
)
4847 ICOM_THIS( ITypeInfoImpl
, iface
);
4848 TLBCustData
*pCData
;
4849 TLBVarDesc
* pVDesc
;
4851 TRACE("(%p) index %d\n", This
, index
);
4852 for(i
=0, pVDesc
=This
->varlist
; i
!=index
&& pVDesc
; i
++,
4853 pVDesc
=pVDesc
->next
)
4856 pCustData
->prgCustData
=
4857 TLB_Alloc(pVDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4858 if(pCustData
->prgCustData
){
4859 pCustData
->cCustData
=pVDesc
->ctCustData
;
4860 for(i
=0, pCData
=pVDesc
->pCustData
; pCData
; i
++,
4861 pCData
= pCData
->next
){
4862 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4863 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4867 ERR(" OUT OF MEMORY! \n");
4868 return E_OUTOFMEMORY
;
4872 return TYPE_E_ELEMENTNOTFOUND
;
4875 /* ITypeInfo2::GetAllImplCustData
4877 * Gets all custom data items for the specified implementation type
4880 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
4883 CUSTDATA
*pCustData
)
4885 ICOM_THIS( ITypeInfoImpl
, iface
);
4886 TLBCustData
*pCData
;
4887 TLBImplType
* pRDesc
;
4889 TRACE("(%p) index %d\n", This
, index
);
4890 for(i
=0, pRDesc
=This
->impltypelist
; i
!=index
&& pRDesc
; i
++,
4891 pRDesc
=pRDesc
->next
)
4894 pCustData
->prgCustData
=
4895 TLB_Alloc(pRDesc
->ctCustData
* sizeof(CUSTDATAITEM
));
4896 if(pCustData
->prgCustData
){
4897 pCustData
->cCustData
=pRDesc
->ctCustData
;
4898 for(i
=0, pCData
=pRDesc
->pCustData
; pCData
; i
++,
4899 pCData
= pCData
->next
){
4900 pCustData
->prgCustData
[i
].guid
=pCData
->guid
;
4901 VariantCopy(& pCustData
->prgCustData
[i
].varValue
,
4905 ERR(" OUT OF MEMORY! \n");
4906 return E_OUTOFMEMORY
;
4910 return TYPE_E_ELEMENTNOTFOUND
;
4913 static ICOM_VTABLE(ITypeInfo2
) tinfvt
=
4915 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4917 ITypeInfo_fnQueryInterface
,
4919 ITypeInfo_fnRelease
,
4921 ITypeInfo_fnGetTypeAttr
,
4922 ITypeInfo_fnGetTypeComp
,
4923 ITypeInfo_fnGetFuncDesc
,
4924 ITypeInfo_fnGetVarDesc
,
4925 ITypeInfo_fnGetNames
,
4926 ITypeInfo_fnGetRefTypeOfImplType
,
4927 ITypeInfo_fnGetImplTypeFlags
,
4928 ITypeInfo_fnGetIDsOfNames
,
4930 ITypeInfo_fnGetDocumentation
,
4931 ITypeInfo_fnGetDllEntry
,
4932 ITypeInfo_fnGetRefTypeInfo
,
4933 ITypeInfo_fnAddressOfMember
,
4934 ITypeInfo_fnCreateInstance
,
4935 ITypeInfo_fnGetMops
,
4936 ITypeInfo_fnGetContainingTypeLib
,
4937 ITypeInfo_fnReleaseTypeAttr
,
4938 ITypeInfo_fnReleaseFuncDesc
,
4939 ITypeInfo_fnReleaseVarDesc
,
4941 ITypeInfo2_fnGetTypeKind
,
4942 ITypeInfo2_fnGetTypeFlags
,
4943 ITypeInfo2_fnGetFuncIndexOfMemId
,
4944 ITypeInfo2_fnGetVarIndexOfMemId
,
4945 ITypeInfo2_fnGetCustData
,
4946 ITypeInfo2_fnGetFuncCustData
,
4947 ITypeInfo2_fnGetParamCustData
,
4948 ITypeInfo2_fnGetVarCustData
,
4949 ITypeInfo2_fnGetImplTypeCustData
,
4950 ITypeInfo2_fnGetDocumentation2
,
4951 ITypeInfo2_fnGetAllCustData
,
4952 ITypeInfo2_fnGetAllFuncCustData
,
4953 ITypeInfo2_fnGetAllParamCustData
,
4954 ITypeInfo2_fnGetAllVarCustData
,
4955 ITypeInfo2_fnGetAllImplTypeCustData
,