4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
64 #include "winnls.h" /* for PRIMARYLANGID */
65 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
68 #include "wine/unicode.h"
69 #include "wine/obj_base.h"
73 #include "wine/debug.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 /****************************************************************************
80 * QueryPathOfRegTypeLib [TYPELIB.14]
82 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
87 QueryPathOfRegTypeLib16(
88 REFGUID guid, /* [in] referenced guid */
89 WORD wMaj, /* [in] major version */
90 WORD wMin, /* [in] minor version */
91 LCID lcid, /* [in] locale id */
92 LPBSTR16 path /* [out] path of typelib */
95 char typelibkey[100],pathname[260];
101 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
102 guid->Data1, guid->Data2, guid->Data3,
103 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
104 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
107 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
108 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
111 plen = sizeof(pathname);
112 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
113 /* try again without lang specific id */
115 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
116 FIXME("key %s not found\n",typelibkey);
119 *path = SysAllocString16(pathname);
123 /****************************************************************************
124 * QueryPathOfRegTypeLib [OLEAUT32.164]
129 QueryPathOfRegTypeLib(
130 REFGUID guid, /* [in] referenced guid */
131 WORD wMaj, /* [in] major version */
132 WORD wMin, /* [in] minor version */
133 LCID lcid, /* [in] locale id */
134 LPBSTR path ) /* [out] path of typelib */
136 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
137 string termination character on output strings */
144 char szTypeLibKey[100];
145 char szPath[MAX_PATH];
146 DWORD dwPathLen = sizeof(szPath);
154 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
160 sprintf(szTypeLibKey,
161 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
162 guid->Data1, guid->Data2, guid->Data3,
163 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
164 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
169 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
173 else if (myLCID == lcid)
175 /* try with sub-langid */
176 myLCID = SUBLANGID(lcid);
178 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
180 /* try with system langid */
190 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
191 BSTR bstrPath = SysAllocStringLen(NULL,len);
193 MultiByteToWideChar(CP_ACP,
205 TRACE_(typelib)("%s not found\n", szTypeLibKey);
210 /******************************************************************************
211 * CreateTypeLib [OLEAUT32.160] creates a typelib
217 HRESULT WINAPI CreateTypeLib(
218 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
220 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
223 /******************************************************************************
224 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
226 * Docs: OLECHAR FAR* szFile
227 * Docs: iTypeLib FAR* FAR* pptLib
233 HRESULT WINAPI LoadTypeLib16(
234 LPOLESTR szFile, /* [in] Name of file to load from */
235 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
237 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
245 /******************************************************************************
246 * LoadTypeLib [OLEAUT32.161]
247 * Loads and registers a type library
249 * Docs: OLECHAR FAR* szFile
250 * Docs: iTypeLib FAR* FAR* pptLib
256 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
258 HRESULT WINAPI LoadTypeLib(
259 const OLECHAR *szFile,/* [in] Name of file to load from */
260 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
263 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
266 /******************************************************************************
267 * LoadTypeLibEx [OLEAUT32.183]
268 * Loads and optionally registers a type library
274 HRESULT WINAPI LoadTypeLibEx(
275 LPCOLESTR szFile, /* [in] Name of file to load from */
276 REGKIND regkind, /* [in] Specify kind of registration */
277 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
279 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
283 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
285 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
288 /* Look for a trailing '\\' followed by an index */
289 pIndexStr = strrchrW(szFile, '\\');
290 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
291 index = atoiW(pIndexStr);
292 memcpy(szFileCopy, szFile,
293 (pIndexStr - szFile - 1) * sizeof(WCHAR));
294 szFileCopy[pIndexStr - szFile - 1] = '\0';
295 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
297 return TYPE_E_CANTLOADLIBRARY;
298 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
299 return TYPE_E_CANTLOADLIBRARY;
301 return TYPE_E_CANTLOADLIBRARY;
304 TRACE("File %s index %d\n", debugstr_w(szPath), index);
306 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
311 case REGKIND_DEFAULT:
312 /* FIXME: is this correct? */
313 if (!szFile || !szFile[0] ||
314 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
316 /* else fall-through */
317 case REGKIND_REGISTER:
318 /* FIXME: Help path? */
319 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
321 IUnknown_Release(*pptLib);
329 TRACE(" returns %08lx\n",res);
333 /******************************************************************************
334 * LoadRegTypeLib [OLEAUT32.162]
336 HRESULT WINAPI LoadRegTypeLib(
337 REFGUID rguid, /* [in] referenced guid */
338 WORD wVerMajor, /* [in] major version */
339 WORD wVerMinor, /* [in] minor version */
340 LCID lcid, /* [in] locale id */
341 ITypeLib **ppTLib) /* [out] path of typelib */
344 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
348 res= LoadTypeLib(bstr, ppTLib);
352 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
358 /******************************************************************************
359 * RegisterTypeLib [OLEAUT32.163]
360 * Adds information about a type library to the System Registry
362 * Docs: ITypeLib FAR * ptlib
363 * Docs: OLECHAR FAR* szFullPath
364 * Docs: OLECHAR FAR* szHelpDir
370 HRESULT WINAPI RegisterTypeLib(
371 ITypeLib * ptlib, /* [in] Pointer to the library*/
372 OLECHAR * szFullPath, /* [in] full Path of the library*/
373 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
384 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
386 if (ptlib == NULL || szFullPath == NULL)
389 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
392 StringFromGUID2(&attr->guid, guid, 80);
393 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
394 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
395 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
396 HeapFree(GetProcessHeap(), 0, guidA);
399 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
400 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
404 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
406 if (RegSetValueExW(key, NULL, 0, REG_SZ,
407 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
415 /* FIXME: This *seems* to be 0 always, not sure though */
416 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
417 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
419 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
420 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
428 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
429 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
432 /* FIXME: is %u correct? */
433 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
434 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
435 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
443 /* register OLE Automation-compatible interfaces for this typelib */
444 types = ITypeLib_GetTypeInfoCount(ptlib);
445 for (tidx=0; tidx<types; tidx++) {
446 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
447 LPOLESTR name = NULL;
448 ITypeInfo *tinfo = NULL;
450 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
452 case TKIND_INTERFACE:
453 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
454 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
457 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
458 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
461 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
462 /* coclasses should probably not be registered? */
465 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
469 TYPEATTR *tattr = NULL;
470 ITypeInfo_GetTypeAttr(tinfo, &tattr);
472 TRACE_(typelib)("guid=%s, flags=%04x (",
473 debugstr_guid(&tattr->guid),
475 if (TRACE_ON(typelib)) {
476 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
496 * FIXME: The 1 is just here until we implement rpcrt4
497 * stub/proxy handling. Until then it helps IShield
500 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
502 /* register interface<->typelib coupling */
503 StringFromGUID2(&tattr->guid, guid, 80);
504 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
505 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
506 HeapFree(GetProcessHeap(), 0, guidA);
508 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
509 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
511 RegSetValueExW(key, NULL, 0, REG_SZ,
512 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
514 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
515 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
516 RegSetValueExA(subKey, NULL, 0, REG_SZ,
520 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
521 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
522 RegSetValueExA(subKey, NULL, 0, REG_SZ,
527 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
528 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
530 StringFromGUID2(&attr->guid, guid, 80);
531 snprintf(ver, sizeof(ver), "%x.%x",
532 attr->wMajorVerNum, attr->wMinorVerNum);
533 RegSetValueExW(subKey, NULL, 0, REG_SZ,
534 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
535 RegSetValueExA(subKey, "Version", 0, REG_SZ,
542 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
544 ITypeInfo_Release(tinfo);
551 ITypeLib_ReleaseTLibAttr(ptlib, attr);
557 /******************************************************************************
558 * UnRegisterTypeLib [OLEAUT32.186]
559 * Removes information about a type library from the System Registry
566 HRESULT WINAPI UnRegisterTypeLib(
567 REFGUID libid, /* [in] Guid of the library */
568 WORD wVerMajor, /* [in] major version */
569 WORD wVerMinor, /* [in] minor version */
570 LCID lcid, /* [in] locale id */
573 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
574 return S_OK; /* FIXME: pretend everything is OK */
577 /****************************************************************************
578 * OaBuildVersion (TYPELIB.15)
580 * known TYPELIB.DLL versions:
582 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
583 * OLE 2.02 1993-94 02 3002
586 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
587 * OLE 2.1 NT 1993-95 ?? ???
588 * OLE 2.3.1 W95 23 700
589 * OLE2 4.0 NT4SP6 1993-98 40 4277
591 DWORD WINAPI OaBuildVersion16(void)
593 /* FIXME: I'd like to return the highest currently known version value
594 * in case the user didn't force a --winver, but I don't know how
595 * to retrieve the "versionForced" info from misc/version.c :(
596 * (this would be useful in other places, too) */
597 FIXME("If you get version error messages, please report them\n");
598 switch(GetVersion() & 0x8000ffff) /* mask off build number */
600 case 0x80000a03: /* WIN31 */
601 return MAKELONG(3027, 3); /* WfW 3.11 */
602 case 0x80000004: /* WIN95 */
603 return MAKELONG(700, 23); /* Win95A */
604 case 0x80000a04: /* WIN98 */
605 return MAKELONG(3024, 10); /* W98 SE */
606 case 0x00000004: /* NT4 */
607 return MAKELONG(4277, 40); /* NT4 SP6 */
609 FIXME("Version value not known yet. Please investigate it!\n");
614 /* for better debugging info leave the static out for the time being */
617 /*======================= ITypeLib implementation =======================*/
619 typedef struct tagTLBCustData
623 struct tagTLBCustData* next;
626 /* data structure for import typelibs */
627 typedef struct tagTLBImpLib
629 int offset; /* offset in the file (MSFT)
630 offset in nametable (SLTG)
631 just used to identify library while reading
633 GUID guid; /* libid */
634 BSTR name; /* name */
636 LCID lcid; /* lcid of imported typelib */
638 WORD wVersionMajor; /* major version number */
639 WORD wVersionMinor; /* minor version number */
641 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
642 NULL if not yet loaded */
643 struct tagTLBImpLib * next;
646 /* internal ITypeLib data */
647 typedef struct tagITypeLibImpl
649 ICOM_VFIELD(ITypeLib2);
651 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
653 /* strings can be stored in tlb as multibyte strings BUT they are *always*
654 * exported to the application as a UNICODE string.
660 unsigned long dwHelpContext;
661 int TypeInfoCount; /* nr of typeinfo's in librarry */
662 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
663 int ctCustData; /* number of items in cust data list */
664 TLBCustData * pCustData; /* linked list to cust data */
665 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
666 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
667 libary. Only used while read MSFT
671 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
673 /* ITypeLib methods */
674 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
675 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
677 /*======================= ITypeInfo implementation =======================*/
679 /* data for refernced types */
680 typedef struct tagTLBRefType
682 INT index; /* Type index for internal ref or for external ref
683 it the format is SLTG. -2 indicates to
686 GUID guid; /* guid of the referenced type */
687 /* if index == TLB_REF_USE_GUID */
689 HREFTYPE reference; /* The href of this ref */
690 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
691 TLB_REF_INTERNAL for internal refs
692 TLB_REF_NOT_FOUND for broken refs */
694 struct tagTLBRefType * next;
697 #define TLB_REF_USE_GUID -2
699 #define TLB_REF_INTERNAL (void*)-2
700 #define TLB_REF_NOT_FOUND (void*)-1
702 /* internal Parameter data */
703 typedef struct tagTLBParDesc
707 TLBCustData * pCustData; /* linked list to cust data */
710 /* internal Function data */
711 typedef struct tagTLBFuncDesc
713 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
714 BSTR Name; /* the name of this function */
715 TLBParDesc *pParamDesc; /* array with param names and custom data */
717 int HelpStringContext;
719 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
721 TLBCustData * pCustData; /* linked list to cust data; */
722 struct tagTLBFuncDesc * next;
725 /* internal Variable data */
726 typedef struct tagTLBVarDesc
728 VARDESC vardesc; /* lots of info on the variable and its attributes. */
729 BSTR Name; /* the name of this variable */
731 int HelpStringContext; /* FIXME: where? */
734 TLBCustData * pCustData;/* linked list to cust data; */
735 struct tagTLBVarDesc * next;
738 /* internal implemented interface data */
739 typedef struct tagTLBImplType
741 HREFTYPE hRef; /* hRef of interface */
742 int implflags; /* IMPLFLAG_*s */
744 TLBCustData * pCustData;/* linked list to custom data; */
745 struct tagTLBImplType *next;
748 /* internal TypeInfo data */
749 typedef struct tagITypeInfoImpl
751 ICOM_VFIELD(ITypeInfo2);
753 TYPEATTR TypeAttr ; /* _lots_ of type information. */
754 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
755 int index; /* index in this typelib; */
756 /* type libs seem to store the doc strings in ascii
757 * so why should we do it in unicode?
761 unsigned long dwHelpContext;
762 unsigned long dwHelpStringContext;
765 TLBFuncDesc * funclist; /* linked list with function descriptions */
768 TLBVarDesc * varlist; /* linked list with variable descriptions */
770 /* Implemented Interfaces */
771 TLBImplType * impltypelist;
773 TLBRefType * reflist;
775 TLBCustData * pCustData; /* linked list to cust data; */
776 struct tagITypeInfoImpl * next;
779 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
781 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
783 typedef struct tagTLBContext
785 unsigned int oStart; /* start of TLB in file */
786 unsigned int pos; /* current pos */
787 unsigned int length; /* total length */
788 void *mapping; /* memory mapping */
789 MSFT_SegDir * pTblDir;
790 ITypeLibImpl* pLibInfo;
794 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
799 static void dump_VarType(VARTYPE vt,char *szVarType) {
800 /* FIXME : we could have better trace here, depending on the VARTYPE
803 if (vt & VT_RESERVED)
804 szVarType += strlen(strcpy(szVarType, "reserved | "));
806 szVarType += strlen(strcpy(szVarType, "ref to "));
808 szVarType += strlen(strcpy(szVarType, "array of "));
810 szVarType += strlen(strcpy(szVarType, "vector of "));
811 switch(vt & VT_TYPEMASK) {
812 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
813 case VT_I2: sprintf(szVarType, "VT_I2"); break;
814 case VT_I4: sprintf(szVarType, "VT_I4"); break;
815 case VT_R4: sprintf(szVarType, "VT_R4"); break;
816 case VT_R8: sprintf(szVarType, "VT_R8"); break;
817 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
818 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
819 case VT_CY: sprintf(szVarType, "VT_CY"); break;
820 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
821 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
822 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
823 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
824 case VT_I1: sprintf(szVarType, "VT_I1"); break;
825 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
826 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
827 case VT_INT: sprintf(szVarType, "VT_INT"); break;
828 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
829 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
830 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
831 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
832 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
836 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
837 if (pTD->vt & VT_RESERVED)
838 szVarType += strlen(strcpy(szVarType, "reserved | "));
839 if (pTD->vt & VT_BYREF)
840 szVarType += strlen(strcpy(szVarType, "ref to "));
841 if (pTD->vt & VT_ARRAY)
842 szVarType += strlen(strcpy(szVarType, "array of "));
843 if (pTD->vt & VT_VECTOR)
844 szVarType += strlen(strcpy(szVarType, "vector of "));
845 switch(pTD->vt & VT_TYPEMASK) {
846 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
847 case VT_I2: sprintf(szVarType, "VT_I2"); break;
848 case VT_I4: sprintf(szVarType, "VT_I4"); break;
849 case VT_R4: sprintf(szVarType, "VT_R4"); break;
850 case VT_R8: sprintf(szVarType, "VT_R8"); break;
851 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
852 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
853 case VT_CY: sprintf(szVarType, "VT_CY"); break;
854 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
855 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
856 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
857 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
858 case VT_I1: sprintf(szVarType, "VT_I1"); break;
859 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
860 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
861 case VT_INT: sprintf(szVarType, "VT_INT"); break;
862 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
863 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
864 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
865 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
866 pTD->u.hreftype); break;
867 case VT_PTR: sprintf(szVarType, "ptr to ");
868 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
870 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
871 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
873 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
874 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
875 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
878 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
882 void dump_ELEMDESC(ELEMDESC *edesc) {
884 dump_TypeDesc(&edesc->tdesc,buf);
885 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
886 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
887 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
889 void dump_FUNCDESC(FUNCDESC *funcdesc) {
891 MESSAGE("memid is %08lx\n",funcdesc->memid);
892 for (i=0;i<funcdesc->cParams;i++) {
893 MESSAGE("Param %d:\n",i);
894 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
896 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
897 switch (funcdesc->funckind) {
898 case FUNC_VIRTUAL: MESSAGE("virtual");break;
899 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
900 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
901 case FUNC_STATIC: MESSAGE("static");break;
902 case FUNC_DISPATCH: MESSAGE("dispatch");break;
903 default: MESSAGE("unknown");break;
905 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
906 switch (funcdesc->invkind) {
907 case INVOKE_FUNC: MESSAGE("func");break;
908 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
909 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
910 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
912 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
913 switch (funcdesc->callconv) {
914 case CC_CDECL: MESSAGE("cdecl");break;
915 case CC_PASCAL: MESSAGE("pascal");break;
916 case CC_STDCALL: MESSAGE("stdcall");break;
917 case CC_SYSCALL: MESSAGE("syscall");break;
920 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
921 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
922 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
925 void dump_IDLDESC(IDLDESC *idl) {
926 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
929 static char * typekind_desc[] =
942 void dump_TYPEATTR(TYPEATTR *tattr) {
944 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
945 MESSAGE("\tlcid: %ld\n",tattr->lcid);
946 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
947 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
948 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
949 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
950 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
951 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
952 MESSAGE("\tcVars: %d\n", tattr->cVars);
953 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
954 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
955 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
956 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
957 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
958 dump_TypeDesc(&tattr->tdescAlias,buf);
959 MESSAGE("\ttypedesc: %s\n", buf);
960 dump_IDLDESC(&tattr->idldescType);
963 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
966 if (!TRACE_ON(typelib))
968 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
969 for (i=0;i<pfd->funcdesc.cParams;i++)
970 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
973 dump_FUNCDESC(&(pfd->funcdesc));
975 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
976 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
978 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
982 dump_TLBFuncDescOne(pfd);
986 static void dump_TLBVarDesc(TLBVarDesc * pvd)
990 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
995 static void dump_TLBImpLib(TLBImpLib *import)
997 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
998 debugstr_w(import->name));
999 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1000 import->wVersionMinor, import->lcid, import->offset);
1003 static void dump_TLBRefType(TLBRefType * prt)
1007 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1008 if(prt->index == -1)
1009 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1011 TRACE_(typelib)("type no: %d\n", prt->index);
1013 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1014 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1015 TRACE_(typelib)("in lib\n");
1016 dump_TLBImpLib(prt->pImpTLInfo);
1022 static void dump_TLBImplType(TLBImplType * impl)
1026 "implementing/inheriting interface hRef = %lx implflags %x\n",
1027 impl->hRef, impl->implflags);
1032 void dump_Variant(VARIANT * pvar)
1037 TRACE("(%p)\n", pvar);
1041 ZeroMemory(szVarType, sizeof(szVarType));
1043 /* FIXME : we could have better trace here, depending on the VARTYPE
1046 dump_VarType(V_VT(pvar),szVarType);
1048 TRACE("VARTYPE: %s\n", szVarType);
1050 if (V_VT(pvar) & VT_BYREF) {
1051 ref = V_UNION(pvar, byref);
1054 else ref = &V_UNION(pvar, cVal);
1056 if (V_VT(pvar) & VT_ARRAY) {
1060 if (V_VT(pvar) & VT_VECTOR) {
1065 switch (V_VT(pvar) & VT_TYPEMASK)
1068 TRACE("%d\n", *(short*)ref);
1072 TRACE("%d\n", *(INT*)ref);
1076 TRACE("%3.3e\n", *(float*)ref);
1080 TRACE("%3.3e\n", *(double*)ref);
1084 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1088 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1093 TRACE("%p\n", *(LPVOID*)ref);
1097 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1103 memset( &TM, 0, sizeof(TM) );
1105 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1106 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1108 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1109 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1110 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1116 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1121 TRACE("(?)%ld\n", *(long*)ref);
1126 static void dump_DispParms(DISPPARAMS * pdp)
1130 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1132 while (index < pdp->cArgs)
1134 dump_Variant( &pdp->rgvarg[index] );
1139 static void dump_TypeInfo(ITypeInfoImpl * pty)
1141 TRACE("%p ref=%u\n", pty, pty->ref);
1142 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1143 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1144 TRACE("fct:%u var:%u impl:%u\n",
1145 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1146 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1147 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1148 dump_TLBFuncDesc(pty->funclist);
1149 dump_TLBVarDesc(pty->varlist);
1150 dump_TLBImplType(pty->impltypelist);
1153 void dump_VARDESC(VARDESC *v)
1155 MESSAGE("memid %ld\n",v->memid);
1156 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1157 MESSAGE("oInst %ld\n",v->u.oInst);
1158 dump_ELEMDESC(&(v->elemdescVar));
1159 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1160 MESSAGE("varkind %d\n",v->varkind);
1163 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1165 /* VT_LPWSTR is largest type that */
1166 /* may appear in type description*/
1167 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1168 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1169 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1170 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1171 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1172 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1176 static void TLB_abort()
1180 static void * TLB_Alloc(unsigned size)
1183 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1185 ERR("cannot allocate memory\n");
1190 static void TLB_Free(void * ptr)
1192 HeapFree(GetProcessHeap(), 0, ptr);
1196 /**********************************************************************
1198 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1201 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1203 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1204 pcx->pos, count, pcx->oStart, pcx->length, where);
1206 if (where != DO_NOT_SEEK)
1208 where += pcx->oStart;
1209 if (where > pcx->length)
1212 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1217 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1218 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1223 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1225 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1227 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1228 memset(pGuid,0, sizeof(GUID));
1231 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1234 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1237 MSFT_NameIntro niName;
1239 WCHAR* pwstring = NULL;
1240 BSTR bstrName = NULL;
1242 MSFT_Read(&niName, sizeof(niName), pcx,
1243 pcx->pTblDir->pNametab.offset+offset);
1244 niName.namelen &= 0xFF; /* FIXME: correct ? */
1245 name=TLB_Alloc((niName.namelen & 0xff) +1);
1246 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1247 name[niName.namelen & 0xff]='\0';
1249 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1252 /* no invalid characters in string */
1255 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1257 /* don't check for invalid character since this has been done previously */
1258 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1260 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1261 lengthInChars = SysStringLen(bstrName);
1262 HeapFree(GetProcessHeap(), 0, pwstring);
1265 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1269 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1276 if(offset<0) return NULL;
1277 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1278 if(length <= 0) return 0;
1279 string=TLB_Alloc(length +1);
1280 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1281 string[length]='\0';
1283 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1284 string, -1, NULL, 0);
1286 /* no invalid characters in string */
1289 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1291 /* don't check for invalid character since this has been done previously */
1292 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1294 bstr = SysAllocStringLen(pwstring, lengthInChars);
1295 lengthInChars = SysStringLen(bstr);
1296 HeapFree(GetProcessHeap(), 0, pwstring);
1299 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1303 * read a value and fill a VARIANT structure
1305 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1309 TRACE_(typelib)("\n");
1311 if(offset <0) { /* data are packed in here */
1312 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1313 V_UNION(pVar, iVal) = offset & 0xffff;
1316 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1317 pcx->pTblDir->pCustData.offset + offset );
1318 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1319 switch (V_VT(pVar)){
1320 case VT_EMPTY: /* FIXME: is this right? */
1321 case VT_NULL: /* FIXME: is this right? */
1322 case VT_I2 : /* this should not happen */
1333 case VT_VOID : /* FIXME: is this right? */
1341 case VT_DECIMAL : /* FIXME: is this right? */
1344 /* pointer types with known behaviour */
1347 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1349 FIXME("BSTR length = %d?\n", size);
1351 ptr=TLB_Alloc(size);/* allocate temp buffer */
1352 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1353 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1354 /* FIXME: do we need a AtoW conversion here? */
1355 V_UNION(pVar, bstrVal[size])=L'\0';
1356 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1361 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1368 case VT_USERDEFINED :
1374 case VT_STREAMED_OBJECT :
1375 case VT_STORED_OBJECT :
1376 case VT_BLOB_OBJECT :
1381 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1385 if(size>0) /* (big|small) endian correct? */
1386 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1390 * create a linked list with custom data
1392 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1398 TRACE_(typelib)("\n");
1402 pNew=TLB_Alloc(sizeof(TLBCustData));
1403 MSFT_Read(&entry, sizeof(entry), pcx,
1404 pcx->pTblDir->pCDGuids.offset+offset);
1405 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1406 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1407 /* add new custom data at head of the list */
1408 pNew->next=*ppCustData;
1410 offset = entry.next;
1415 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1419 pTd->vt=type & VT_TYPEMASK;
1421 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1423 if(pTd->vt == VT_USERDEFINED)
1424 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1426 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1430 MSFT_DoFuncs(TLBContext* pcx,
1435 TLBFuncDesc** pptfd)
1438 * member information is stored in a data structure at offset
1439 * indicated by the memoffset field of the typeinfo structure
1440 * There are several distinctive parts.
1441 * the first part starts with a field that holds the total length
1442 * of this (first) part excluding this field. Then follow the records,
1443 * for each member there is one record.
1445 * First entry is always the length of the record (excluding this
1447 * Rest of the record depends on the type of the member. If there is
1448 * a field indicating the member type (function variable intereface etc)
1449 * I have not found it yet. At this time we depend on the information
1450 * in the type info and the usual order how things are stored.
1452 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1455 * Third is a equal sized array with file offsets to the name entry
1458 * Forth and last (?) part is an array with offsets to the records in the
1459 * first part of this file segment.
1462 int infolen, nameoffset, reclength, nrattributes, i;
1463 int recoffset = offset + sizeof(INT);
1466 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1468 TRACE_(typelib)("\n");
1470 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1472 for ( i = 0; i < cFuncs ; i++ )
1474 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1476 /* name, eventually add to a hash table */
1477 MSFT_Read(&nameoffset,
1480 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1482 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1484 /* read the function information record */
1485 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1489 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1491 /* do the attributes */
1492 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1495 if ( nrattributes > 0 )
1497 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1499 if ( nrattributes > 1 )
1501 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1502 pFuncRec->OptAttr[1]) ;
1504 if ( nrattributes > 2 )
1506 if ( pFuncRec->FKCCIC & 0x2000 )
1508 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1512 (*pptfd)->Entry = MSFT_ReadString(pcx,
1513 pFuncRec->OptAttr[2]);
1515 if( nrattributes > 5 )
1517 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1519 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1522 pFuncRec->OptAttr[6],
1523 &(*pptfd)->pCustData);
1530 /* fill the FuncDesc Structure */
1531 MSFT_Read( & (*pptfd)->funcdesc.memid,
1533 offset + infolen + ( i + 1) * sizeof(INT));
1535 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1536 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1537 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1538 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1539 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1540 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1541 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1545 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1548 /* do the parameters/arguments */
1549 if(pFuncRec->nrargs)
1552 MSFT_ParameterInfo paraminfo;
1554 (*pptfd)->funcdesc.lprgelemdescParam =
1555 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1557 (*pptfd)->pParamDesc =
1558 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1560 MSFT_Read(¶minfo,
1563 recoffset + reclength -
1564 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1566 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1568 TYPEDESC* lpArgTypeDesc = 0;
1572 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1575 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1577 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1579 /* SEEK value = jump to offset,
1580 * from there jump to the end of record,
1581 * go back by (j-1) arguments
1583 MSFT_Read( ¶minfo ,
1584 sizeof(MSFT_ParameterInfo), pcx,
1585 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1586 * sizeof(MSFT_ParameterInfo)));
1588 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1590 while ( lpArgTypeDesc != NULL )
1592 switch ( lpArgTypeDesc->vt )
1595 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1599 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1602 case VT_USERDEFINED:
1603 MSFT_DoRefType(pcx, pTI,
1604 lpArgTypeDesc->u.hreftype);
1606 lpArgTypeDesc = NULL;
1610 lpArgTypeDesc = NULL;
1616 /* parameter is the return value! */
1617 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1619 TYPEDESC* lpArgTypeDesc;
1621 (*pptfd)->funcdesc.elemdescFunc =
1622 (*pptfd)->funcdesc.lprgelemdescParam[j];
1624 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1626 while ( lpArgTypeDesc != NULL )
1628 switch ( lpArgTypeDesc->vt )
1631 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1635 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1639 case VT_USERDEFINED:
1642 lpArgTypeDesc->u.hreftype);
1644 lpArgTypeDesc = NULL;
1648 lpArgTypeDesc = NULL;
1653 /* second time around */
1654 for(j=0;j<pFuncRec->nrargs;j++)
1657 (*pptfd)->pParamDesc[j].Name =
1658 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1661 if ( (PARAMFLAG_FHASDEFAULT &
1662 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1663 ((pFuncRec->FKCCIC) & 0x1000) )
1665 INT* pInt = (INT *)((char *)pFuncRec +
1667 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1669 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1671 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1672 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1674 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1678 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1681 pFuncRec->OptAttr[7+j],
1682 &(*pptfd)->pParamDesc[j].pCustData);
1687 /* scode is not used: archaic win16 stuff FIXME: right? */
1688 (*pptfd)->funcdesc.cScodes = 0 ;
1689 (*pptfd)->funcdesc.lprgscode = NULL ;
1691 pptfd = & ((*pptfd)->next);
1692 recoffset += reclength;
1695 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1696 int cVars, int offset, TLBVarDesc ** pptvd)
1698 int infolen, nameoffset, reclength;
1700 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1704 TRACE_(typelib)("\n");
1706 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1707 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1708 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1709 recoffset += offset+sizeof(INT);
1710 for(i=0;i<cVars;i++){
1711 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1712 /* name, eventually add to a hash table */
1713 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1714 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1715 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1716 /* read the variable information record */
1717 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1719 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1721 if(reclength >(6*sizeof(INT)) )
1722 (*pptvd)->HelpContext=pVarRec->HelpContext;
1723 if(reclength >(7*sizeof(INT)) )
1724 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1725 if(reclength >(8*sizeof(INT)) )
1726 if(reclength >(9*sizeof(INT)) )
1727 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1728 /* fill the VarDesc Structure */
1729 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1730 offset + infolen + ( i + 1) * sizeof(INT));
1731 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1732 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1733 MSFT_GetTdesc(pcx, pVarRec->DataType,
1734 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1735 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1736 if(pVarRec->VarKind == VAR_CONST ){
1737 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1738 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1739 pVarRec->OffsValue, pcx);
1741 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1742 pptvd=&((*pptvd)->next);
1743 recoffset += reclength;
1746 /* fill in data for a hreftype (offset). When the refernced type is contained
1747 * in the typelib, it's just an (file) offset in the type info base dir.
1748 * If comes from import, it's an offset+1 in the ImpInfo table
1750 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1754 TLBRefType **ppRefType = &pTI->reflist;
1756 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1759 if((*ppRefType)->reference == offset)
1761 ppRefType = &(*ppRefType)->next;
1764 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1765 sizeof(**ppRefType));
1767 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1768 /* external typelib */
1769 MSFT_ImpInfo impinfo;
1770 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1772 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1774 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1775 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1776 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1777 if(pImpLib->offset==impinfo.oImpFile) break;
1778 pImpLib=pImpLib->next;
1781 (*ppRefType)->reference=offset;
1782 (*ppRefType)->pImpTLInfo = pImpLib;
1783 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1784 (*ppRefType)->index = TLB_REF_USE_GUID;
1786 ERR("Cannot find a reference\n");
1787 (*ppRefType)->reference=-1;
1788 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1791 /* in this typelib */
1792 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1793 (*ppRefType)->reference=offset;
1794 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1798 /* process Implemented Interfaces of a com class */
1799 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1803 MSFT_RefRecord refrec;
1804 TLBImplType **ppImpl = &pTI->impltypelist;
1806 TRACE_(typelib)("\n");
1808 for(i=0;i<count;i++){
1809 if(offset<0) break; /* paranoia */
1810 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1811 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1812 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1813 (*ppImpl)->hRef = refrec.reftype;
1814 (*ppImpl)->implflags=refrec.flags;
1815 (*ppImpl)->ctCustData=
1816 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1817 offset=refrec.onext;
1818 ppImpl=&((*ppImpl)->next);
1822 * process a typeinfo record
1824 ITypeInfoImpl * MSFT_DoTypeInfo(
1827 ITypeLibImpl * pLibInfo)
1829 MSFT_TypeInfoBase tiBase;
1830 ITypeInfoImpl *ptiRet;
1832 TRACE_(typelib)("count=%u\n", count);
1834 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1835 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1836 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1837 /* this is where we are coming from */
1838 ptiRet->pTypeLib = pLibInfo;
1839 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1840 ptiRet->index=count;
1841 /* fill in the typeattr fields */
1842 FIXME("Assign constructor/destructor memid\n");
1844 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1845 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1846 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1847 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1848 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1849 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1850 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1851 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1852 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1853 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1854 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1855 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1856 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1857 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1858 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1859 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1860 MSFT_GetTdesc(pcx, tiBase.datatype1,
1861 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1864 /* IDLDESC idldescType; *//* never saw this one != zero */
1866 /* name, eventually add to a hash table */
1867 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1868 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1870 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1871 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1872 ptiRet->dwHelpContext=tiBase.helpcontext;
1873 /* note: InfoType's Help file and HelpStringDll come from the containing
1874 * library. Further HelpString and Docstring appear to be the same thing :(
1877 if(ptiRet->TypeAttr.cFuncs >0 )
1878 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1879 ptiRet->TypeAttr.cVars,
1880 tiBase.memoffset, & ptiRet->funclist);
1882 if(ptiRet->TypeAttr.cVars >0 )
1883 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1884 ptiRet->TypeAttr.cVars,
1885 tiBase.memoffset, & ptiRet->varlist);
1886 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1887 switch(ptiRet->TypeAttr.typekind)
1890 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1893 case TKIND_DISPATCH:
1894 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1896 if (tiBase.datatype1 != -1)
1898 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1899 ptiRet->impltypelist->hRef = tiBase.datatype1;
1902 { /* FIXME: This is a really bad hack to add IDispatch */
1903 char* szStdOle = "stdole2.tlb\0";
1904 int nStdOleLen = strlen(szStdOle);
1905 TLBRefType **ppRef = &ptiRet->reflist;
1908 if((*ppRef)->reference == -1)
1910 ppRef = &(*ppRef)->next;
1913 *ppRef = TLB_Alloc(sizeof(**ppRef));
1914 (*ppRef)->guid = IID_IDispatch;
1915 (*ppRef)->reference = -1;
1916 (*ppRef)->index = TLB_REF_USE_GUID;
1917 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1918 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1919 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1922 MultiByteToWideChar(CP_ACP,
1926 (*ppRef)->pImpTLInfo->name,
1927 SysStringLen((*ppRef)->pImpTLInfo->name));
1929 (*ppRef)->pImpTLInfo->lcid = 0;
1930 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1931 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1936 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1937 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1938 ptiRet->impltypelist->hRef = tiBase.datatype1;
1943 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1945 TRACE_(typelib)("%s guid: %s kind:%s\n",
1946 debugstr_w(ptiRet->Name),
1947 debugstr_guid(&ptiRet->TypeAttr.guid),
1948 typekind_desc[ptiRet->TypeAttr.typekind]);
1953 /****************************************************************************
1956 * find the type of the typelib file and map the typelib resource into
1959 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1960 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1961 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1963 int ret = TYPE_E_CANTLOADLIBRARY;
1964 DWORD dwSignature = 0;
1967 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1971 /* check the signature of the file */
1972 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1973 if (INVALID_HANDLE_VALUE != hFile)
1975 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1978 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1981 /* retrieve file size */
1982 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1984 /* first try to load as *.tlb */
1985 dwSignature = *((DWORD*) pBase);
1986 if ( dwSignature == MSFT_SIGNATURE)
1988 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1990 else if ( dwSignature == SLTG_SIGNATURE)
1992 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1994 UnmapViewOfFile(pBase);
1996 CloseHandle(hMapping);
2001 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2003 /* find the typelibrary resource*/
2004 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2005 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2008 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2012 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2015 LPVOID pBase = LockResource(hGlobal);
2016 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2020 /* try to load as incore resource */
2021 dwSignature = *((DWORD*) pBase);
2022 if ( dwSignature == MSFT_SIGNATURE)
2024 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2026 else if ( dwSignature == SLTG_SIGNATURE)
2028 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2032 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2035 FreeResource( hGlobal );
2038 FreeLibrary(hinstDLL);
2045 ERR("Loading of typelib %s failed with error %ld\n",
2046 debugstr_w(pszFileName), GetLastError());
2051 /*================== ITypeLib(2) Methods ===================================*/
2053 /****************************************************************************
2054 * ITypeLib2_Constructor_MSFT
2056 * loading an MSFT typelib from an in-memory image
2058 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2062 MSFT_Header tlbHeader;
2063 MSFT_SegDir tlbSegDir;
2064 ITypeLibImpl * pTypeLibImpl;
2066 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2068 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2069 if (!pTypeLibImpl) return NULL;
2071 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2072 pTypeLibImpl->ref = 1;
2074 /* get pointer to beginning of typelib data */
2078 cx.pLibInfo = pTypeLibImpl;
2079 cx.length = dwTLBLength;
2082 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2084 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2085 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
2086 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2089 /* there is a small amount of information here until the next important
2091 * the segment directory . Try to calculate the amount of data */
2092 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2094 /* now read the segment directory */
2095 TRACE("read segment directory (at %ld)\n",lPSegDir);
2096 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2097 cx.pTblDir = &tlbSegDir;
2099 /* just check two entries */
2100 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2102 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2103 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2107 /* now fill our internal data */
2108 /* TLIBATTR fields */
2109 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2111 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2112 /* Windows seems to have zero here, is this correct? */
2113 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2114 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2116 pTypeLibImpl->LibAttr.lcid = 0;
2118 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2119 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2120 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2121 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2123 /* name, eventually add to a hash table */
2124 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2127 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2128 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2130 if( tlbHeader.varflags & HELPDLLFLAG)
2133 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2134 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2137 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2140 if(tlbHeader.CustomDataOffset >= 0)
2142 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2145 /* fill in typedescriptions */
2146 if(tlbSegDir.pTypdescTab.length > 0)
2148 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2150 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2151 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2154 /* FIXME: add several sanity checks here */
2155 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2156 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2158 /* FIXME: check safearray */
2160 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2162 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2164 else if(td[0] == VT_CARRAY)
2166 /* array descr table here */
2167 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2169 else if(td[0] == VT_USERDEFINED)
2171 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2173 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2176 /* second time around to fill the array subscript info */
2179 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2180 if(tlbSegDir.pArrayDescriptions.offset>0)
2182 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2183 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2186 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2188 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2190 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2192 for(j = 0; j<td[2]; j++)
2194 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2195 sizeof(INT), &cx, DO_NOT_SEEK);
2196 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2197 sizeof(INT), &cx, DO_NOT_SEEK);
2202 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2203 ERR("didn't find array description data\n");
2208 /* imported type libs */
2209 if(tlbSegDir.pImpFiles.offset>0)
2211 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2212 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2215 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2217 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2218 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2219 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2221 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2222 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2223 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2224 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2227 (*ppImpLib)->name = TLB_Alloc(size+1);
2228 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2229 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2230 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2232 ppImpLib = &(*ppImpLib)->next;
2237 if(tlbHeader.nrtypeinfos >= 0 )
2239 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2240 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2243 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2245 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2247 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2248 ppTI = &((*ppTI)->next);
2249 (pTypeLibImpl->TypeInfoCount)++;
2253 TRACE("(%p)\n", pTypeLibImpl);
2254 return (ITypeLib2*) pTypeLibImpl;
2258 static BSTR TLB_MultiByteToBSTR(char *ptr)
2264 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2265 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2266 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2267 ret = SysAllocString(nameW);
2268 HeapFree(GetProcessHeap(), 0, nameW);
2272 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2278 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2279 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2283 guid->Data4[0] = s >> 8;
2284 guid->Data4[1] = s & 0xff;
2287 for(i = 0; i < 6; i++) {
2288 memcpy(b, str + 24 + 2 * i, 2);
2289 guid->Data4[i + 2] = strtol(b, NULL, 16);
2294 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2301 bytelen = *(WORD*)ptr;
2302 if(bytelen == 0xffff) return 2;
2303 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2304 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2305 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2306 *pBstr = SysAllocStringLen(nameW, len);
2307 HeapFree(GetProcessHeap(), 0, nameW);
2311 static WORD SLTG_ReadStringA(char *ptr, char **str)
2316 bytelen = *(WORD*)ptr;
2317 if(bytelen == 0xffff) return 2;
2318 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2319 memcpy(*str, ptr + 2, bytelen);
2320 (*str)[bytelen] = '\0';
2324 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2326 char *ptr = pLibBlk;
2329 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2330 FIXME("libblk magic = %04x\n", w);
2335 if((w = *(WORD*)ptr) != 0xffff) {
2336 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2341 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2343 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2345 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2348 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2351 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2354 ptr += 4; /* skip res12 */
2356 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2359 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2362 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2365 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2366 ptr += sizeof(GUID);
2368 return ptr - (char*)pLibBlk;
2371 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2374 TYPEDESC *pTD = &pElem->tdesc;
2376 /* Handle [in/out] first */
2377 if((*pType & 0xc000) == 0xc000)
2378 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2379 else if(*pType & 0x8000)
2380 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2381 else if(*pType & 0x4000)
2382 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2384 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2387 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2390 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2393 if((*pType & 0xe00) == 0xe00) {
2395 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2397 pTD = pTD->u.lptdesc;
2399 switch(*pType & 0x7f) {
2402 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2404 pTD = pTD->u.lptdesc;
2407 case VT_USERDEFINED:
2408 pTD->vt = VT_USERDEFINED;
2409 pTD->u.hreftype = *(++pType) / 4;
2415 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2418 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2420 pTD->vt = VT_CARRAY;
2421 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2423 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2424 pTD->u.lpadesc->cDims = pSA->cDims;
2425 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2426 pSA->cDims * sizeof(SAFEARRAYBOUND));
2428 pTD = &pTD->u.lpadesc->tdescElem;
2434 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2438 pTD->vt = VT_SAFEARRAY;
2439 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2441 pTD = pTD->u.lptdesc;
2445 pTD->vt = *pType & 0x7f;
2455 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2460 TLBRefType **ppRefType;
2462 if(pRef->magic != SLTG_REF_MAGIC) {
2463 FIXME("Ref magic = %x\n", pRef->magic);
2466 name = ( (char*)(&pRef->names) + pRef->number);
2468 ppRefType = &pTI->reflist;
2469 for(ref = 0; ref < pRef->number >> 3; ref++) {
2471 unsigned int lib_offs, type_num;
2473 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2474 sizeof(**ppRefType));
2476 name += SLTG_ReadStringA(name, &refname);
2477 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2478 FIXME("Can't sscanf ref\n");
2479 if(lib_offs != 0xffff) {
2480 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2483 if((*import)->offset == lib_offs)
2485 import = &(*import)->next;
2488 char fname[MAX_PATH+1];
2491 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2493 (*import)->offset = lib_offs;
2494 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2496 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2497 &(*import)->wVersionMajor,
2498 &(*import)->wVersionMinor,
2499 &(*import)->lcid, fname) != 4) {
2500 FIXME("can't sscanf ref %s\n",
2501 pNameTable + lib_offs + 40);
2503 len = strlen(fname);
2504 if(fname[len-1] != '#')
2505 FIXME("fname = %s\n", fname);
2506 fname[len-1] = '\0';
2507 (*import)->name = TLB_MultiByteToBSTR(fname);
2509 (*ppRefType)->pImpTLInfo = *import;
2510 } else { /* internal ref */
2511 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2513 (*ppRefType)->reference = ref;
2514 (*ppRefType)->index = type_num;
2516 HeapFree(GetProcessHeap(), 0, refname);
2517 ppRefType = &(*ppRefType)->next;
2519 if((BYTE)*name != SLTG_REF_MAGIC)
2520 FIXME("End of ref block magic = %x\n", *name);
2521 dump_TLBRefType(pTI->reflist);
2524 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2527 SLTG_ImplInfo *info;
2528 TLBImplType **ppImplType = &pTI->impltypelist;
2529 /* I don't really get this structure, usually it's 0x16 bytes
2530 long, but iuser.tlb contains some that are 0x18 bytes long.
2531 That's ok because we can use the next ptr to jump to the next
2532 one. But how do we know the length of the last one? The WORD
2533 at offs 0x8 might be the clue. For now I'm just assuming that
2534 the last one is the regular 0x16 bytes. */
2536 info = (SLTG_ImplInfo*)pBlk;
2538 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2539 sizeof(**ppImplType));
2540 (*ppImplType)->hRef = info->ref;
2541 (*ppImplType)->implflags = info->impltypeflags;
2542 pTI->TypeAttr.cImplTypes++;
2543 ppImplType = &(*ppImplType)->next;
2545 if(info->next == 0xffff)
2548 FIXME("Interface inheriting more than one interface\n");
2549 info = (SLTG_ImplInfo*)(pBlk + info->next);
2551 info++; /* see comment at top of function */
2555 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2558 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2559 SLTG_MemberHeader *pMemHeader;
2560 char *pFirstItem, *pNextItem;
2562 if(pTIHeader->href_table != 0xffffffff) {
2563 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2568 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2570 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2572 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2573 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2576 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2580 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2583 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2584 SLTG_MemberHeader *pMemHeader;
2585 SLTG_Function *pFunc;
2586 char *pFirstItem, *pNextItem;
2587 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2590 if(pTIHeader->href_table != 0xffffffff) {
2591 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2595 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2597 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2599 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2600 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2603 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2604 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2609 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2610 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2611 FIXME("func magic = %02x\n", pFunc->magic);
2614 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2615 sizeof(**ppFuncDesc));
2616 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2618 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2619 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2620 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2621 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2622 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2623 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2625 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2626 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2628 if(pFunc->retnextopt & 0x80)
2629 pType = &pFunc->rettype;
2631 pType = (WORD*)(pFirstItem + pFunc->rettype);
2634 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2636 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2637 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2638 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2639 (*ppFuncDesc)->pParamDesc =
2640 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2641 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2643 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2645 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2646 char *paramName = pNameTable + *pArg;
2648 /* If arg type follows then paramName points to the 2nd
2649 letter of the name, else the next WORD is an offset to
2650 the arg type and paramName points to the first letter.
2651 So let's take one char off paramName and see if we're
2652 pointing at an alpha-numeric char. However if *pArg is
2653 0xffff or 0xfffe then the param has no name, the former
2654 meaning that the next WORD is the type, the latter
2655 meaning the the next WORD is an offset to the type. */
2660 else if(*pArg == 0xfffe) {
2664 else if(!isalnum(*(paramName-1)))
2669 if(HaveOffs) { /* the next word is an offset to type */
2670 pType = (WORD*)(pFirstItem + *pArg);
2671 SLTG_DoType(pType, pFirstItem,
2672 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2677 pArg = SLTG_DoType(pArg, pFirstItem,
2678 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2681 /* Are we an optional param ? */
2682 if((*ppFuncDesc)->funcdesc.cParams - param <=
2683 (*ppFuncDesc)->funcdesc.cParamsOpt)
2684 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2687 (*ppFuncDesc)->pParamDesc[param].Name =
2688 TLB_MultiByteToBSTR(paramName);
2692 ppFuncDesc = &((*ppFuncDesc)->next);
2693 if(pFunc->next == 0xffff) break;
2695 pTI->TypeAttr.cFuncs = num;
2696 dump_TLBFuncDesc(pTI->funclist);
2697 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2700 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2703 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2704 SLTG_MemberHeader *pMemHeader;
2705 SLTG_RecordItem *pItem;
2707 TLBVarDesc **ppVarDesc = &pTI->varlist;
2712 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2714 pFirstItem = (char*)(pMemHeader + 1);
2715 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2716 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2717 if(pItem->magic != SLTG_RECORD_MAGIC) {
2718 FIXME("record magic = %02x\n", pItem->magic);
2721 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2722 sizeof(**ppVarDesc));
2723 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2724 (*ppVarDesc)->vardesc.memid = pItem->memid;
2725 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2726 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2728 if(pItem->typepos == 0x02)
2729 pType = &pItem->type;
2730 else if(pItem->typepos == 0x00)
2731 pType = (WORD*)(pFirstItem + pItem->type);
2733 FIXME("typepos = %02x\n", pItem->typepos);
2737 SLTG_DoType(pType, pFirstItem,
2738 &(*ppVarDesc)->vardesc.elemdescVar);
2740 /* FIXME("helpcontext, helpstring\n"); */
2742 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2744 ppVarDesc = &((*ppVarDesc)->next);
2745 if(pItem->next == 0xffff) break;
2747 pTI->TypeAttr.cVars = num;
2748 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2751 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2754 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2755 SLTG_MemberHeader *pMemHeader;
2756 SLTG_EnumItem *pItem;
2758 TLBVarDesc **ppVarDesc = &pTI->varlist;
2761 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2763 pFirstItem = (char*)(pMemHeader + 1);
2764 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2765 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2766 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2767 FIXME("enumitem magic = %04x\n", pItem->magic);
2770 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2771 sizeof(**ppVarDesc));
2772 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2773 (*ppVarDesc)->vardesc.memid = pItem->memid;
2774 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2776 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2777 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2778 *(INT*)(pItem->value + pFirstItem);
2779 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2780 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2781 /* FIXME("helpcontext, helpstring\n"); */
2783 ppVarDesc = &((*ppVarDesc)->next);
2784 if(pItem->next == 0xffff) break;
2786 pTI->TypeAttr.cVars = num;
2787 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2790 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2791 managable copy of it into this */
2804 } SLTG_InternalOtherTypeInfo;
2806 /****************************************************************************
2807 * ITypeLib2_Constructor_SLTG
2809 * loading a SLTG typelib from an in-memory image
2811 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2813 ITypeLibImpl *pTypeLibImpl;
2814 SLTG_Header *pHeader;
2815 SLTG_BlkEntry *pBlkEntry;
2819 LPVOID pBlk, pFirstBlk;
2820 SLTG_LibBlk *pLibBlk;
2821 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2822 char *pAfterOTIBlks = NULL;
2823 char *pNameTable, *ptr;
2826 ITypeInfoImpl **ppTypeInfoImpl;
2828 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2830 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2831 if (!pTypeLibImpl) return NULL;
2833 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2834 pTypeLibImpl->ref = 1;
2839 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2840 pHeader->nrOfFileBlks );
2841 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2842 FIXME("Header type magic 0x%08lx not supported.\n",
2843 pHeader->SLTG_magic);
2847 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2848 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2850 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2851 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2853 /* Next we have a magic block */
2854 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2856 /* Let's see if we're still in sync */
2857 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2858 sizeof(SLTG_COMPOBJ_MAGIC))) {
2859 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2862 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2863 sizeof(SLTG_DIR_MAGIC))) {
2864 FIXME("dir magic = %s\n", pMagic->dir_magic);
2868 pIndex = (SLTG_Index*)(pMagic+1);
2870 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2872 pFirstBlk = (LPVOID)(pPad9 + 1);
2874 /* We'll set up a ptr to the main library block, which is the last one. */
2876 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2877 pBlkEntry[order].next != 0;
2878 order = pBlkEntry[order].next - 1, i++) {
2879 pBlk += pBlkEntry[order].len;
2883 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2885 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2890 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2892 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2893 sizeof(*pOtherTypeInfoBlks) *
2894 pTypeLibImpl->TypeInfoCount);
2897 ptr = (char*)pLibBlk + len;
2899 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2903 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2905 w = *(WORD*)(ptr + 2);
2908 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2910 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2911 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2913 w = *(WORD*)(ptr + 4 + len);
2915 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2917 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2919 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2920 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2922 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2923 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2924 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2926 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2928 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2931 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2932 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2933 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2934 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2935 len += sizeof(SLTG_OtherTypeInfo);
2939 pAfterOTIBlks = ptr;
2941 /* Skip this WORD and get the next DWORD */
2942 len = *(DWORD*)(pAfterOTIBlks + 2);
2944 /* Now add this to pLibBLk look at what we're pointing at and
2945 possibly add 0x20, then add 0x216, sprinkle a bit a magic
2946 dust and we should be pointing at the beginning of the name
2949 pNameTable = (char*)pLibBlk + len;
2951 switch(*(WORD*)pNameTable) {
2958 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
2962 pNameTable += 0x216;
2966 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2968 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2971 /* Hopefully we now have enough ptrs set up to actually read in
2972 some TypeInfos. It's not clear which order to do them in, so
2973 I'll just follow the links along the BlkEntry chain and read
2974 them in in the order in which they're in the file */
2976 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2978 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2979 pBlkEntry[order].next != 0;
2980 order = pBlkEntry[order].next - 1, i++) {
2982 SLTG_TypeInfoHeader *pTIHeader;
2983 SLTG_TypeInfoTail *pTITail;
2985 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2986 pOtherTypeInfoBlks[i].index_name)) {
2987 FIXME("Index strings don't match\n");
2992 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2993 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2996 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2997 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2998 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
2999 (*ppTypeInfoImpl)->index = i;
3000 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3001 pOtherTypeInfoBlks[i].name_offs +
3003 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3004 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3006 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3007 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3008 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3009 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3010 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3012 if((pTIHeader->typeflags1 & 7) != 2)
3013 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3014 if(pTIHeader->typeflags3 != 2)
3015 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3017 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3018 debugstr_w((*ppTypeInfoImpl)->Name),
3019 typekind_desc[pTIHeader->typekind],
3020 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3021 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3023 switch(pTIHeader->typekind) {
3025 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3029 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3032 case TKIND_INTERFACE:
3033 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3037 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3041 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3047 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3048 but we've already set those */
3049 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3050 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3051 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3053 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3054 pBlk += pBlkEntry[order].len;
3057 if(i != pTypeLibImpl->TypeInfoCount) {
3058 FIXME("Somehow processed %d TypeInfos\n", i);
3062 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3063 return (ITypeLib2*)pTypeLibImpl;
3066 /* ITypeLib::QueryInterface
3068 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3073 ICOM_THIS( ITypeLibImpl, iface);
3075 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3078 if(IsEqualIID(riid, &IID_IUnknown) ||
3079 IsEqualIID(riid,&IID_ITypeLib)||
3080 IsEqualIID(riid,&IID_ITypeLib2))
3087 ITypeLib2_AddRef(iface);
3088 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3091 TRACE("-- Interface: E_NOINTERFACE\n");
3092 return E_NOINTERFACE;
3097 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3099 ICOM_THIS( ITypeLibImpl, iface);
3101 TRACE("(%p)->ref is %u\n",This, This->ref);
3103 return ++(This->ref);
3106 /* ITypeLib::Release
3108 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3110 ICOM_THIS( ITypeLibImpl, iface);
3114 TRACE("(%p)->(%u)\n",This, This->ref);
3118 /* FIXME destroy child objects */
3120 TRACE(" destroying ITypeLib(%p)\n",This);
3124 SysFreeString(This->Name);
3128 if (This->DocString)
3130 SysFreeString(This->DocString);
3131 This->DocString = NULL;
3136 SysFreeString(This->HelpFile);
3137 This->HelpFile = NULL;
3140 if (This->HelpStringDll)
3142 SysFreeString(This->HelpStringDll);
3143 This->HelpStringDll = NULL;
3146 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3147 HeapFree(GetProcessHeap(),0,This);
3154 /* ITypeLib::GetTypeInfoCount
3156 * Returns the number of type descriptions in the type library
3158 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3160 ICOM_THIS( ITypeLibImpl, iface);
3161 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3162 return This->TypeInfoCount;
3165 /* ITypeLib::GetTypeInfo
3167 * retrieves the specified type description in the library.
3169 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3172 ITypeInfo **ppTInfo)
3176 ICOM_THIS( ITypeLibImpl, iface);
3177 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3179 TRACE("(%p)->(index=%d) \n", This, index);
3181 if (!ppTInfo) return E_INVALIDARG;
3183 /* search element n in list */
3184 for(i=0; i < index; i++)
3186 pTypeInfo = pTypeInfo->next;
3189 TRACE("-- element not found\n");
3190 return TYPE_E_ELEMENTNOTFOUND;
3194 *ppTInfo = (ITypeInfo *) pTypeInfo;
3196 ITypeInfo_AddRef(*ppTInfo);
3197 TRACE("-- found (%p)\n",*ppTInfo);
3202 /* ITypeLibs::GetTypeInfoType
3204 * Retrieves the type of a type description.
3206 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3211 ICOM_THIS( ITypeLibImpl, iface);
3213 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3215 TRACE("(%p) index %d \n",This, index);
3217 if(!pTKind) return E_INVALIDARG;
3219 /* search element n in list */
3220 for(i=0; i < index; i++)
3224 TRACE("-- element not found\n");
3225 return TYPE_E_ELEMENTNOTFOUND;
3227 pTInfo = pTInfo->next;
3230 *pTKind = pTInfo->TypeAttr.typekind;
3231 TRACE("-- found Type (%d)\n", *pTKind);
3235 /* ITypeLib::GetTypeInfoOfGuid
3237 * Retrieves the type description that corresponds to the specified GUID.
3240 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3243 ITypeInfo **ppTInfo)
3245 ICOM_THIS( ITypeLibImpl, iface);
3246 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3248 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3250 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3252 /* search linked list for guid */
3253 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3255 pTypeInfo = pTypeInfo->next;
3259 /* end of list reached */
3260 TRACE("-- element not found\n");
3261 return TYPE_E_ELEMENTNOTFOUND;
3265 TRACE("-- found (%p, %s)\n",
3267 debugstr_w(pTypeInfo->Name));
3269 *ppTInfo = (ITypeInfo*)pTypeInfo;
3270 ITypeInfo_AddRef(*ppTInfo);
3274 /* ITypeLib::GetLibAttr
3276 * Retrieves the structure that contains the library's attributes.
3279 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3281 LPTLIBATTR *ppTLibAttr)
3283 ICOM_THIS( ITypeLibImpl, iface);
3284 TRACE("(%p)\n",This);
3285 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3286 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3290 /* ITypeLib::GetTypeComp
3292 * Enables a client compiler to bind to a library's types, variables,
3293 * constants, and global functions.
3296 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3298 ITypeComp **ppTComp)
3300 ICOM_THIS( ITypeLibImpl, iface);
3301 FIXME("(%p): stub!\n",This);
3305 /* ITypeLib::GetDocumentation
3307 * Retrieves the library's documentation string, the complete Help file name
3308 * and path, and the context identifier for the library Help topic in the Help
3311 * On a successful return all non-null BSTR pointers will have been set,
3314 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3318 BSTR *pBstrDocString,
3319 DWORD *pdwHelpContext,
3320 BSTR *pBstrHelpFile)
3322 ICOM_THIS( ITypeLibImpl, iface);
3324 HRESULT result = E_INVALIDARG;
3329 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3331 pBstrName, pBstrDocString,
3332 pdwHelpContext, pBstrHelpFile);
3336 /* documentation for the typelib */
3340 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3346 if (This->DocString)
3347 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3348 else if (This->Name)
3349 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3351 *pBstrDocString = NULL;
3355 *pdwHelpContext = This->dwHelpContext;
3360 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3362 *pBstrHelpFile = NULL;
3369 /* for a typeinfo */
3370 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3372 if(SUCCEEDED(result))
3374 result = ITypeInfo_GetDocumentation(pTInfo,
3378 pdwHelpContext, pBstrHelpFile);
3380 ITypeInfo_Release(pTInfo);
3385 if (pBstrDocString) SysFreeString (*pBstrDocString);
3387 if (pBstrName) SysFreeString (*pBstrName);
3389 return STG_E_INSUFFICIENTMEMORY;
3394 * Indicates whether a passed-in string contains the name of a type or member
3395 * described in the library.
3398 static HRESULT WINAPI ITypeLib2_fnIsName(
3404 ICOM_THIS( ITypeLibImpl, iface);
3405 ITypeInfoImpl *pTInfo;
3406 TLBFuncDesc *pFInfo;
3409 UINT nNameBufLen = SysStringLen(szNameBuf);
3411 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3415 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3416 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3417 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3418 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3419 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3420 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3421 goto ITypeLib2_fnIsName_exit;
3423 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3424 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3429 ITypeLib2_fnIsName_exit:
3430 TRACE("(%p)slow! search for %s: %s found!\n", This,
3431 debugstr_w(szNameBuf), *pfName?"NOT":"");
3436 /* ITypeLib::FindName
3438 * Finds occurrences of a type description in a type library. This may be used
3439 * to quickly verify that a name exists in a type library.
3442 static HRESULT WINAPI ITypeLib2_fnFindName(
3446 ITypeInfo **ppTInfo,
3450 ICOM_THIS( ITypeLibImpl, iface);
3451 ITypeInfoImpl *pTInfo;
3452 TLBFuncDesc *pFInfo;
3456 UINT nNameBufLen = SysStringLen(szNameBuf);
3458 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3459 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3460 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3461 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3462 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3463 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3464 goto ITypeLib2_fnFindName_exit;
3466 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3467 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3469 ITypeLib2_fnFindName_exit:
3470 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3471 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3474 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3475 This, *pcFound, debugstr_w(szNameBuf), j);
3482 /* ITypeLib::ReleaseTLibAttr
3484 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3487 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3489 TLIBATTR *pTLibAttr)
3491 ICOM_THIS( ITypeLibImpl, iface);
3492 TRACE("freeing (%p)\n",This);
3493 HeapFree(GetProcessHeap(),0,pTLibAttr);
3497 /* ITypeLib2::GetCustData
3499 * gets the custom data
3501 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3506 ICOM_THIS( ITypeLibImpl, iface);
3507 TLBCustData *pCData;
3509 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3511 if( IsEqualIID(guid, &pCData->guid)) break;
3514 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3518 VariantInit( pVarVal);
3519 VariantCopy( pVarVal, &pCData->data);
3522 return E_INVALIDARG; /* FIXME: correct? */
3525 /* ITypeLib2::GetLibStatistics
3527 * Returns statistics about a type library that are required for efficient
3528 * sizing of hash tables.
3531 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3533 ULONG *pcUniqueNames,
3534 ULONG *pcchUniqueNames)
3536 ICOM_THIS( ITypeLibImpl, iface);
3538 FIXME("(%p): stub!\n", This);
3540 if(pcUniqueNames) *pcUniqueNames=1;
3541 if(pcchUniqueNames) *pcchUniqueNames=1;
3545 /* ITypeLib2::GetDocumentation2
3547 * Retrieves the library's documentation string, the complete Help file name
3548 * and path, the localization context to use, and the context ID for the
3549 * library Help topic in the Help file.
3552 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3556 BSTR *pbstrHelpString,
3557 DWORD *pdwHelpStringContext,
3558 BSTR *pbstrHelpStringDll)
3560 ICOM_THIS( ITypeLibImpl, iface);
3564 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3566 /* the help string should be obtained from the helpstringdll,
3567 * using the _DLLGetDocumentation function, based on the supplied
3568 * lcid. Nice to do sometime...
3572 /* documentation for the typelib */
3574 *pbstrHelpString=SysAllocString(This->DocString);
3575 if(pdwHelpStringContext)
3576 *pdwHelpStringContext=This->dwHelpContext;
3577 if(pbstrHelpStringDll)
3578 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3584 /* for a typeinfo */
3585 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3587 if(SUCCEEDED(result))
3589 ITypeInfo2 * pTInfo2;
3590 result = ITypeInfo_QueryInterface(pTInfo,
3592 (LPVOID*) &pTInfo2);
3594 if(SUCCEEDED(result))
3596 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3600 pdwHelpStringContext,
3601 pbstrHelpStringDll);
3603 ITypeInfo2_Release(pTInfo2);
3606 ITypeInfo_Release(pTInfo);
3612 /* ITypeLib2::GetAllCustData
3614 * Gets all custom data items for the library.
3617 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3619 CUSTDATA *pCustData)
3621 ICOM_THIS( ITypeLibImpl, iface);
3622 TLBCustData *pCData;
3624 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3625 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3626 if(pCustData->prgCustData ){
3627 pCustData->cCustData=This->ctCustData;
3628 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3629 pCustData->prgCustData[i].guid=pCData->guid;
3630 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3633 ERR(" OUT OF MEMORY! \n");
3634 return E_OUTOFMEMORY;
3639 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3640 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3641 ITypeLib2_fnQueryInterface,
3643 ITypeLib2_fnRelease,
3644 ITypeLib2_fnGetTypeInfoCount,
3645 ITypeLib2_fnGetTypeInfo,
3646 ITypeLib2_fnGetTypeInfoType,
3647 ITypeLib2_fnGetTypeInfoOfGuid,
3648 ITypeLib2_fnGetLibAttr,
3649 ITypeLib2_fnGetTypeComp,
3650 ITypeLib2_fnGetDocumentation,
3652 ITypeLib2_fnFindName,
3653 ITypeLib2_fnReleaseTLibAttr,
3655 ITypeLib2_fnGetCustData,
3656 ITypeLib2_fnGetLibStatistics,
3657 ITypeLib2_fnGetDocumentation2,
3658 ITypeLib2_fnGetAllCustData
3661 /*================== ITypeInfo(2) Methods ===================================*/
3662 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3664 ITypeInfoImpl * pTypeInfoImpl;
3666 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3669 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3670 pTypeInfoImpl->ref=1;
3672 TRACE("(%p)\n", pTypeInfoImpl);
3673 return (ITypeInfo2*) pTypeInfoImpl;
3676 /* ITypeInfo::QueryInterface
3678 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3683 ICOM_THIS( ITypeLibImpl, iface);
3685 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3688 if(IsEqualIID(riid, &IID_IUnknown) ||
3689 IsEqualIID(riid,&IID_ITypeInfo)||
3690 IsEqualIID(riid,&IID_ITypeInfo2))
3694 ITypeInfo_AddRef(iface);
3695 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3698 TRACE("-- Interface: E_NOINTERFACE\n");
3699 return E_NOINTERFACE;
3702 /* ITypeInfo::AddRef
3704 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3706 ICOM_THIS( ITypeInfoImpl, iface);
3710 TRACE("(%p)->ref is %u\n",This, This->ref);
3714 /* ITypeInfo::Release
3716 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3718 ICOM_THIS( ITypeInfoImpl, iface);
3722 TRACE("(%p)->(%u)\n",This, This->ref);
3726 FIXME("destroy child objects\n");
3728 TRACE("destroying ITypeInfo(%p)\n",This);
3731 SysFreeString(This->Name);
3735 if (This->DocString)
3737 SysFreeString(This->DocString);
3738 This->DocString = 0;
3743 ITypeInfo_Release((ITypeInfo*)This->next);
3746 HeapFree(GetProcessHeap(),0,This);
3752 /* ITypeInfo::GetTypeAttr
3754 * Retrieves a TYPEATTR structure that contains the attributes of the type
3758 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3759 LPTYPEATTR *ppTypeAttr)
3761 ICOM_THIS( ITypeInfoImpl, iface);
3762 TRACE("(%p)\n",This);
3763 /* FIXME: must do a copy here */
3764 *ppTypeAttr=&This->TypeAttr;
3768 /* ITypeInfo::GetTypeComp
3770 * Retrieves the ITypeComp interface for the type description, which enables a
3771 * client compiler to bind to the type description's members.
3774 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3775 ITypeComp * *ppTComp)
3777 ICOM_THIS( ITypeInfoImpl, iface);
3778 FIXME("(%p) stub!\n", This);
3782 /* ITypeInfo::GetFuncDesc
3784 * Retrieves the FUNCDESC structure that contains information about a
3785 * specified function.
3788 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3789 LPFUNCDESC *ppFuncDesc)
3791 ICOM_THIS( ITypeInfoImpl, iface);
3793 TLBFuncDesc * pFDesc;
3794 TRACE("(%p) index %d\n", This, index);
3795 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3798 /* FIXME: must do a copy here */
3799 *ppFuncDesc=&pFDesc->funcdesc;
3802 return E_INVALIDARG;
3805 /* ITypeInfo::GetVarDesc
3807 * Retrieves a VARDESC structure that describes the specified variable.
3810 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3811 LPVARDESC *ppVarDesc)
3813 ICOM_THIS( ITypeInfoImpl, iface);
3815 TLBVarDesc * pVDesc;
3816 TRACE("(%p) index %d\n", This, index);
3817 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3820 /* FIXME: must do a copy here */
3821 *ppVarDesc=&pVDesc->vardesc;
3824 return E_INVALIDARG;
3827 /* ITypeInfo_GetNames
3829 * Retrieves the variable with the specified member ID (or the name of the
3830 * property or method and its parameters) that correspond to the specified
3833 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3834 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3836 ICOM_THIS( ITypeInfoImpl, iface);
3837 TLBFuncDesc * pFDesc;
3838 TLBVarDesc * pVDesc;
3840 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3841 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3844 /* function found, now return function and parameter names */
3845 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3848 *rgBstrNames=SysAllocString(pFDesc->Name);
3850 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3856 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3859 *rgBstrNames=SysAllocString(pVDesc->Name);
3864 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3866 /* recursive search */
3869 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3871 if(SUCCEEDED(result))
3873 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3874 ITypeInfo_Release(pTInfo);
3877 WARN("Could not search inherited interface!\n");
3881 WARN("no names found\n");
3884 return TYPE_E_ELEMENTNOTFOUND;
3891 /* ITypeInfo::GetRefTypeOfImplType
3893 * If a type description describes a COM class, it retrieves the type
3894 * description of the implemented interface types. For an interface,
3895 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3899 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3904 ICOM_THIS( ITypeInfoImpl, iface);
3906 TLBImplType *pImpl = This->impltypelist;
3908 TRACE("(%p) index %d\n", This, index);
3909 dump_TypeInfo(This);
3913 /* only valid on dual interfaces;
3914 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3916 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3918 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3919 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3925 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3926 *pRefType = pImpl->hRef;
3931 /* get element n from linked list */
3932 for(i=0; pImpl && i<index; i++)
3934 pImpl = pImpl->next;
3937 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3939 *pRefType = pImpl->hRef;
3941 TRACE("-- 0x%08lx\n", pImpl->hRef );
3948 /* ITypeInfo::GetImplTypeFlags
3950 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3951 * or base interface in a type description.
3953 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3954 UINT index, INT *pImplTypeFlags)
3956 ICOM_THIS( ITypeInfoImpl, iface);
3960 TRACE("(%p) index %d\n", This, index);
3961 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3962 i++, pImpl=pImpl->next)
3964 if(i==index && pImpl){
3965 *pImplTypeFlags=pImpl->implflags;
3969 return TYPE_E_ELEMENTNOTFOUND;
3973 * Maps between member names and member IDs, and parameter names and
3976 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3977 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3979 ICOM_THIS( ITypeInfoImpl, iface);
3980 TLBFuncDesc * pFDesc;
3981 TLBVarDesc * pVDesc;
3984 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3986 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3988 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3989 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3990 for(i=1; i < cNames; i++){
3991 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3992 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3994 if( j<pFDesc->funcdesc.cParams)
3997 ret=DISP_E_UNKNOWNNAME;
4002 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4003 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4004 if(cNames) *pMemId=pVDesc->vardesc.memid;
4008 /* not found, see if this is and interface with an inheritance */
4009 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4010 This->TypeAttr.cImplTypes ){
4011 /* recursive search */
4013 ret=ITypeInfo_GetRefTypeInfo(iface,
4014 This->impltypelist->hRef, &pTInfo);
4016 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4017 ITypeInfo_Release(pTInfo);
4020 WARN("Could not search inherited interface!\n");
4022 WARN("no names found\n");
4023 return DISP_E_UNKNOWNNAME;
4026 /* ITypeInfo::Invoke
4028 * Invokes a method, or accesses a property of an object, that implements the
4029 * interface described by the type description.
4032 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
4035 if (TRACE_ON(ole)) {
4037 MESSAGE("Calling %p(",func);
4038 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
4047 DWORD (WINAPI *xfunc)() = func;
4052 DWORD (WINAPI *xfunc)(DWORD) = func;
4053 res = xfunc(args[0]);
4057 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
4058 res = xfunc(args[0],args[1]);
4062 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
4063 res = xfunc(args[0],args[1],args[2]);
4067 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
4068 res = xfunc(args[0],args[1],args[2],args[3]);
4072 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4073 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4077 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4078 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4082 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4083 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4087 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4088 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4092 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4093 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4097 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4103 FIXME("unsupported calling convention %d\n",callconv);
4107 TRACE("returns %08lx\n",res);
4111 extern int const _argsize(DWORD vt);
4113 static HRESULT WINAPI ITypeInfo_fnInvoke(
4118 DISPPARAMS *pDispParams,
4119 VARIANT *pVarResult,
4120 EXCEPINFO *pExcepInfo,
4123 ICOM_THIS( ITypeInfoImpl, iface);
4124 TLBFuncDesc * pFDesc;
4125 TLBVarDesc * pVDesc;
4128 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4129 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4131 dump_DispParms(pDispParams);
4133 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4134 if (pFDesc->funcdesc.memid == memid) {
4135 if (pFDesc->funcdesc.invkind & dwFlags)
4139 dump_TLBFuncDescOne(pFDesc);
4140 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4141 switch (pFDesc->funcdesc.funckind) {
4142 case FUNC_PUREVIRTUAL:
4143 case FUNC_VIRTUAL: {
4145 int numargs, numargs2, argspos, args2pos;
4146 DWORD *args , *args2;
4149 numargs = 1; numargs2 = 0;
4150 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4151 if (i<pDispParams->cArgs)
4152 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4154 numargs += 1; /* sizeof(lpvoid) */
4155 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4159 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4160 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4162 args[0] = (DWORD)pIUnk;
4163 argspos = 1; args2pos = 0;
4164 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4165 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4166 if (i<pDispParams->cArgs) {
4167 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4168 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4170 if (V_VT(arg) == tdesc->vt) {
4171 memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
4173 if (tdesc->vt == VT_VARIANT) {
4174 memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
4176 ERR("Set arg %d to disparg type %d vs %d\n",i,
4183 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4184 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4185 /*FIXME: give pointers for the rest, so propertyget works*/
4186 args[argspos] = (DWORD)&args2[args2pos];
4188 /* If pointer to variant, pass reference it. */
4189 if ((tdesc->vt == VT_PTR) &&
4190 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4193 args[argspos]= (DWORD)pVarResult;
4198 if (pFDesc->funcdesc.cParamsOpt)
4199 FIXME("Does not support optional parameters (%d)\n",
4200 pFDesc->funcdesc.cParamsOpt
4203 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4204 pFDesc->funcdesc.callconv,
4208 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4210 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4211 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4212 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4213 /* If we are a pointer to a variant, we are done already */
4214 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4217 VariantInit(pVarResult);
4218 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4220 if (tdesc->vt == VT_PTR)
4221 tdesc = tdesc->u.lptdesc;
4222 V_VT(pVarResult) = tdesc->vt;
4224 /* HACK: VB5 likes this.
4225 * I do not know why. There is 1 example in MSDN which uses
4226 * this which appears broken (mixes int vals and
4229 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4230 V_VT(pVarResult) = VT_DISPATCH;
4231 TRACE("storing into variant:\n");
4232 dump_Variant(pVarResult);
4236 HeapFree(GetProcessHeap(),0,args2);
4237 HeapFree(GetProcessHeap(),0,args);
4240 case FUNC_DISPATCH: {
4244 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4246 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4249 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4250 hr = IDispatch_Invoke(
4251 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4252 pVarResult,pExcepInfo,pArgErr
4255 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4256 IDispatch_Release(disp);
4260 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4264 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4265 if (pVDesc->vardesc.memid == memid) {
4266 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4267 dump_TLBVarDesc(pVDesc);
4272 /* not found, look for it in inherited interfaces */
4273 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4274 /* recursive search */
4277 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4279 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4280 ITypeInfo_Release(pTInfo);
4283 WARN("Could not search inherited interface!\n");
4285 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4286 return DISP_E_MEMBERNOTFOUND;
4289 /* ITypeInfo::GetDocumentation
4291 * Retrieves the documentation string, the complete Help file name and path,
4292 * and the context ID for the Help topic for a specified type description.
4294 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4295 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4296 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4298 ICOM_THIS( ITypeInfoImpl, iface);
4299 TLBFuncDesc * pFDesc;
4300 TLBVarDesc * pVDesc;
4301 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4302 " HelpContext(%p) HelpFile(%p)\n",
4303 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4304 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4306 *pBstrName=SysAllocString(This->Name);
4308 *pBstrDocString=SysAllocString(This->DocString);
4310 *pdwHelpContext=This->dwHelpContext;
4312 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4314 }else {/* for a member */
4315 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4316 if(pFDesc->funcdesc.memid==memid){
4318 *pBstrName = SysAllocString(pFDesc->Name);
4320 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4322 *pdwHelpContext=pFDesc->helpcontext;
4325 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4326 if(pVDesc->vardesc.memid==memid){
4327 FIXME("Not implemented\n");
4331 return TYPE_E_ELEMENTNOTFOUND;
4334 /* ITypeInfo::GetDllEntry
4336 * Retrieves a description or specification of an entry point for a function
4339 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4340 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4343 ICOM_THIS( ITypeInfoImpl, iface);
4344 FIXME("(%p) stub!\n", This);
4348 /* ITypeInfo::GetRefTypeInfo
4350 * If a type description references other type descriptions, it retrieves
4351 * the referenced type descriptions.
4353 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4356 ITypeInfo **ppTInfo)
4358 ICOM_THIS( ITypeInfoImpl, iface);
4359 HRESULT result = E_FAIL;
4362 if (hRefType == -1 &&
4363 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4364 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4366 /* when we meet a DUAL dispinterface, we must create the interface
4369 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4372 /* the interface version contains the same information as the dispinterface
4373 * copy the contents of the structs.
4375 *pTypeInfoImpl = *This;
4376 pTypeInfoImpl->ref = 1;
4378 /* change the type to interface */
4379 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4381 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4383 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4388 TLBRefType *pRefType;
4389 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4390 if(pRefType->reference == hRefType)
4394 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4395 if(pRefType && hRefType != -1) {
4396 ITypeLib *pTLib = NULL;
4398 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4400 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4402 if(pRefType->pImpTLInfo->pImpTypeLib) {
4403 TRACE("typeinfo in imported typelib that is already loaded\n");
4404 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4405 ITypeLib2_AddRef((ITypeLib*) pTLib);
4408 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4409 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4410 pRefType->pImpTLInfo->wVersionMajor,
4411 pRefType->pImpTLInfo->wVersionMinor,
4412 pRefType->pImpTLInfo->lcid,
4415 if(!SUCCEEDED(result)) {
4416 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4417 result=LoadTypeLib(libnam, &pTLib);
4418 SysFreeString(libnam);
4420 if(SUCCEEDED(result)) {
4421 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4422 ITypeLib2_AddRef(pTLib);
4426 if(SUCCEEDED(result)) {
4427 if(pRefType->index == TLB_REF_USE_GUID)
4428 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4432 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4436 ITypeLib2_Release(pTLib);
4440 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4441 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4445 /* ITypeInfo::AddressOfMember
4447 * Retrieves the addresses of static functions or variables, such as those
4450 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4451 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4453 ICOM_THIS( ITypeInfoImpl, iface);
4454 FIXME("(%p) stub!\n", This);
4458 /* ITypeInfo::CreateInstance
4460 * Creates a new instance of a type that describes a component object class
4463 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4464 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4466 ICOM_THIS( ITypeInfoImpl, iface);
4467 FIXME("(%p) stub!\n", This);
4471 /* ITypeInfo::GetMops
4473 * Retrieves marshaling information.
4475 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4478 ICOM_THIS( ITypeInfoImpl, iface);
4479 FIXME("(%p) stub!\n", This);
4483 /* ITypeInfo::GetContainingTypeLib
4485 * Retrieves the containing type library and the index of the type description
4486 * within that type library.
4488 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4489 ITypeLib * *ppTLib, UINT *pIndex)
4491 ICOM_THIS( ITypeInfoImpl, iface);
4493 return E_INVALIDARG;
4494 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4495 *pIndex=This->index;
4496 ITypeLib2_AddRef(*ppTLib);
4497 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4501 /* ITypeInfo::ReleaseTypeAttr
4503 * Releases a TYPEATTR previously returned by GetTypeAttr.
4506 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4507 TYPEATTR* pTypeAttr)
4509 ICOM_THIS( ITypeInfoImpl, iface);
4510 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4514 /* ITypeInfo::ReleaseFuncDesc
4516 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4518 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4520 FUNCDESC *pFuncDesc)
4522 ICOM_THIS( ITypeInfoImpl, iface);
4523 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4527 /* ITypeInfo::ReleaseVarDesc
4529 * Releases a VARDESC previously returned by GetVarDesc.
4531 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4534 ICOM_THIS( ITypeInfoImpl, iface);
4535 TRACE("(%p)->(%p)\n", This, pVarDesc);
4539 /* ITypeInfo2::GetTypeKind
4541 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4544 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4545 TYPEKIND *pTypeKind)
4547 ICOM_THIS( ITypeInfoImpl, iface);
4548 *pTypeKind=This->TypeAttr.typekind;
4549 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4553 /* ITypeInfo2::GetTypeFlags
4555 * Returns the type flags without any allocations. This returns a DWORD type
4556 * flag, which expands the type flags without growing the TYPEATTR (type
4560 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4563 ICOM_THIS( ITypeInfoImpl, iface);
4564 *pTypeFlags=This->TypeAttr.wTypeFlags;
4565 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4569 /* ITypeInfo2::GetFuncIndexOfMemId
4570 * Binds to a specific member based on a known DISPID, where the member name
4571 * is not known (for example, when binding to a default member).
4574 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4575 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4577 ICOM_THIS( ITypeInfoImpl, iface);
4578 TLBFuncDesc *pFuncInfo;
4581 /* FIXME: should check for invKind??? */
4582 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4583 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4589 result=E_INVALIDARG;
4591 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4592 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4596 /* TypeInfo2::GetVarIndexOfMemId
4598 * Binds to a specific member based on a known DISPID, where the member name
4599 * is not known (for example, when binding to a default member).
4602 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4603 MEMBERID memid, UINT *pVarIndex)
4605 ICOM_THIS( ITypeInfoImpl, iface);
4606 TLBVarDesc *pVarInfo;
4609 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4610 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4617 result=E_INVALIDARG;
4619 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4620 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4624 /* ITypeInfo2::GetCustData
4626 * Gets the custom data
4628 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4633 ICOM_THIS( ITypeInfoImpl, iface);
4634 TLBCustData *pCData;
4636 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4637 if( IsEqualIID(guid, &pCData->guid)) break;
4639 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4643 VariantInit( pVarVal);
4644 VariantCopy( pVarVal, &pCData->data);
4647 return E_INVALIDARG; /* FIXME: correct? */
4650 /* ITypeInfo2::GetFuncCustData
4652 * Gets the custom data
4654 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4660 ICOM_THIS( ITypeInfoImpl, iface);
4661 TLBCustData *pCData=NULL;
4662 TLBFuncDesc * pFDesc;
4664 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4665 pFDesc=pFDesc->next);
4668 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4669 if( IsEqualIID(guid, &pCData->guid)) break;
4671 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4674 VariantInit( pVarVal);
4675 VariantCopy( pVarVal, &pCData->data);
4678 return E_INVALIDARG; /* FIXME: correct? */
4681 /* ITypeInfo2::GetParamCustData
4683 * Gets the custom data
4685 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4692 ICOM_THIS( ITypeInfoImpl, iface);
4693 TLBCustData *pCData=NULL;
4694 TLBFuncDesc * pFDesc;
4697 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4699 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4700 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4701 pCData = pCData->next)
4702 if( IsEqualIID(guid, &pCData->guid)) break;
4704 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4708 VariantInit( pVarVal);
4709 VariantCopy( pVarVal, &pCData->data);
4712 return E_INVALIDARG; /* FIXME: correct? */
4715 /* ITypeInfo2::GetVarCustData
4717 * Gets the custom data
4719 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4725 ICOM_THIS( ITypeInfoImpl, iface);
4726 TLBCustData *pCData=NULL;
4727 TLBVarDesc * pVDesc;
4730 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4734 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4736 if( IsEqualIID(guid, &pCData->guid)) break;
4740 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4744 VariantInit( pVarVal);
4745 VariantCopy( pVarVal, &pCData->data);
4748 return E_INVALIDARG; /* FIXME: correct? */
4751 /* ITypeInfo2::GetImplCustData
4753 * Gets the custom data
4755 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4761 ICOM_THIS( ITypeInfoImpl, iface);
4762 TLBCustData *pCData=NULL;
4763 TLBImplType * pRDesc;
4766 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4770 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4772 if( IsEqualIID(guid, &pCData->guid)) break;
4776 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4780 VariantInit( pVarVal);
4781 VariantCopy( pVarVal, &pCData->data);
4784 return E_INVALIDARG; /* FIXME: correct? */
4787 /* ITypeInfo2::GetDocumentation2
4789 * Retrieves the documentation string, the complete Help file name and path,
4790 * the localization context to use, and the context ID for the library Help
4791 * topic in the Help file.
4794 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4798 BSTR *pbstrHelpString,
4799 DWORD *pdwHelpStringContext,
4800 BSTR *pbstrHelpStringDll)
4802 ICOM_THIS( ITypeInfoImpl, iface);
4803 TLBFuncDesc * pFDesc;
4804 TLBVarDesc * pVDesc;
4805 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4806 "HelpStringContext(%p) HelpStringDll(%p)\n",
4807 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4808 pbstrHelpStringDll );
4809 /* the help string should be obtained from the helpstringdll,
4810 * using the _DLLGetDocumentation function, based on the supplied
4811 * lcid. Nice to do sometime...
4813 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4815 *pbstrHelpString=SysAllocString(This->Name);
4816 if(pdwHelpStringContext)
4817 *pdwHelpStringContext=This->dwHelpStringContext;
4818 if(pbstrHelpStringDll)
4819 *pbstrHelpStringDll=
4820 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4822 }else {/* for a member */
4823 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4824 if(pFDesc->funcdesc.memid==memid){
4826 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4827 if(pdwHelpStringContext)
4828 *pdwHelpStringContext=pFDesc->HelpStringContext;
4829 if(pbstrHelpStringDll)
4830 *pbstrHelpStringDll=
4831 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4834 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4835 if(pVDesc->vardesc.memid==memid){
4837 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4838 if(pdwHelpStringContext)
4839 *pdwHelpStringContext=pVDesc->HelpStringContext;
4840 if(pbstrHelpStringDll)
4841 *pbstrHelpStringDll=
4842 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4846 return TYPE_E_ELEMENTNOTFOUND;
4849 /* ITypeInfo2::GetAllCustData
4851 * Gets all custom data items for the Type info.
4854 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4856 CUSTDATA *pCustData)
4858 ICOM_THIS( ITypeInfoImpl, iface);
4859 TLBCustData *pCData;
4862 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4864 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4865 if(pCustData->prgCustData ){
4866 pCustData->cCustData=This->ctCustData;
4867 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4868 pCustData->prgCustData[i].guid=pCData->guid;
4869 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4872 ERR(" OUT OF MEMORY! \n");
4873 return E_OUTOFMEMORY;
4878 /* ITypeInfo2::GetAllFuncCustData
4880 * Gets all custom data items for the specified Function
4883 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4886 CUSTDATA *pCustData)
4888 ICOM_THIS( ITypeInfoImpl, iface);
4889 TLBCustData *pCData;
4890 TLBFuncDesc * pFDesc;
4892 TRACE("(%p) index %d\n", This, index);
4893 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4894 pFDesc=pFDesc->next)
4897 pCustData->prgCustData =
4898 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4899 if(pCustData->prgCustData ){
4900 pCustData->cCustData=pFDesc->ctCustData;
4901 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4902 pCData = pCData->next){
4903 pCustData->prgCustData[i].guid=pCData->guid;
4904 VariantCopy(& pCustData->prgCustData[i].varValue,
4908 ERR(" OUT OF MEMORY! \n");
4909 return E_OUTOFMEMORY;
4913 return TYPE_E_ELEMENTNOTFOUND;
4916 /* ITypeInfo2::GetAllParamCustData
4918 * Gets all custom data items for the Functions
4921 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4922 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4924 ICOM_THIS( ITypeInfoImpl, iface);
4925 TLBCustData *pCData=NULL;
4926 TLBFuncDesc * pFDesc;
4928 TRACE("(%p) index %d\n", This, indexFunc);
4929 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4930 pFDesc=pFDesc->next)
4932 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4933 pCustData->prgCustData =
4934 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4935 sizeof(CUSTDATAITEM));
4936 if(pCustData->prgCustData ){
4937 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4938 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4939 pCData; i++, pCData = pCData->next){
4940 pCustData->prgCustData[i].guid=pCData->guid;
4941 VariantCopy(& pCustData->prgCustData[i].varValue,
4945 ERR(" OUT OF MEMORY! \n");
4946 return E_OUTOFMEMORY;
4950 return TYPE_E_ELEMENTNOTFOUND;
4953 /* ITypeInfo2::GetAllVarCustData
4955 * Gets all custom data items for the specified Variable
4958 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4959 UINT index, CUSTDATA *pCustData)
4961 ICOM_THIS( ITypeInfoImpl, iface);
4962 TLBCustData *pCData;
4963 TLBVarDesc * pVDesc;
4965 TRACE("(%p) index %d\n", This, index);
4966 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4967 pVDesc=pVDesc->next)
4970 pCustData->prgCustData =
4971 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4972 if(pCustData->prgCustData ){
4973 pCustData->cCustData=pVDesc->ctCustData;
4974 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4975 pCData = pCData->next){
4976 pCustData->prgCustData[i].guid=pCData->guid;
4977 VariantCopy(& pCustData->prgCustData[i].varValue,
4981 ERR(" OUT OF MEMORY! \n");
4982 return E_OUTOFMEMORY;
4986 return TYPE_E_ELEMENTNOTFOUND;
4989 /* ITypeInfo2::GetAllImplCustData
4991 * Gets all custom data items for the specified implementation type
4994 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4997 CUSTDATA *pCustData)
4999 ICOM_THIS( ITypeInfoImpl, iface);
5000 TLBCustData *pCData;
5001 TLBImplType * pRDesc;
5003 TRACE("(%p) index %d\n", This, index);
5004 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5005 pRDesc=pRDesc->next)
5008 pCustData->prgCustData =
5009 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5010 if(pCustData->prgCustData ){
5011 pCustData->cCustData=pRDesc->ctCustData;
5012 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5013 pCData = pCData->next){
5014 pCustData->prgCustData[i].guid=pCData->guid;
5015 VariantCopy(& pCustData->prgCustData[i].varValue,
5019 ERR(" OUT OF MEMORY! \n");
5020 return E_OUTOFMEMORY;
5024 return TYPE_E_ELEMENTNOTFOUND;
5027 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5029 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5031 ITypeInfo_fnQueryInterface,
5033 ITypeInfo_fnRelease,
5035 ITypeInfo_fnGetTypeAttr,
5036 ITypeInfo_fnGetTypeComp,
5037 ITypeInfo_fnGetFuncDesc,
5038 ITypeInfo_fnGetVarDesc,
5039 ITypeInfo_fnGetNames,
5040 ITypeInfo_fnGetRefTypeOfImplType,
5041 ITypeInfo_fnGetImplTypeFlags,
5042 ITypeInfo_fnGetIDsOfNames,
5044 ITypeInfo_fnGetDocumentation,
5045 ITypeInfo_fnGetDllEntry,
5046 ITypeInfo_fnGetRefTypeInfo,
5047 ITypeInfo_fnAddressOfMember,
5048 ITypeInfo_fnCreateInstance,
5049 ITypeInfo_fnGetMops,
5050 ITypeInfo_fnGetContainingTypeLib,
5051 ITypeInfo_fnReleaseTypeAttr,
5052 ITypeInfo_fnReleaseFuncDesc,
5053 ITypeInfo_fnReleaseVarDesc,
5055 ITypeInfo2_fnGetTypeKind,
5056 ITypeInfo2_fnGetTypeFlags,
5057 ITypeInfo2_fnGetFuncIndexOfMemId,
5058 ITypeInfo2_fnGetVarIndexOfMemId,
5059 ITypeInfo2_fnGetCustData,
5060 ITypeInfo2_fnGetFuncCustData,
5061 ITypeInfo2_fnGetParamCustData,
5062 ITypeInfo2_fnGetVarCustData,
5063 ITypeInfo2_fnGetImplTypeCustData,
5064 ITypeInfo2_fnGetDocumentation2,
5065 ITypeInfo2_fnGetAllCustData,
5066 ITypeInfo2_fnGetAllFuncCustData,
5067 ITypeInfo2_fnGetAllParamCustData,
5068 ITypeInfo2_fnGetAllVarCustData,
5069 ITypeInfo2_fnGetAllImplTypeCustData,