4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
63 #define NONAMELESSUNION
64 #define NONAMELESSSTRUCT
66 #include "winnls.h" /* for PRIMARYLANGID */
67 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
70 #include "wine/unicode.h"
75 #include "wine/debug.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib);
81 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
82 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
84 /****************************************************************************
87 * Takes p_iVal (which is in little endian) and returns it
88 * in the host machine's byte order.
90 #ifdef WORDS_BIGENDIAN
91 static WORD FromLEWord(WORD p_iVal)
93 return (((p_iVal & 0x00FF) << 8) |
94 ((p_iVal & 0xFF00) >> 8));
98 static DWORD FromLEDWord(DWORD p_iVal)
100 return (((p_iVal & 0x000000FF) << 24) |
101 ((p_iVal & 0x0000FF00) << 8) |
102 ((p_iVal & 0x00FF0000) >> 8) |
103 ((p_iVal & 0xFF000000) >> 24));
106 #define FromLEWord(X) (X)
107 #define FromLEDWord(X) (X)
111 /****************************************************************************
114 * Fix byte order in any structure if necessary
116 #ifdef WORDS_BIGENDIAN
117 static void FromLEWords(void *p_Val, int p_iSize)
121 p_iSize /= sizeof(WORD);
124 *Val = FromLEWord(*Val);
131 static void FromLEDWords(void *p_Val, int p_iSize)
135 p_iSize /= sizeof(DWORD);
138 *Val = FromLEDWord(*Val);
144 #define FromLEWords(X,Y) /*nothing*/
145 #define FromLEDWords(X,Y) /*nothing*/
149 /****************************************************************************
150 * QueryPathOfRegTypeLib [OLEAUT32.164]
155 QueryPathOfRegTypeLib(
156 REFGUID guid, /* [in] referenced guid */
157 WORD wMaj, /* [in] major version */
158 WORD wMin, /* [in] minor version */
159 LCID lcid, /* [in] locale id */
160 LPBSTR path ) /* [out] path of typelib */
162 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
163 string termination character on output strings */
170 char szTypeLibKey[100];
171 char szPath[MAX_PATH];
172 DWORD dwPathLen = sizeof(szPath);
180 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
186 sprintf(szTypeLibKey,
187 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
188 guid->Data1, guid->Data2, guid->Data3,
189 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
190 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
195 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
199 else if (myLCID == lcid)
201 /* try with sub-langid */
202 myLCID = SUBLANGID(lcid);
204 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
206 /* try with system langid */
216 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
217 BSTR bstrPath = SysAllocStringLen(NULL,len);
219 MultiByteToWideChar(CP_ACP,
231 TRACE_(typelib)("%s not found\n", szTypeLibKey);
236 /******************************************************************************
237 * CreateTypeLib [OLEAUT32.160] creates a typelib
243 HRESULT WINAPI CreateTypeLib(
244 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
246 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
249 /******************************************************************************
250 * LoadTypeLib [OLEAUT32.161]
251 * Loads and registers a type library
253 * Docs: OLECHAR FAR* szFile
254 * Docs: iTypeLib FAR* FAR* pptLib
260 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
262 HRESULT WINAPI LoadTypeLib(
263 const OLECHAR *szFile,/* [in] Name of file to load from */
264 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
267 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
270 /******************************************************************************
271 * LoadTypeLibEx [OLEAUT32.183]
272 * Loads and optionally registers a type library
278 HRESULT WINAPI LoadTypeLibEx(
279 LPCOLESTR szFile, /* [in] Name of file to load from */
280 REGKIND regkind, /* [in] Specify kind of registration */
281 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
283 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
288 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
289 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
292 /* Look for a trailing '\\' followed by an index */
293 pIndexStr = strrchrW(szFile, '\\');
294 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
295 index = atoiW(pIndexStr);
296 memcpy(szFileCopy, szFile,
297 (pIndexStr - szFile - 1) * sizeof(WCHAR));
298 szFileCopy[pIndexStr - szFile - 1] = '\0';
299 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
301 return TYPE_E_CANTLOADLIBRARY;
302 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
303 return TYPE_E_CANTLOADLIBRARY;
306 WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
309 lstrcpyW(tstpath,szFile);
311 for (i=0;i<strlenW(tstpath);i++) {
312 if (tstpath[i] == 's') {
313 if (!strcmpW(tstpath+i,stdole32tlb)) {
315 MESSAGE("**************************************************************************\n");
316 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
317 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
318 MESSAGE("on the Microsoft Download Pages.\n");
319 MESSAGE("**************************************************************************\n");
324 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
325 return TYPE_E_CANTLOADLIBRARY;
329 TRACE("File %s index %d\n", debugstr_w(szPath), index);
331 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
336 case REGKIND_DEFAULT:
337 /* FIXME: is this correct? */
338 if (!szFile || !szFile[0] ||
339 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
341 /* else fall-through */
342 case REGKIND_REGISTER:
343 /* FIXME: Help path? */
344 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
346 IUnknown_Release(*pptLib);
354 TRACE(" returns %08lx\n",res);
358 /******************************************************************************
359 * LoadRegTypeLib [OLEAUT32.162]
361 HRESULT WINAPI LoadRegTypeLib(
362 REFGUID rguid, /* [in] referenced guid */
363 WORD wVerMajor, /* [in] major version */
364 WORD wVerMinor, /* [in] minor version */
365 LCID lcid, /* [in] locale id */
366 ITypeLib **ppTLib) /* [out] path of typelib */
369 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
373 res= LoadTypeLib(bstr, ppTLib);
377 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
383 /******************************************************************************
384 * RegisterTypeLib [OLEAUT32.163]
385 * Adds information about a type library to the System Registry
387 * Docs: ITypeLib FAR * ptlib
388 * Docs: OLECHAR FAR* szFullPath
389 * Docs: OLECHAR FAR* szHelpDir
395 HRESULT WINAPI RegisterTypeLib(
396 ITypeLib * ptlib, /* [in] Pointer to the library*/
397 OLECHAR * szFullPath, /* [in] full Path of the library*/
398 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
409 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
411 if (ptlib == NULL || szFullPath == NULL)
414 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
417 StringFromGUID2(&attr->guid, guid, 80);
418 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
419 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
420 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
421 HeapFree(GetProcessHeap(), 0, guidA);
424 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
425 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
429 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
431 if (RegSetValueExW(key, NULL, 0, REG_SZ,
432 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
440 /* FIXME: This *seems* to be 0 always, not sure though */
441 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
442 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
444 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
445 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
453 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
454 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
457 /* FIXME: is %u correct? */
458 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
459 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
460 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
468 /* register OLE Automation-compatible interfaces for this typelib */
469 types = ITypeLib_GetTypeInfoCount(ptlib);
470 for (tidx=0; tidx<types; tidx++) {
471 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
472 LPOLESTR name = NULL;
473 ITypeInfo *tinfo = NULL;
475 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
477 case TKIND_INTERFACE:
478 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
479 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
482 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
483 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
486 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
487 /* coclasses should probably not be registered? */
490 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
494 TYPEATTR *tattr = NULL;
495 ITypeInfo_GetTypeAttr(tinfo, &tattr);
497 TRACE_(typelib)("guid=%s, flags=%04x (",
498 debugstr_guid(&tattr->guid),
500 if (TRACE_ON(typelib)) {
501 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
521 * FIXME: The 1 is just here until we implement rpcrt4
522 * stub/proxy handling. Until then it helps IShield
525 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
527 /* register interface<->typelib coupling */
528 StringFromGUID2(&tattr->guid, guid, 80);
529 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
530 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
531 HeapFree(GetProcessHeap(), 0, guidA);
533 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
534 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
536 RegSetValueExW(key, NULL, 0, REG_SZ,
537 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
539 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
540 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
541 RegSetValueExA(subKey, NULL, 0, REG_SZ,
545 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
546 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
547 RegSetValueExA(subKey, NULL, 0, REG_SZ,
552 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
553 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
555 StringFromGUID2(&attr->guid, guid, 80);
556 snprintf(ver, sizeof(ver), "%x.%x",
557 attr->wMajorVerNum, attr->wMinorVerNum);
558 RegSetValueExW(subKey, NULL, 0, REG_SZ,
559 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
560 RegSetValueExA(subKey, "Version", 0, REG_SZ,
567 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
569 ITypeInfo_Release(tinfo);
576 ITypeLib_ReleaseTLibAttr(ptlib, attr);
582 /******************************************************************************
583 * UnRegisterTypeLib [OLEAUT32.186]
584 * Removes information about a type library from the System Registry
591 HRESULT WINAPI UnRegisterTypeLib(
592 REFGUID libid, /* [in] Guid of the library */
593 WORD wVerMajor, /* [in] major version */
594 WORD wVerMinor, /* [in] minor version */
595 LCID lcid, /* [in] locale id */
598 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
599 return S_OK; /* FIXME: pretend everything is OK */
602 /*======================= ITypeLib implementation =======================*/
604 typedef struct tagTLBCustData
608 struct tagTLBCustData* next;
611 /* data structure for import typelibs */
612 typedef struct tagTLBImpLib
614 int offset; /* offset in the file (MSFT)
615 offset in nametable (SLTG)
616 just used to identify library while reading
618 GUID guid; /* libid */
619 BSTR name; /* name */
621 LCID lcid; /* lcid of imported typelib */
623 WORD wVersionMajor; /* major version number */
624 WORD wVersionMinor; /* minor version number */
626 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
627 NULL if not yet loaded */
628 struct tagTLBImpLib * next;
631 /* internal ITypeLib data */
632 typedef struct tagITypeLibImpl
634 ICOM_VFIELD(ITypeLib2);
635 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
637 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
639 /* strings can be stored in tlb as multibyte strings BUT they are *always*
640 * exported to the application as a UNICODE string.
646 unsigned long dwHelpContext;
647 int TypeInfoCount; /* nr of typeinfo's in librarry */
648 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
649 int ctCustData; /* number of items in cust data list */
650 TLBCustData * pCustData; /* linked list to cust data */
651 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
652 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
653 libary. Only used while read MSFT
657 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
658 static struct ICOM_VTABLE(ITypeComp) tlbtcvt;
660 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
661 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
663 /* ITypeLib methods */
664 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
665 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
667 /*======================= ITypeInfo implementation =======================*/
669 /* data for refernced types */
670 typedef struct tagTLBRefType
672 INT index; /* Type index for internal ref or for external ref
673 it the format is SLTG. -2 indicates to
676 GUID guid; /* guid of the referenced type */
677 /* if index == TLB_REF_USE_GUID */
679 HREFTYPE reference; /* The href of this ref */
680 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
681 TLB_REF_INTERNAL for internal refs
682 TLB_REF_NOT_FOUND for broken refs */
684 struct tagTLBRefType * next;
687 #define TLB_REF_USE_GUID -2
689 #define TLB_REF_INTERNAL (void*)-2
690 #define TLB_REF_NOT_FOUND (void*)-1
692 /* internal Parameter data */
693 typedef struct tagTLBParDesc
697 TLBCustData * pCustData; /* linked list to cust data */
700 /* internal Function data */
701 typedef struct tagTLBFuncDesc
703 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
704 BSTR Name; /* the name of this function */
705 TLBParDesc *pParamDesc; /* array with param names and custom data */
707 int HelpStringContext;
709 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
711 TLBCustData * pCustData; /* linked list to cust data; */
712 struct tagTLBFuncDesc * next;
715 /* internal Variable data */
716 typedef struct tagTLBVarDesc
718 VARDESC vardesc; /* lots of info on the variable and its attributes. */
719 BSTR Name; /* the name of this variable */
721 int HelpStringContext; /* FIXME: where? */
724 TLBCustData * pCustData;/* linked list to cust data; */
725 struct tagTLBVarDesc * next;
728 /* internal implemented interface data */
729 typedef struct tagTLBImplType
731 HREFTYPE hRef; /* hRef of interface */
732 int implflags; /* IMPLFLAG_*s */
734 TLBCustData * pCustData;/* linked list to custom data; */
735 struct tagTLBImplType *next;
738 /* internal TypeInfo data */
739 typedef struct tagITypeInfoImpl
741 ICOM_VFIELD(ITypeInfo2);
742 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
744 TYPEATTR TypeAttr ; /* _lots_ of type information. */
745 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
746 int index; /* index in this typelib; */
747 /* type libs seem to store the doc strings in ascii
748 * so why should we do it in unicode?
752 unsigned long dwHelpContext;
753 unsigned long dwHelpStringContext;
756 TLBFuncDesc * funclist; /* linked list with function descriptions */
759 TLBVarDesc * varlist; /* linked list with variable descriptions */
761 /* Implemented Interfaces */
762 TLBImplType * impltypelist;
764 TLBRefType * reflist;
766 TLBCustData * pCustData; /* linked list to cust data; */
767 struct tagITypeInfoImpl * next;
770 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
771 static struct ICOM_VTABLE(ITypeComp) tcompvt;
773 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
775 typedef struct tagTLBContext
777 unsigned int oStart; /* start of TLB in file */
778 unsigned int pos; /* current pos */
779 unsigned int length; /* total length */
780 void *mapping; /* memory mapping */
781 MSFT_SegDir * pTblDir;
782 ITypeLibImpl* pLibInfo;
786 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
791 static void dump_VarType(VARTYPE vt,char *szVarType) {
792 /* FIXME : we could have better trace here, depending on the VARTYPE
795 if (vt & VT_RESERVED)
796 szVarType += strlen(strcpy(szVarType, "reserved | "));
798 szVarType += strlen(strcpy(szVarType, "ref to "));
800 szVarType += strlen(strcpy(szVarType, "array of "));
802 szVarType += strlen(strcpy(szVarType, "vector of "));
803 switch(vt & VT_TYPEMASK) {
804 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
805 case VT_I2: sprintf(szVarType, "VT_I2"); break;
806 case VT_I4: sprintf(szVarType, "VT_I4"); break;
807 case VT_R4: sprintf(szVarType, "VT_R4"); break;
808 case VT_R8: sprintf(szVarType, "VT_R8"); break;
809 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
810 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
811 case VT_CY: sprintf(szVarType, "VT_CY"); break;
812 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
813 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
814 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
815 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
816 case VT_I1: sprintf(szVarType, "VT_I1"); break;
817 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
818 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
819 case VT_INT: sprintf(szVarType, "VT_INT"); break;
820 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
821 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
822 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
823 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
824 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
828 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
829 if (pTD->vt & VT_RESERVED)
830 szVarType += strlen(strcpy(szVarType, "reserved | "));
831 if (pTD->vt & VT_BYREF)
832 szVarType += strlen(strcpy(szVarType, "ref to "));
833 if (pTD->vt & VT_ARRAY)
834 szVarType += strlen(strcpy(szVarType, "array of "));
835 if (pTD->vt & VT_VECTOR)
836 szVarType += strlen(strcpy(szVarType, "vector of "));
837 switch(pTD->vt & VT_TYPEMASK) {
838 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
839 case VT_I2: sprintf(szVarType, "VT_I2"); break;
840 case VT_I4: sprintf(szVarType, "VT_I4"); break;
841 case VT_R4: sprintf(szVarType, "VT_R4"); break;
842 case VT_R8: sprintf(szVarType, "VT_R8"); break;
843 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
844 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
845 case VT_CY: sprintf(szVarType, "VT_CY"); break;
846 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
847 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
848 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
849 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
850 case VT_I1: sprintf(szVarType, "VT_I1"); break;
851 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
852 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
853 case VT_INT: sprintf(szVarType, "VT_INT"); break;
854 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
855 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
856 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
857 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
858 pTD->u.hreftype); break;
859 case VT_PTR: sprintf(szVarType, "ptr to ");
860 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
862 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
863 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
865 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
866 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
867 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
870 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
874 void dump_ELEMDESC(ELEMDESC *edesc) {
876 dump_TypeDesc(&edesc->tdesc,buf);
877 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
878 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
879 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
881 void dump_FUNCDESC(FUNCDESC *funcdesc) {
883 MESSAGE("memid is %08lx\n",funcdesc->memid);
884 for (i=0;i<funcdesc->cParams;i++) {
885 MESSAGE("Param %d:\n",i);
886 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
888 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
889 switch (funcdesc->funckind) {
890 case FUNC_VIRTUAL: MESSAGE("virtual");break;
891 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
892 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
893 case FUNC_STATIC: MESSAGE("static");break;
894 case FUNC_DISPATCH: MESSAGE("dispatch");break;
895 default: MESSAGE("unknown");break;
897 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
898 switch (funcdesc->invkind) {
899 case INVOKE_FUNC: MESSAGE("func");break;
900 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
901 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
902 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
904 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
905 switch (funcdesc->callconv) {
906 case CC_CDECL: MESSAGE("cdecl");break;
907 case CC_PASCAL: MESSAGE("pascal");break;
908 case CC_STDCALL: MESSAGE("stdcall");break;
909 case CC_SYSCALL: MESSAGE("syscall");break;
912 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
913 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
914 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
917 void dump_IDLDESC(IDLDESC *idl) {
918 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
921 static char * typekind_desc[] =
934 void dump_TYPEATTR(TYPEATTR *tattr) {
936 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
937 MESSAGE("\tlcid: %ld\n",tattr->lcid);
938 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
939 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
940 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
941 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
942 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
943 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
944 MESSAGE("\tcVars: %d\n", tattr->cVars);
945 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
946 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
947 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
948 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
949 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
950 dump_TypeDesc(&tattr->tdescAlias,buf);
951 MESSAGE("\ttypedesc: %s\n", buf);
952 dump_IDLDESC(&tattr->idldescType);
955 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
958 if (!TRACE_ON(typelib))
960 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
961 for (i=0;i<pfd->funcdesc.cParams;i++)
962 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
965 dump_FUNCDESC(&(pfd->funcdesc));
967 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
968 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
970 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
974 dump_TLBFuncDescOne(pfd);
978 static void dump_TLBVarDesc(TLBVarDesc * pvd)
982 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
987 static void dump_TLBImpLib(TLBImpLib *import)
989 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
990 debugstr_w(import->name));
991 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
992 import->wVersionMinor, import->lcid, import->offset);
995 static void dump_TLBRefType(TLBRefType * prt)
999 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1000 if(prt->index == -1)
1001 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1003 TRACE_(typelib)("type no: %d\n", prt->index);
1005 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1006 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1007 TRACE_(typelib)("in lib\n");
1008 dump_TLBImpLib(prt->pImpTLInfo);
1014 static void dump_TLBImplType(TLBImplType * impl)
1018 "implementing/inheriting interface hRef = %lx implflags %x\n",
1019 impl->hRef, impl->implflags);
1024 void dump_Variant(VARIANT * pvar)
1029 TRACE("(%p)\n", pvar);
1033 ZeroMemory(szVarType, sizeof(szVarType));
1035 /* FIXME : we could have better trace here, depending on the VARTYPE
1038 dump_VarType(V_VT(pvar),szVarType);
1040 TRACE("VARTYPE: %s\n", szVarType);
1042 if (V_VT(pvar) & VT_BYREF) {
1043 ref = V_UNION(pvar, byref);
1046 else ref = &V_UNION(pvar, cVal);
1048 if (V_VT(pvar) & VT_ARRAY) {
1052 if (V_VT(pvar) & VT_VECTOR) {
1057 switch (V_VT(pvar) & VT_TYPEMASK)
1060 TRACE("%d\n", *(short*)ref);
1065 TRACE("%u\n", *(UINT*)ref);
1070 TRACE("%d\n", *(INT*)ref);
1074 TRACE("%3.3e\n", *(float*)ref);
1078 TRACE("%3.3e\n", *(double*)ref);
1082 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1086 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1091 TRACE("%p\n", *(LPVOID*)ref);
1095 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1101 memset( &TM, 0, sizeof(TM) );
1103 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1104 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1106 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1107 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1108 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1114 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1119 TRACE("(?)%ld\n", *(long*)ref);
1124 static void dump_DispParms(DISPPARAMS * pdp)
1128 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1130 while (index < pdp->cArgs)
1132 dump_Variant( &pdp->rgvarg[index] );
1137 static void dump_TypeInfo(ITypeInfoImpl * pty)
1139 TRACE("%p ref=%u\n", pty, pty->ref);
1140 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1141 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1142 TRACE("fct:%u var:%u impl:%u\n",
1143 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1144 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1145 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1146 dump_TLBFuncDesc(pty->funclist);
1147 dump_TLBVarDesc(pty->varlist);
1148 dump_TLBImplType(pty->impltypelist);
1151 void dump_VARDESC(VARDESC *v)
1153 MESSAGE("memid %ld\n",v->memid);
1154 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1155 MESSAGE("oInst %ld\n",v->u.oInst);
1156 dump_ELEMDESC(&(v->elemdescVar));
1157 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1158 MESSAGE("varkind %d\n",v->varkind);
1161 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1163 /* VT_LPWSTR is largest type that */
1164 /* may appear in type description*/
1165 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1166 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1167 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1168 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1169 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1170 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1174 static void TLB_abort()
1178 static void * TLB_Alloc(unsigned size)
1181 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1183 ERR("cannot allocate memory\n");
1188 static void TLB_Free(void * ptr)
1190 HeapFree(GetProcessHeap(), 0, ptr);
1194 /**********************************************************************
1196 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1199 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1201 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1202 pcx->pos, count, pcx->oStart, pcx->length, where);
1204 if (where != DO_NOT_SEEK)
1206 where += pcx->oStart;
1207 if (where > pcx->length)
1210 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1215 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1216 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1221 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1226 ret = MSFT_Read(buffer, count, pcx, where);
1227 FromLEDWords(buffer, ret);
1232 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1237 ret = MSFT_Read(buffer, count, pcx, where);
1238 FromLEWords(buffer, ret);
1243 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1245 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1246 memset(pGuid,0, sizeof(GUID));
1249 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1250 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1251 pGuid->Data2 = FromLEWord(pGuid->Data2);
1252 pGuid->Data3 = FromLEWord(pGuid->Data3);
1253 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1256 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1259 MSFT_NameIntro niName;
1261 WCHAR* pwstring = NULL;
1262 BSTR bstrName = NULL;
1264 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1265 pcx->pTblDir->pNametab.offset+offset);
1266 niName.namelen &= 0xFF; /* FIXME: correct ? */
1267 name=TLB_Alloc((niName.namelen & 0xff) +1);
1268 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1269 name[niName.namelen & 0xff]='\0';
1271 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1274 /* no invalid characters in string */
1277 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1279 /* don't check for invalid character since this has been done previously */
1280 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1282 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1283 lengthInChars = SysStringLen(bstrName);
1284 HeapFree(GetProcessHeap(), 0, pwstring);
1287 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1291 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1298 if(offset<0) return NULL;
1299 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1300 if(length <= 0) return 0;
1301 string=TLB_Alloc(length +1);
1302 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1303 string[length]='\0';
1305 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1306 string, -1, NULL, 0);
1308 /* no invalid characters in string */
1311 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1313 /* don't check for invalid character since this has been done previously */
1314 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1316 bstr = SysAllocStringLen(pwstring, lengthInChars);
1317 lengthInChars = SysStringLen(bstr);
1318 HeapFree(GetProcessHeap(), 0, pwstring);
1321 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1325 * read a value and fill a VARIANT structure
1327 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1331 TRACE_(typelib)("\n");
1333 if(offset <0) { /* data are packed in here */
1334 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1335 V_UNION(pVar, iVal) = offset & 0xffff;
1338 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1339 pcx->pTblDir->pCustData.offset + offset );
1340 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1341 switch (V_VT(pVar)){
1342 case VT_EMPTY: /* FIXME: is this right? */
1343 case VT_NULL: /* FIXME: is this right? */
1344 case VT_I2 : /* this should not happen */
1355 case VT_VOID : /* FIXME: is this right? */
1363 case VT_DECIMAL : /* FIXME: is this right? */
1366 /* pointer types with known behaviour */
1369 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1371 FIXME("BSTR length = %d?\n", size);
1373 ptr=TLB_Alloc(size);/* allocate temp buffer */
1374 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1375 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1376 /* FIXME: do we need a AtoW conversion here? */
1377 V_UNION(pVar, bstrVal[size])=L'\0';
1378 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1383 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1390 case VT_USERDEFINED :
1396 case VT_STREAMED_OBJECT :
1397 case VT_STORED_OBJECT :
1398 case VT_BLOB_OBJECT :
1403 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1407 if(size>0) /* (big|small) endian correct? */
1408 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1412 * create a linked list with custom data
1414 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1420 TRACE_(typelib)("\n");
1424 pNew=TLB_Alloc(sizeof(TLBCustData));
1425 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1426 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1427 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1428 /* add new custom data at head of the list */
1429 pNew->next=*ppCustData;
1431 offset = entry.next;
1436 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1440 pTd->vt=type & VT_TYPEMASK;
1442 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1444 if(pTd->vt == VT_USERDEFINED)
1445 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1447 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1451 MSFT_DoFuncs(TLBContext* pcx,
1456 TLBFuncDesc** pptfd)
1459 * member information is stored in a data structure at offset
1460 * indicated by the memoffset field of the typeinfo structure
1461 * There are several distinctive parts.
1462 * the first part starts with a field that holds the total length
1463 * of this (first) part excluding this field. Then follow the records,
1464 * for each member there is one record.
1466 * First entry is always the length of the record (excluding this
1468 * Rest of the record depends on the type of the member. If there is
1469 * a field indicating the member type (function variable intereface etc)
1470 * I have not found it yet. At this time we depend on the information
1471 * in the type info and the usual order how things are stored.
1473 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1476 * Third is a equal sized array with file offsets to the name entry
1479 * Forth and last (?) part is an array with offsets to the records in the
1480 * first part of this file segment.
1483 int infolen, nameoffset, reclength, nrattributes, i;
1484 int recoffset = offset + sizeof(INT);
1487 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1489 TRACE_(typelib)("\n");
1491 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1493 for ( i = 0; i < cFuncs ; i++ )
1495 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1497 /* name, eventually add to a hash table */
1498 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1499 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1501 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1503 /* read the function information record */
1504 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1508 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1510 /* do the attributes */
1511 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1514 if ( nrattributes > 0 )
1516 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1518 if ( nrattributes > 1 )
1520 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1521 pFuncRec->OptAttr[1]) ;
1523 if ( nrattributes > 2 )
1525 if ( pFuncRec->FKCCIC & 0x2000 )
1527 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1531 (*pptfd)->Entry = MSFT_ReadString(pcx,
1532 pFuncRec->OptAttr[2]);
1534 if( nrattributes > 5 )
1536 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1538 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1541 pFuncRec->OptAttr[6],
1542 &(*pptfd)->pCustData);
1549 /* fill the FuncDesc Structure */
1550 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1551 offset + infolen + ( i + 1) * sizeof(INT));
1553 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1554 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1555 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1556 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1557 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1558 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1559 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1563 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1566 /* do the parameters/arguments */
1567 if(pFuncRec->nrargs)
1570 MSFT_ParameterInfo paraminfo;
1572 (*pptfd)->funcdesc.lprgelemdescParam =
1573 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1575 (*pptfd)->pParamDesc =
1576 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1578 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1579 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1581 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1583 TYPEDESC* lpArgTypeDesc = 0;
1587 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1590 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1592 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1594 /* SEEK value = jump to offset,
1595 * from there jump to the end of record,
1596 * go back by (j-1) arguments
1598 MSFT_ReadLEDWords( ¶minfo ,
1599 sizeof(MSFT_ParameterInfo), pcx,
1600 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1601 * sizeof(MSFT_ParameterInfo)));
1603 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1605 while ( lpArgTypeDesc != NULL )
1607 switch ( lpArgTypeDesc->vt )
1610 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1614 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1617 case VT_USERDEFINED:
1618 MSFT_DoRefType(pcx, pTI,
1619 lpArgTypeDesc->u.hreftype);
1621 lpArgTypeDesc = NULL;
1625 lpArgTypeDesc = NULL;
1631 /* parameter is the return value! */
1632 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1634 TYPEDESC* lpArgTypeDesc;
1636 (*pptfd)->funcdesc.elemdescFunc =
1637 (*pptfd)->funcdesc.lprgelemdescParam[j];
1639 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1641 while ( lpArgTypeDesc != NULL )
1643 switch ( lpArgTypeDesc->vt )
1646 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1650 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1654 case VT_USERDEFINED:
1657 lpArgTypeDesc->u.hreftype);
1659 lpArgTypeDesc = NULL;
1663 lpArgTypeDesc = NULL;
1668 /* second time around */
1669 for(j=0;j<pFuncRec->nrargs;j++)
1672 (*pptfd)->pParamDesc[j].Name =
1673 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1676 if ( (PARAMFLAG_FHASDEFAULT &
1677 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1678 ((pFuncRec->FKCCIC) & 0x1000) )
1680 INT* pInt = (INT *)((char *)pFuncRec +
1682 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1684 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1686 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1687 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1689 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1693 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1696 pFuncRec->OptAttr[7+j],
1697 &(*pptfd)->pParamDesc[j].pCustData);
1702 /* scode is not used: archaic win16 stuff FIXME: right? */
1703 (*pptfd)->funcdesc.cScodes = 0 ;
1704 (*pptfd)->funcdesc.lprgscode = NULL ;
1706 pptfd = & ((*pptfd)->next);
1707 recoffset += reclength;
1710 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1711 int cVars, int offset, TLBVarDesc ** pptvd)
1713 int infolen, nameoffset, reclength;
1715 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1719 TRACE_(typelib)("\n");
1721 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1722 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1723 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1724 recoffset += offset+sizeof(INT);
1725 for(i=0;i<cVars;i++){
1726 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1727 /* name, eventually add to a hash table */
1728 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1729 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1730 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1731 /* read the variable information record */
1732 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1734 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1736 if(reclength >(6*sizeof(INT)) )
1737 (*pptvd)->HelpContext=pVarRec->HelpContext;
1738 if(reclength >(7*sizeof(INT)) )
1739 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1740 if(reclength >(8*sizeof(INT)) )
1741 if(reclength >(9*sizeof(INT)) )
1742 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1743 /* fill the VarDesc Structure */
1744 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1745 offset + infolen + ( i + 1) * sizeof(INT));
1746 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1747 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1748 MSFT_GetTdesc(pcx, pVarRec->DataType,
1749 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1750 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1751 if(pVarRec->VarKind == VAR_CONST ){
1752 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1753 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1754 pVarRec->OffsValue, pcx);
1756 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1757 pptvd=&((*pptvd)->next);
1758 recoffset += reclength;
1761 /* fill in data for a hreftype (offset). When the refernced type is contained
1762 * in the typelib, it's just an (file) offset in the type info base dir.
1763 * If comes from import, it's an offset+1 in the ImpInfo table
1765 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1769 TLBRefType **ppRefType = &pTI->reflist;
1771 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1774 if((*ppRefType)->reference == offset)
1776 ppRefType = &(*ppRefType)->next;
1779 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1780 sizeof(**ppRefType));
1782 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1783 /* external typelib */
1784 MSFT_ImpInfo impinfo;
1785 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1787 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1789 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1790 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1791 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1792 if(pImpLib->offset==impinfo.oImpFile) break;
1793 pImpLib=pImpLib->next;
1796 (*ppRefType)->reference=offset;
1797 (*ppRefType)->pImpTLInfo = pImpLib;
1798 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1799 (*ppRefType)->index = TLB_REF_USE_GUID;
1801 ERR("Cannot find a reference\n");
1802 (*ppRefType)->reference=-1;
1803 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1806 /* in this typelib */
1807 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1808 (*ppRefType)->reference=offset;
1809 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1813 /* process Implemented Interfaces of a com class */
1814 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1818 MSFT_RefRecord refrec;
1819 TLBImplType **ppImpl = &pTI->impltypelist;
1821 TRACE_(typelib)("\n");
1823 for(i=0;i<count;i++){
1824 if(offset<0) break; /* paranoia */
1825 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1826 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1827 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1828 (*ppImpl)->hRef = refrec.reftype;
1829 (*ppImpl)->implflags=refrec.flags;
1830 (*ppImpl)->ctCustData=
1831 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1832 offset=refrec.onext;
1833 ppImpl=&((*ppImpl)->next);
1837 * process a typeinfo record
1839 ITypeInfoImpl * MSFT_DoTypeInfo(
1842 ITypeLibImpl * pLibInfo)
1844 MSFT_TypeInfoBase tiBase;
1845 ITypeInfoImpl *ptiRet;
1847 TRACE_(typelib)("count=%u\n", count);
1849 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1850 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1851 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1852 /* this is where we are coming from */
1853 ptiRet->pTypeLib = pLibInfo;
1854 ptiRet->index=count;
1855 /* fill in the typeattr fields */
1856 WARN("Assign constructor/destructor memid\n");
1858 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1859 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1860 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1861 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1862 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1863 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1864 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1865 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1866 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1867 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1868 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1869 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1870 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1871 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1872 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1873 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1874 MSFT_GetTdesc(pcx, tiBase.datatype1,
1875 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1878 /* IDLDESC idldescType; *//* never saw this one != zero */
1880 /* name, eventually add to a hash table */
1881 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1882 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1884 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1885 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1886 ptiRet->dwHelpContext=tiBase.helpcontext;
1887 /* note: InfoType's Help file and HelpStringDll come from the containing
1888 * library. Further HelpString and Docstring appear to be the same thing :(
1891 if(ptiRet->TypeAttr.cFuncs >0 )
1892 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1893 ptiRet->TypeAttr.cVars,
1894 tiBase.memoffset, & ptiRet->funclist);
1896 if(ptiRet->TypeAttr.cVars >0 )
1897 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1898 ptiRet->TypeAttr.cVars,
1899 tiBase.memoffset, & ptiRet->varlist);
1900 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1901 switch(ptiRet->TypeAttr.typekind)
1904 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1907 case TKIND_DISPATCH:
1908 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1910 if (tiBase.datatype1 != -1)
1912 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1913 ptiRet->impltypelist->hRef = tiBase.datatype1;
1916 { /* FIXME: This is a really bad hack to add IDispatch */
1917 char* szStdOle = "stdole2.tlb\0";
1918 int nStdOleLen = strlen(szStdOle);
1919 TLBRefType **ppRef = &ptiRet->reflist;
1922 if((*ppRef)->reference == -1)
1924 ppRef = &(*ppRef)->next;
1927 *ppRef = TLB_Alloc(sizeof(**ppRef));
1928 (*ppRef)->guid = IID_IDispatch;
1929 (*ppRef)->reference = -1;
1930 (*ppRef)->index = TLB_REF_USE_GUID;
1931 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1932 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1933 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1936 MultiByteToWideChar(CP_ACP,
1940 (*ppRef)->pImpTLInfo->name,
1941 SysStringLen((*ppRef)->pImpTLInfo->name));
1943 (*ppRef)->pImpTLInfo->lcid = 0;
1944 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1945 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1950 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1951 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1952 ptiRet->impltypelist->hRef = tiBase.datatype1;
1957 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1959 TRACE_(typelib)("%s guid: %s kind:%s\n",
1960 debugstr_w(ptiRet->Name),
1961 debugstr_guid(&ptiRet->TypeAttr.guid),
1962 typekind_desc[ptiRet->TypeAttr.typekind]);
1967 /****************************************************************************
1970 * find the type of the typelib file and map the typelib resource into
1973 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1974 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1975 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1977 int ret = TYPE_E_CANTLOADLIBRARY;
1978 DWORD dwSignature = 0;
1981 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1985 /* check the signature of the file */
1986 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1987 if (INVALID_HANDLE_VALUE != hFile)
1989 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1992 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1995 /* retrieve file size */
1996 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1998 /* first try to load as *.tlb */
1999 dwSignature = FromLEDWord(*((DWORD*) pBase));
2000 if ( dwSignature == MSFT_SIGNATURE)
2002 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2004 else if ( dwSignature == SLTG_SIGNATURE)
2006 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2008 UnmapViewOfFile(pBase);
2010 CloseHandle(hMapping);
2015 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2017 /* find the typelibrary resource*/
2018 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2019 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2022 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2026 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2029 LPVOID pBase = LockResource(hGlobal);
2030 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2034 /* try to load as incore resource */
2035 dwSignature = FromLEDWord(*((DWORD*) pBase));
2036 if ( dwSignature == MSFT_SIGNATURE)
2038 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2040 else if ( dwSignature == SLTG_SIGNATURE)
2042 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2046 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2049 FreeResource( hGlobal );
2052 FreeLibrary(hinstDLL);
2059 ERR("Loading of typelib %s failed with error %ld\n",
2060 debugstr_w(pszFileName), GetLastError());
2065 /*================== ITypeLib(2) Methods ===================================*/
2067 /****************************************************************************
2068 * ITypeLib2_Constructor_MSFT
2070 * loading an MSFT typelib from an in-memory image
2072 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2076 MSFT_Header tlbHeader;
2077 MSFT_SegDir tlbSegDir;
2078 ITypeLibImpl * pTypeLibImpl;
2080 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2082 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2083 if (!pTypeLibImpl) return NULL;
2085 pTypeLibImpl->lpVtbl = &tlbvt;
2086 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2087 pTypeLibImpl->ref = 1;
2089 /* get pointer to beginning of typelib data */
2093 cx.pLibInfo = pTypeLibImpl;
2094 cx.length = dwTLBLength;
2097 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2099 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2100 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2101 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2104 /* there is a small amount of information here until the next important
2106 * the segment directory . Try to calculate the amount of data */
2107 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2109 /* now read the segment directory */
2110 TRACE("read segment directory (at %ld)\n",lPSegDir);
2111 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2112 cx.pTblDir = &tlbSegDir;
2114 /* just check two entries */
2115 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2117 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2118 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2122 /* now fill our internal data */
2123 /* TLIBATTR fields */
2124 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2126 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2127 /* Windows seems to have zero here, is this correct? */
2128 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2129 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2131 pTypeLibImpl->LibAttr.lcid = 0;
2133 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2134 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2135 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2136 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2138 /* name, eventually add to a hash table */
2139 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2142 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2143 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2145 if( tlbHeader.varflags & HELPDLLFLAG)
2148 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2149 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2152 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2155 if(tlbHeader.CustomDataOffset >= 0)
2157 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2160 /* fill in typedescriptions */
2161 if(tlbSegDir.pTypdescTab.length > 0)
2163 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2165 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2166 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2169 /* FIXME: add several sanity checks here */
2170 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2171 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2173 /* FIXME: check safearray */
2175 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2177 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2179 else if(td[0] == VT_CARRAY)
2181 /* array descr table here */
2182 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2184 else if(td[0] == VT_USERDEFINED)
2186 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2188 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2191 /* second time around to fill the array subscript info */
2194 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2195 if(tlbSegDir.pArrayDescriptions.offset>0)
2197 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2198 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2201 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2203 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2205 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2207 for(j = 0; j<td[2]; j++)
2209 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2210 sizeof(INT), &cx, DO_NOT_SEEK);
2211 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2212 sizeof(INT), &cx, DO_NOT_SEEK);
2217 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2218 ERR("didn't find array description data\n");
2223 /* imported type libs */
2224 if(tlbSegDir.pImpFiles.offset>0)
2226 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2227 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2230 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2232 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2233 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2234 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2236 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2237 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2238 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2239 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2242 (*ppImpLib)->name = TLB_Alloc(size+1);
2243 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2244 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2245 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2247 ppImpLib = &(*ppImpLib)->next;
2252 if(tlbHeader.nrtypeinfos >= 0 )
2254 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2255 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2258 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2260 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2262 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2263 ppTI = &((*ppTI)->next);
2264 (pTypeLibImpl->TypeInfoCount)++;
2268 TRACE("(%p)\n", pTypeLibImpl);
2269 return (ITypeLib2*) pTypeLibImpl;
2273 static BSTR TLB_MultiByteToBSTR(char *ptr)
2279 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2280 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2281 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2282 ret = SysAllocString(nameW);
2283 HeapFree(GetProcessHeap(), 0, nameW);
2287 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2293 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2294 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2298 guid->Data4[0] = s >> 8;
2299 guid->Data4[1] = s & 0xff;
2302 for(i = 0; i < 6; i++) {
2303 memcpy(b, str + 24 + 2 * i, 2);
2304 guid->Data4[i + 2] = strtol(b, NULL, 16);
2309 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2316 bytelen = *(WORD*)ptr;
2317 if(bytelen == 0xffff) return 2;
2318 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2319 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2320 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2321 *pBstr = SysAllocStringLen(nameW, len);
2322 HeapFree(GetProcessHeap(), 0, nameW);
2326 static WORD SLTG_ReadStringA(char *ptr, char **str)
2331 bytelen = *(WORD*)ptr;
2332 if(bytelen == 0xffff) return 2;
2333 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2334 memcpy(*str, ptr + 2, bytelen);
2335 (*str)[bytelen] = '\0';
2339 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2341 char *ptr = pLibBlk;
2344 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2345 FIXME("libblk magic = %04x\n", w);
2350 if((w = *(WORD*)ptr) != 0xffff) {
2351 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2356 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2358 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2360 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2363 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2366 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2369 ptr += 4; /* skip res12 */
2371 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2374 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2377 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2380 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2381 ptr += sizeof(GUID);
2383 return ptr - (char*)pLibBlk;
2386 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2389 TYPEDESC *pTD = &pElem->tdesc;
2391 /* Handle [in/out] first */
2392 if((*pType & 0xc000) == 0xc000)
2393 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2394 else if(*pType & 0x8000)
2395 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2396 else if(*pType & 0x4000)
2397 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2399 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2402 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2405 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2408 if((*pType & 0xe00) == 0xe00) {
2410 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2412 pTD = pTD->u.lptdesc;
2414 switch(*pType & 0x7f) {
2417 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2419 pTD = pTD->u.lptdesc;
2422 case VT_USERDEFINED:
2423 pTD->vt = VT_USERDEFINED;
2424 pTD->u.hreftype = *(++pType) / 4;
2430 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2433 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2435 pTD->vt = VT_CARRAY;
2436 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2438 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2439 pTD->u.lpadesc->cDims = pSA->cDims;
2440 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2441 pSA->cDims * sizeof(SAFEARRAYBOUND));
2443 pTD = &pTD->u.lpadesc->tdescElem;
2449 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2453 pTD->vt = VT_SAFEARRAY;
2454 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2456 pTD = pTD->u.lptdesc;
2460 pTD->vt = *pType & 0x7f;
2470 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2475 TLBRefType **ppRefType;
2477 if(pRef->magic != SLTG_REF_MAGIC) {
2478 FIXME("Ref magic = %x\n", pRef->magic);
2481 name = ( (char*)(&pRef->names) + pRef->number);
2483 ppRefType = &pTI->reflist;
2484 for(ref = 0; ref < pRef->number >> 3; ref++) {
2486 unsigned int lib_offs, type_num;
2488 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2489 sizeof(**ppRefType));
2491 name += SLTG_ReadStringA(name, &refname);
2492 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2493 FIXME("Can't sscanf ref\n");
2494 if(lib_offs != 0xffff) {
2495 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2498 if((*import)->offset == lib_offs)
2500 import = &(*import)->next;
2503 char fname[MAX_PATH+1];
2506 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2508 (*import)->offset = lib_offs;
2509 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2511 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2512 &(*import)->wVersionMajor,
2513 &(*import)->wVersionMinor,
2514 &(*import)->lcid, fname) != 4) {
2515 FIXME("can't sscanf ref %s\n",
2516 pNameTable + lib_offs + 40);
2518 len = strlen(fname);
2519 if(fname[len-1] != '#')
2520 FIXME("fname = %s\n", fname);
2521 fname[len-1] = '\0';
2522 (*import)->name = TLB_MultiByteToBSTR(fname);
2524 (*ppRefType)->pImpTLInfo = *import;
2525 } else { /* internal ref */
2526 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2528 (*ppRefType)->reference = ref;
2529 (*ppRefType)->index = type_num;
2531 HeapFree(GetProcessHeap(), 0, refname);
2532 ppRefType = &(*ppRefType)->next;
2534 if((BYTE)*name != SLTG_REF_MAGIC)
2535 FIXME("End of ref block magic = %x\n", *name);
2536 dump_TLBRefType(pTI->reflist);
2539 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2542 SLTG_ImplInfo *info;
2543 TLBImplType **ppImplType = &pTI->impltypelist;
2544 /* I don't really get this structure, usually it's 0x16 bytes
2545 long, but iuser.tlb contains some that are 0x18 bytes long.
2546 That's ok because we can use the next ptr to jump to the next
2547 one. But how do we know the length of the last one? The WORD
2548 at offs 0x8 might be the clue. For now I'm just assuming that
2549 the last one is the regular 0x16 bytes. */
2551 info = (SLTG_ImplInfo*)pBlk;
2553 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2554 sizeof(**ppImplType));
2555 (*ppImplType)->hRef = info->ref;
2556 (*ppImplType)->implflags = info->impltypeflags;
2557 pTI->TypeAttr.cImplTypes++;
2558 ppImplType = &(*ppImplType)->next;
2560 if(info->next == 0xffff)
2563 FIXME("Interface inheriting more than one interface\n");
2564 info = (SLTG_ImplInfo*)(pBlk + info->next);
2566 info++; /* see comment at top of function */
2570 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2573 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2574 SLTG_MemberHeader *pMemHeader;
2575 char *pFirstItem, *pNextItem;
2577 if(pTIHeader->href_table != 0xffffffff) {
2578 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2583 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2585 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2587 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2588 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2591 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2595 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2598 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2599 SLTG_MemberHeader *pMemHeader;
2600 SLTG_Function *pFunc;
2601 char *pFirstItem, *pNextItem;
2602 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2605 if(pTIHeader->href_table != 0xffffffff) {
2606 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2610 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2612 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2614 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2615 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2618 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2619 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2624 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2625 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2626 FIXME("func magic = %02x\n", pFunc->magic);
2629 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2630 sizeof(**ppFuncDesc));
2631 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2633 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2634 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2635 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2636 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2637 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2638 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2640 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2641 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2643 if(pFunc->retnextopt & 0x80)
2644 pType = &pFunc->rettype;
2646 pType = (WORD*)(pFirstItem + pFunc->rettype);
2649 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2651 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2652 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2653 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2654 (*ppFuncDesc)->pParamDesc =
2655 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2656 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2658 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2660 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2661 char *paramName = pNameTable + *pArg;
2663 /* If arg type follows then paramName points to the 2nd
2664 letter of the name, else the next WORD is an offset to
2665 the arg type and paramName points to the first letter.
2666 So let's take one char off paramName and see if we're
2667 pointing at an alpha-numeric char. However if *pArg is
2668 0xffff or 0xfffe then the param has no name, the former
2669 meaning that the next WORD is the type, the latter
2670 meaning the the next WORD is an offset to the type. */
2675 else if(*pArg == 0xfffe) {
2679 else if(!isalnum(*(paramName-1)))
2684 if(HaveOffs) { /* the next word is an offset to type */
2685 pType = (WORD*)(pFirstItem + *pArg);
2686 SLTG_DoType(pType, pFirstItem,
2687 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2692 pArg = SLTG_DoType(pArg, pFirstItem,
2693 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2696 /* Are we an optional param ? */
2697 if((*ppFuncDesc)->funcdesc.cParams - param <=
2698 (*ppFuncDesc)->funcdesc.cParamsOpt)
2699 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2702 (*ppFuncDesc)->pParamDesc[param].Name =
2703 TLB_MultiByteToBSTR(paramName);
2707 ppFuncDesc = &((*ppFuncDesc)->next);
2708 if(pFunc->next == 0xffff) break;
2710 pTI->TypeAttr.cFuncs = num;
2711 dump_TLBFuncDesc(pTI->funclist);
2712 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2715 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2718 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2719 SLTG_MemberHeader *pMemHeader;
2720 SLTG_RecordItem *pItem;
2722 TLBVarDesc **ppVarDesc = &pTI->varlist;
2727 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2729 pFirstItem = (char*)(pMemHeader + 1);
2730 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2731 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2732 if(pItem->magic != SLTG_RECORD_MAGIC) {
2733 FIXME("record magic = %02x\n", pItem->magic);
2736 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2737 sizeof(**ppVarDesc));
2738 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2739 (*ppVarDesc)->vardesc.memid = pItem->memid;
2740 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2741 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2743 if(pItem->typepos == 0x02)
2744 pType = &pItem->type;
2745 else if(pItem->typepos == 0x00)
2746 pType = (WORD*)(pFirstItem + pItem->type);
2748 FIXME("typepos = %02x\n", pItem->typepos);
2752 SLTG_DoType(pType, pFirstItem,
2753 &(*ppVarDesc)->vardesc.elemdescVar);
2755 /* FIXME("helpcontext, helpstring\n"); */
2757 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2759 ppVarDesc = &((*ppVarDesc)->next);
2760 if(pItem->next == 0xffff) break;
2762 pTI->TypeAttr.cVars = num;
2763 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2766 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2769 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2770 SLTG_MemberHeader *pMemHeader;
2771 SLTG_AliasItem *pItem;
2774 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2775 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2778 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2779 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2780 if (pItem->vt == 0xffff) {
2781 if (i<(pMemHeader->cbExtra/4-1))
2782 FIXME("Endmarker too early in process alias data!\n");
2786 FIXME("Chain extends over last entry?\n");
2789 if (pItem->vt == VT_USERDEFINED) {
2790 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2791 /* guessing here ... */
2792 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2793 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2796 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2797 FIXME("alias %d: 0x%x\n",i,pItem->res02);
2801 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2804 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
2807 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2808 SLTG_MemberHeader *pMemHeader;
2809 SLTG_AliasItem *pItem;
2811 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2812 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2813 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
2814 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
2815 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2818 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2821 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2822 SLTG_MemberHeader *pMemHeader;
2823 SLTG_EnumItem *pItem;
2825 TLBVarDesc **ppVarDesc = &pTI->varlist;
2828 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2830 pFirstItem = (char*)(pMemHeader + 1);
2831 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2832 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2833 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2834 FIXME("enumitem magic = %04x\n", pItem->magic);
2837 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2838 sizeof(**ppVarDesc));
2839 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2840 (*ppVarDesc)->vardesc.memid = pItem->memid;
2841 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2843 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2844 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2845 *(INT*)(pItem->value + pFirstItem);
2846 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2847 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2848 /* FIXME("helpcontext, helpstring\n"); */
2850 ppVarDesc = &((*ppVarDesc)->next);
2851 if(pItem->next == 0xffff) break;
2853 pTI->TypeAttr.cVars = num;
2854 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2857 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2858 managable copy of it into this */
2871 } SLTG_InternalOtherTypeInfo;
2873 /****************************************************************************
2874 * ITypeLib2_Constructor_SLTG
2876 * loading a SLTG typelib from an in-memory image
2878 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2880 ITypeLibImpl *pTypeLibImpl;
2881 SLTG_Header *pHeader;
2882 SLTG_BlkEntry *pBlkEntry;
2886 LPVOID pBlk, pFirstBlk;
2887 SLTG_LibBlk *pLibBlk;
2888 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2889 char *pAfterOTIBlks = NULL;
2890 char *pNameTable, *ptr;
2893 ITypeInfoImpl **ppTypeInfoImpl;
2895 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2897 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2898 if (!pTypeLibImpl) return NULL;
2900 pTypeLibImpl->lpVtbl = &tlbvt;
2901 pTypeLibImpl->ref = 1;
2906 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2907 pHeader->nrOfFileBlks );
2908 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2909 FIXME("Header type magic 0x%08lx not supported.\n",
2910 pHeader->SLTG_magic);
2914 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2915 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2917 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2918 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2920 /* Next we have a magic block */
2921 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2923 /* Let's see if we're still in sync */
2924 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2925 sizeof(SLTG_COMPOBJ_MAGIC))) {
2926 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2929 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2930 sizeof(SLTG_DIR_MAGIC))) {
2931 FIXME("dir magic = %s\n", pMagic->dir_magic);
2935 pIndex = (SLTG_Index*)(pMagic+1);
2937 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2939 pFirstBlk = (LPVOID)(pPad9 + 1);
2941 /* We'll set up a ptr to the main library block, which is the last one. */
2943 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2944 pBlkEntry[order].next != 0;
2945 order = pBlkEntry[order].next - 1, i++) {
2946 pBlk = (char*)pBlk + pBlkEntry[order].len;
2950 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2952 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2957 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2959 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2960 sizeof(*pOtherTypeInfoBlks) *
2961 pTypeLibImpl->TypeInfoCount);
2964 ptr = (char*)pLibBlk + len;
2966 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2970 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2972 w = *(WORD*)(ptr + 2);
2975 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2977 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2978 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2980 w = *(WORD*)(ptr + 4 + len);
2982 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2984 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2986 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2987 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2989 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2990 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2991 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2993 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2995 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2998 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2999 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3000 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3001 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3002 len += sizeof(SLTG_OtherTypeInfo);
3006 pAfterOTIBlks = ptr;
3008 /* Skip this WORD and get the next DWORD */
3009 len = *(DWORD*)(pAfterOTIBlks + 2);
3011 /* Now add this to pLibBLk look at what we're pointing at and
3012 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3013 dust and we should be pointing at the beginning of the name
3016 pNameTable = (char*)pLibBlk + len;
3018 switch(*(WORD*)pNameTable) {
3025 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3029 pNameTable += 0x216;
3033 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3035 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3038 /* Hopefully we now have enough ptrs set up to actually read in
3039 some TypeInfos. It's not clear which order to do them in, so
3040 I'll just follow the links along the BlkEntry chain and read
3041 them in in the order in which they're in the file */
3043 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3045 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3046 pBlkEntry[order].next != 0;
3047 order = pBlkEntry[order].next - 1, i++) {
3049 SLTG_TypeInfoHeader *pTIHeader;
3050 SLTG_TypeInfoTail *pTITail;
3052 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3053 pOtherTypeInfoBlks[i].index_name)) {
3054 FIXME("Index strings don't match\n");
3059 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3060 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3063 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3064 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3065 (*ppTypeInfoImpl)->index = i;
3066 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3067 pOtherTypeInfoBlks[i].name_offs +
3069 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3070 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3072 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3073 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3074 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3075 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3076 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3078 if((pTIHeader->typeflags1 & 7) != 2)
3079 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3080 if(pTIHeader->typeflags3 != 2)
3081 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3083 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3084 debugstr_w((*ppTypeInfoImpl)->Name),
3085 typekind_desc[pTIHeader->typekind],
3086 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3087 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3089 switch(pTIHeader->typekind) {
3091 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3095 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3098 case TKIND_INTERFACE:
3099 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3103 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3107 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3108 if (pTITail->tdescalias_vt)
3109 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3112 case TKIND_DISPATCH:
3113 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3117 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3123 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3124 but we've already set those */
3125 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3126 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3127 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3129 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3151 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3152 pBlk = (char*)pBlk + pBlkEntry[order].len;
3155 if(i != pTypeLibImpl->TypeInfoCount) {
3156 FIXME("Somehow processed %d TypeInfos\n", i);
3160 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3161 return (ITypeLib2*)pTypeLibImpl;
3164 /* ITypeLib::QueryInterface
3166 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3171 ICOM_THIS( ITypeLibImpl, iface);
3173 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3176 if(IsEqualIID(riid, &IID_IUnknown) ||
3177 IsEqualIID(riid,&IID_ITypeLib)||
3178 IsEqualIID(riid,&IID_ITypeLib2))
3185 ITypeLib2_AddRef(iface);
3186 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3189 TRACE("-- Interface: E_NOINTERFACE\n");
3190 return E_NOINTERFACE;
3195 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3197 ICOM_THIS( ITypeLibImpl, iface);
3199 TRACE("(%p)->ref is %u\n",This, This->ref);
3201 return ++(This->ref);
3204 /* ITypeLib::Release
3206 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3208 ICOM_THIS( ITypeLibImpl, iface);
3212 TRACE("(%p)->(%u)\n",This, This->ref);
3216 /* FIXME destroy child objects */
3218 TRACE(" destroying ITypeLib(%p)\n",This);
3222 SysFreeString(This->Name);
3226 if (This->DocString)
3228 SysFreeString(This->DocString);
3229 This->DocString = NULL;
3234 SysFreeString(This->HelpFile);
3235 This->HelpFile = NULL;
3238 if (This->HelpStringDll)
3240 SysFreeString(This->HelpStringDll);
3241 This->HelpStringDll = NULL;
3244 if (This->pTypeInfo) /* can be NULL */
3245 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3246 HeapFree(GetProcessHeap(),0,This);
3253 /* ITypeLib::GetTypeInfoCount
3255 * Returns the number of type descriptions in the type library
3257 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3259 ICOM_THIS( ITypeLibImpl, iface);
3260 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3261 return This->TypeInfoCount;
3264 /* ITypeLib::GetTypeInfo
3266 * retrieves the specified type description in the library.
3268 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3271 ITypeInfo **ppTInfo)
3275 ICOM_THIS( ITypeLibImpl, iface);
3276 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3278 TRACE("(%p)->(index=%d) \n", This, index);
3280 if (!ppTInfo) return E_INVALIDARG;
3282 /* search element n in list */
3283 for(i=0; i < index; i++)
3285 pTypeInfo = pTypeInfo->next;
3288 TRACE("-- element not found\n");
3289 return TYPE_E_ELEMENTNOTFOUND;
3293 *ppTInfo = (ITypeInfo *) pTypeInfo;
3295 ITypeInfo_AddRef(*ppTInfo);
3296 TRACE("-- found (%p)\n",*ppTInfo);
3301 /* ITypeLibs::GetTypeInfoType
3303 * Retrieves the type of a type description.
3305 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3310 ICOM_THIS( ITypeLibImpl, iface);
3312 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3314 TRACE("(%p) index %d \n",This, index);
3316 if(!pTKind) return E_INVALIDARG;
3318 /* search element n in list */
3319 for(i=0; i < index; i++)
3323 TRACE("-- element not found\n");
3324 return TYPE_E_ELEMENTNOTFOUND;
3326 pTInfo = pTInfo->next;
3329 *pTKind = pTInfo->TypeAttr.typekind;
3330 TRACE("-- found Type (%d)\n", *pTKind);
3334 /* ITypeLib::GetTypeInfoOfGuid
3336 * Retrieves the type description that corresponds to the specified GUID.
3339 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3342 ITypeInfo **ppTInfo)
3344 ICOM_THIS( ITypeLibImpl, iface);
3345 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3347 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3349 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3351 /* search linked list for guid */
3352 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3354 pTypeInfo = pTypeInfo->next;
3358 /* end of list reached */
3359 TRACE("-- element not found\n");
3360 return TYPE_E_ELEMENTNOTFOUND;
3364 TRACE("-- found (%p, %s)\n",
3366 debugstr_w(pTypeInfo->Name));
3368 *ppTInfo = (ITypeInfo*)pTypeInfo;
3369 ITypeInfo_AddRef(*ppTInfo);
3373 /* ITypeLib::GetLibAttr
3375 * Retrieves the structure that contains the library's attributes.
3378 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3380 LPTLIBATTR *ppTLibAttr)
3382 ICOM_THIS( ITypeLibImpl, iface);
3383 TRACE("(%p)\n",This);
3384 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3385 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3389 /* ITypeLib::GetTypeComp
3391 * Enables a client compiler to bind to a library's types, variables,
3392 * constants, and global functions.
3395 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3397 ITypeComp **ppTComp)
3399 ICOM_THIS( ITypeLibImpl, iface);
3401 TRACE("(%p)->(%p)\n",This,ppTComp);
3402 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3403 ITypeComp_AddRef(*ppTComp);
3408 /* ITypeLib::GetDocumentation
3410 * Retrieves the library's documentation string, the complete Help file name
3411 * and path, and the context identifier for the library Help topic in the Help
3414 * On a successful return all non-null BSTR pointers will have been set,
3417 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3421 BSTR *pBstrDocString,
3422 DWORD *pdwHelpContext,
3423 BSTR *pBstrHelpFile)
3425 ICOM_THIS( ITypeLibImpl, iface);
3427 HRESULT result = E_INVALIDARG;
3432 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3434 pBstrName, pBstrDocString,
3435 pdwHelpContext, pBstrHelpFile);
3439 /* documentation for the typelib */
3443 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3449 if (This->DocString)
3450 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3451 else if (This->Name)
3452 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3454 *pBstrDocString = NULL;
3458 *pdwHelpContext = This->dwHelpContext;
3463 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3465 *pBstrHelpFile = NULL;
3472 /* for a typeinfo */
3473 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3475 if(SUCCEEDED(result))
3477 result = ITypeInfo_GetDocumentation(pTInfo,
3481 pdwHelpContext, pBstrHelpFile);
3483 ITypeInfo_Release(pTInfo);
3488 if (pBstrDocString) SysFreeString (*pBstrDocString);
3490 if (pBstrName) SysFreeString (*pBstrName);
3492 return STG_E_INSUFFICIENTMEMORY;
3497 * Indicates whether a passed-in string contains the name of a type or member
3498 * described in the library.
3501 static HRESULT WINAPI ITypeLib2_fnIsName(
3507 ICOM_THIS( ITypeLibImpl, iface);
3508 ITypeInfoImpl *pTInfo;
3509 TLBFuncDesc *pFInfo;
3512 UINT nNameBufLen = SysStringLen(szNameBuf);
3514 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3518 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3519 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3520 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3521 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3522 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3523 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3524 goto ITypeLib2_fnIsName_exit;
3526 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3527 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3532 ITypeLib2_fnIsName_exit:
3533 TRACE("(%p)slow! search for %s: %s found!\n", This,
3534 debugstr_w(szNameBuf), *pfName?"NOT":"");
3539 /* ITypeLib::FindName
3541 * Finds occurrences of a type description in a type library. This may be used
3542 * to quickly verify that a name exists in a type library.
3545 static HRESULT WINAPI ITypeLib2_fnFindName(
3549 ITypeInfo **ppTInfo,
3553 ICOM_THIS( ITypeLibImpl, iface);
3554 ITypeInfoImpl *pTInfo;
3555 TLBFuncDesc *pFInfo;
3559 UINT nNameBufLen = SysStringLen(szNameBuf);
3561 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3562 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3563 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3564 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3565 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3566 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3567 goto ITypeLib2_fnFindName_exit;
3569 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3570 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3572 ITypeLib2_fnFindName_exit:
3573 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3574 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3577 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3578 This, *pcFound, debugstr_w(szNameBuf), j);
3585 /* ITypeLib::ReleaseTLibAttr
3587 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3590 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3592 TLIBATTR *pTLibAttr)
3594 ICOM_THIS( ITypeLibImpl, iface);
3595 TRACE("freeing (%p)\n",This);
3596 HeapFree(GetProcessHeap(),0,pTLibAttr);
3600 /* ITypeLib2::GetCustData
3602 * gets the custom data
3604 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3609 ICOM_THIS( ITypeLibImpl, iface);
3610 TLBCustData *pCData;
3612 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3614 if( IsEqualIID(guid, &pCData->guid)) break;
3617 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3621 VariantInit( pVarVal);
3622 VariantCopy( pVarVal, &pCData->data);
3625 return E_INVALIDARG; /* FIXME: correct? */
3628 /* ITypeLib2::GetLibStatistics
3630 * Returns statistics about a type library that are required for efficient
3631 * sizing of hash tables.
3634 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3636 ULONG *pcUniqueNames,
3637 ULONG *pcchUniqueNames)
3639 ICOM_THIS( ITypeLibImpl, iface);
3641 FIXME("(%p): stub!\n", This);
3643 if(pcUniqueNames) *pcUniqueNames=1;
3644 if(pcchUniqueNames) *pcchUniqueNames=1;
3648 /* ITypeLib2::GetDocumentation2
3650 * Retrieves the library's documentation string, the complete Help file name
3651 * and path, the localization context to use, and the context ID for the
3652 * library Help topic in the Help file.
3655 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3659 BSTR *pbstrHelpString,
3660 DWORD *pdwHelpStringContext,
3661 BSTR *pbstrHelpStringDll)
3663 ICOM_THIS( ITypeLibImpl, iface);
3667 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3669 /* the help string should be obtained from the helpstringdll,
3670 * using the _DLLGetDocumentation function, based on the supplied
3671 * lcid. Nice to do sometime...
3675 /* documentation for the typelib */
3677 *pbstrHelpString=SysAllocString(This->DocString);
3678 if(pdwHelpStringContext)
3679 *pdwHelpStringContext=This->dwHelpContext;
3680 if(pbstrHelpStringDll)
3681 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3687 /* for a typeinfo */
3688 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3690 if(SUCCEEDED(result))
3692 ITypeInfo2 * pTInfo2;
3693 result = ITypeInfo_QueryInterface(pTInfo,
3695 (LPVOID*) &pTInfo2);
3697 if(SUCCEEDED(result))
3699 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3703 pdwHelpStringContext,
3704 pbstrHelpStringDll);
3706 ITypeInfo2_Release(pTInfo2);
3709 ITypeInfo_Release(pTInfo);
3715 /* ITypeLib2::GetAllCustData
3717 * Gets all custom data items for the library.
3720 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3722 CUSTDATA *pCustData)
3724 ICOM_THIS( ITypeLibImpl, iface);
3725 TLBCustData *pCData;
3727 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3728 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3729 if(pCustData->prgCustData ){
3730 pCustData->cCustData=This->ctCustData;
3731 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3732 pCustData->prgCustData[i].guid=pCData->guid;
3733 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3736 ERR(" OUT OF MEMORY! \n");
3737 return E_OUTOFMEMORY;
3742 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3743 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3744 ITypeLib2_fnQueryInterface,
3746 ITypeLib2_fnRelease,
3747 ITypeLib2_fnGetTypeInfoCount,
3748 ITypeLib2_fnGetTypeInfo,
3749 ITypeLib2_fnGetTypeInfoType,
3750 ITypeLib2_fnGetTypeInfoOfGuid,
3751 ITypeLib2_fnGetLibAttr,
3752 ITypeLib2_fnGetTypeComp,
3753 ITypeLib2_fnGetDocumentation,
3755 ITypeLib2_fnFindName,
3756 ITypeLib2_fnReleaseTLibAttr,
3758 ITypeLib2_fnGetCustData,
3759 ITypeLib2_fnGetLibStatistics,
3760 ITypeLib2_fnGetDocumentation2,
3761 ITypeLib2_fnGetAllCustData
3765 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3767 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3769 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3772 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3774 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3776 return ITypeInfo_AddRef((ITypeInfo *)This);
3779 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3781 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3783 return ITypeInfo_Release((ITypeInfo *)This);
3786 static HRESULT WINAPI ITypeLibComp_fnBind(
3789 unsigned long lHash,
3790 unsigned short wFlags,
3791 ITypeInfo ** ppTInfo,
3792 DESCKIND * pDescKind,
3795 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
3799 static HRESULT WINAPI ITypeLibComp_fnBindType(
3802 unsigned long lHash,
3803 ITypeInfo ** ppTInfo,
3804 ITypeComp ** ppTComp)
3806 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
3810 static ICOM_VTABLE(ITypeComp) tlbtcvt =
3812 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3814 ITypeLibComp_fnQueryInterface,
3815 ITypeLibComp_fnAddRef,
3816 ITypeLibComp_fnRelease,
3818 ITypeLibComp_fnBind,
3819 ITypeLibComp_fnBindType
3822 /*================== ITypeInfo(2) Methods ===================================*/
3823 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3825 ITypeInfoImpl * pTypeInfoImpl;
3827 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3830 pTypeInfoImpl->lpVtbl = &tinfvt;
3831 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
3832 pTypeInfoImpl->ref=1;
3834 TRACE("(%p)\n", pTypeInfoImpl);
3835 return (ITypeInfo2*) pTypeInfoImpl;
3838 /* ITypeInfo::QueryInterface
3840 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3845 ICOM_THIS( ITypeLibImpl, iface);
3847 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3850 if(IsEqualIID(riid, &IID_IUnknown) ||
3851 IsEqualIID(riid,&IID_ITypeInfo)||
3852 IsEqualIID(riid,&IID_ITypeInfo2))
3856 ITypeInfo_AddRef(iface);
3857 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3860 TRACE("-- Interface: E_NOINTERFACE\n");
3861 return E_NOINTERFACE;
3864 /* ITypeInfo::AddRef
3866 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3868 ICOM_THIS( ITypeInfoImpl, iface);
3872 TRACE("(%p)->ref is %u\n",This, This->ref);
3876 /* ITypeInfo::Release
3878 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3880 ICOM_THIS( ITypeInfoImpl, iface);
3884 TRACE("(%p)->(%u)\n",This, This->ref);
3888 FIXME("destroy child objects\n");
3890 TRACE("destroying ITypeInfo(%p)\n",This);
3893 SysFreeString(This->Name);
3897 if (This->DocString)
3899 SysFreeString(This->DocString);
3900 This->DocString = 0;
3905 ITypeInfo_Release((ITypeInfo*)This->next);
3908 HeapFree(GetProcessHeap(),0,This);
3914 /* ITypeInfo::GetTypeAttr
3916 * Retrieves a TYPEATTR structure that contains the attributes of the type
3920 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3921 LPTYPEATTR *ppTypeAttr)
3923 ICOM_THIS( ITypeInfoImpl, iface);
3924 TRACE("(%p)\n",This);
3925 /* FIXME: must do a copy here */
3926 *ppTypeAttr=&This->TypeAttr;
3930 /* ITypeInfo::GetTypeComp
3932 * Retrieves the ITypeComp interface for the type description, which enables a
3933 * client compiler to bind to the type description's members.
3936 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3937 ITypeComp * *ppTComp)
3939 ICOM_THIS( ITypeInfoImpl, iface);
3941 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
3943 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3944 ITypeComp_AddRef(*ppTComp);
3948 /* ITypeInfo::GetFuncDesc
3950 * Retrieves the FUNCDESC structure that contains information about a
3951 * specified function.
3954 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3955 LPFUNCDESC *ppFuncDesc)
3957 ICOM_THIS( ITypeInfoImpl, iface);
3959 TLBFuncDesc * pFDesc;
3960 TRACE("(%p) index %d\n", This, index);
3961 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3964 /* FIXME: must do a copy here */
3965 *ppFuncDesc=&pFDesc->funcdesc;
3968 return E_INVALIDARG;
3971 /* ITypeInfo::GetVarDesc
3973 * Retrieves a VARDESC structure that describes the specified variable.
3976 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3977 LPVARDESC *ppVarDesc)
3979 ICOM_THIS( ITypeInfoImpl, iface);
3981 TLBVarDesc * pVDesc;
3982 TRACE("(%p) index %d\n", This, index);
3983 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3986 /* FIXME: must do a copy here */
3987 *ppVarDesc=&pVDesc->vardesc;
3990 return E_INVALIDARG;
3993 /* ITypeInfo_GetNames
3995 * Retrieves the variable with the specified member ID (or the name of the
3996 * property or method and its parameters) that correspond to the specified
3999 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4000 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4002 ICOM_THIS( ITypeInfoImpl, iface);
4003 TLBFuncDesc * pFDesc;
4004 TLBVarDesc * pVDesc;
4006 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4007 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4010 /* function found, now return function and parameter names */
4011 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4014 *rgBstrNames=SysAllocString(pFDesc->Name);
4016 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4022 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4025 *rgBstrNames=SysAllocString(pVDesc->Name);
4030 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
4032 /* recursive search */
4035 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4037 if(SUCCEEDED(result))
4039 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4040 ITypeInfo_Release(pTInfo);
4043 WARN("Could not search inherited interface!\n");
4047 WARN("no names found\n");
4050 return TYPE_E_ELEMENTNOTFOUND;
4057 /* ITypeInfo::GetRefTypeOfImplType
4059 * If a type description describes a COM class, it retrieves the type
4060 * description of the implemented interface types. For an interface,
4061 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4065 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4070 ICOM_THIS( ITypeInfoImpl, iface);
4072 TLBImplType *pImpl = This->impltypelist;
4074 TRACE("(%p) index %d\n", This, index);
4075 if (TRACE_ON(ole)) dump_TypeInfo(This);
4079 /* only valid on dual interfaces;
4080 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4082 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4084 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4085 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4091 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4092 *pRefType = pImpl->hRef;
4097 /* get element n from linked list */
4098 for(i=0; pImpl && i<index; i++)
4100 pImpl = pImpl->next;
4103 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4105 *pRefType = pImpl->hRef;
4107 TRACE("-- 0x%08lx\n", pImpl->hRef );
4114 /* ITypeInfo::GetImplTypeFlags
4116 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4117 * or base interface in a type description.
4119 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4120 UINT index, INT *pImplTypeFlags)
4122 ICOM_THIS( ITypeInfoImpl, iface);
4126 TRACE("(%p) index %d\n", This, index);
4127 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4128 i++, pImpl=pImpl->next)
4130 if(i==index && pImpl){
4131 *pImplTypeFlags=pImpl->implflags;
4135 return TYPE_E_ELEMENTNOTFOUND;
4139 * Maps between member names and member IDs, and parameter names and
4142 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4143 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4145 ICOM_THIS( ITypeInfoImpl, iface);
4146 TLBFuncDesc * pFDesc;
4147 TLBVarDesc * pVDesc;
4150 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4152 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4154 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4155 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4156 for(i=1; i < cNames; i++){
4157 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4158 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4160 if( j<pFDesc->funcdesc.cParams)
4163 ret=DISP_E_UNKNOWNNAME;
4168 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4169 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4170 if(cNames) *pMemId=pVDesc->vardesc.memid;
4174 /* not found, see if this is and interface with an inheritance */
4175 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4176 This->TypeAttr.cImplTypes ){
4177 /* recursive search */
4179 ret=ITypeInfo_GetRefTypeInfo(iface,
4180 This->impltypelist->hRef, &pTInfo);
4182 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4183 ITypeInfo_Release(pTInfo);
4186 WARN("Could not search inherited interface!\n");
4188 WARN("no names found\n");
4189 return DISP_E_UNKNOWNNAME;
4192 /* ITypeInfo::Invoke
4194 * Invokes a method, or accesses a property of an object, that implements the
4195 * interface described by the type description.
4198 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4201 if (TRACE_ON(ole)) {
4203 TRACE("Calling %p(",func);
4204 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4216 res = func(args[0]);
4219 res = func(args[0],args[1]);
4222 res = func(args[0],args[1],args[2]);
4225 res = func(args[0],args[1],args[2],args[3]);
4228 res = func(args[0],args[1],args[2],args[3],args[4]);
4231 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4234 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4237 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4240 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4243 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4249 FIXME("unsupported calling convention %d\n",callconv);
4253 TRACE("returns %08lx\n",res);
4257 extern int const _argsize(DWORD vt);
4259 /****************************************************************************
4260 * Helper functions for Dispcall / Invoke, which copies one variant
4261 * with target type onto the argument stack.
4264 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4265 DWORD *argpos, VARIANT *arg, VARTYPE vt
4267 UINT arglen = _argsize(vt)*sizeof(DWORD);
4270 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4271 memcpy(argpos,&arg,sizeof(void*));
4275 if (V_VT(arg) == vt) {
4276 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4280 if (vt == VT_VARIANT) {
4281 memcpy(argpos, arg, arglen);
4284 /* Deref BYREF vars if there is need */
4285 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4286 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4289 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4290 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4291 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4294 if ((vt == VT_PTR) && tdesc)
4295 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4296 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4301 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4303 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing from vt 0x%x. Copying 4 byte.\n",tdesc->u.hreftype,V_VT(arg));
4304 memcpy(argpos, &V_UNION(arg,lVal), 4);
4307 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4308 switch (tattr->typekind) {
4310 switch ( V_VT( arg ) ) {
4312 *argpos = V_UNION(arg,iVal);
4315 memcpy(argpos, &V_UNION(arg,lVal), 4);
4318 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4323 tdesc = &(tattr->tdescAlias);
4324 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4325 ITypeInfo_Release(tinfo2);
4328 case TKIND_INTERFACE:
4329 if (V_VT(arg) == VT_DISPATCH) {
4331 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4332 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4335 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4336 if (SUCCEEDED(hres)) {
4337 memcpy(argpos,&disp,4);
4338 IUnknown_Release(V_UNION(arg,pdispVal));
4341 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4344 if (V_VT(arg) == VT_UNKNOWN) {
4345 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4348 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4350 case TKIND_DISPATCH:
4351 if (V_VT(arg) == VT_DISPATCH) {
4352 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4355 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4358 FIXME("TKIND_RECORD unhandled.\n");
4361 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4367 if (VariantChangeType(arg,arg,0,vt)==S_OK) {
4368 FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt, vt);
4369 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4372 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4376 /***********************************************************************
4377 * DispCallFunc (OLEAUT32.@)
4381 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4382 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4384 int i, argsize, argspos;
4388 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4389 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4391 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4392 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4394 for (i=0;i<cActuals;i++) {
4395 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4396 dump_Variant(prgpvarg[i]);
4397 argsize += _argsize(prgvt[i]);
4399 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4400 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4402 for (i=0;i<cActuals;i++) {
4403 VARIANT *arg = prgpvarg[i];
4404 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4405 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4406 argspos += _argsize(prgvt[i]);
4409 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4411 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4416 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4417 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4418 FIXME("Method returned %lx\n",hres);
4420 HeapFree(GetProcessHeap(),0,args);
4424 static HRESULT WINAPI ITypeInfo_fnInvoke(
4429 DISPPARAMS *pDispParams,
4430 VARIANT *pVarResult,
4431 EXCEPINFO *pExcepInfo,
4434 ICOM_THIS( ITypeInfoImpl, iface);
4435 TLBFuncDesc * pFDesc;
4436 TLBVarDesc * pVDesc;
4440 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4441 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4443 dump_DispParms(pDispParams);
4445 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4446 if (pFDesc->funcdesc.memid == memid) {
4447 if (pFDesc->funcdesc.invkind & dwFlags)
4451 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4452 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4453 switch (pFDesc->funcdesc.funckind) {
4454 case FUNC_PUREVIRTUAL:
4455 case FUNC_VIRTUAL: {
4457 int numargs, numargs2, argspos, args2pos;
4458 DWORD *args , *args2;
4461 numargs = 1; numargs2 = 0;
4462 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4463 if (i<pDispParams->cArgs)
4464 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4466 numargs += 1; /* sizeof(lpvoid) */
4467 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4471 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4472 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4474 args[0] = (DWORD)pIUnk;
4475 argspos = 1; args2pos = 0;
4476 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4477 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4478 if (i<pDispParams->cArgs) {
4479 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4480 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4481 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4482 if (FAILED(hres)) return hres;
4485 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4486 if (tdesc->vt != VT_PTR)
4487 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4488 /*FIXME: give pointers for the rest, so propertyget works*/
4489 args[argspos] = (DWORD)&args2[args2pos];
4491 /* If pointer to variant, pass reference it. */
4492 if ((tdesc->vt == VT_PTR) &&
4493 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4496 args[argspos]= (DWORD)pVarResult;
4501 if (pFDesc->funcdesc.cParamsOpt)
4502 FIXME("Does not support optional parameters (%d)\n",
4503 pFDesc->funcdesc.cParamsOpt
4506 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4507 pFDesc->funcdesc.callconv,
4511 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4513 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4514 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4515 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4517 i4_tdesc.vt = VT_I4;
4519 /* If we are a pointer to a variant, we are done already */
4520 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4523 VariantInit(pVarResult);
4524 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4526 if (tdesc->vt == VT_PTR)
4527 tdesc = tdesc->u.lptdesc;
4528 if (tdesc->vt == VT_USERDEFINED) {
4532 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4534 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4537 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4538 switch (tattr->typekind) {
4540 /* force the return type to be VT_I4 */
4544 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4545 tdesc = &(tattr->tdescAlias);
4548 case TKIND_INTERFACE:
4549 FIXME("TKIND_INTERFACE unhandled.\n");
4551 case TKIND_DISPATCH:
4552 FIXME("TKIND_DISPATCH unhandled.\n");
4555 FIXME("TKIND_RECORD unhandled.\n");
4558 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4561 ITypeInfo_Release(tinfo2);
4563 V_VT(pVarResult) = tdesc->vt;
4565 /* HACK: VB5 likes this.
4566 * I do not know why. There is 1 example in MSDN which uses
4567 * this which appears broken (mixes int vals and
4570 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4571 V_VT(pVarResult) = VT_DISPATCH;
4572 TRACE("storing into variant:\n");
4573 dump_Variant(pVarResult);
4577 HeapFree(GetProcessHeap(),0,args2);
4578 HeapFree(GetProcessHeap(),0,args);
4581 case FUNC_DISPATCH: {
4585 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4587 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4590 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4591 hr = IDispatch_Invoke(
4592 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4593 pVarResult,pExcepInfo,pArgErr
4596 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4597 IDispatch_Release(disp);
4601 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4605 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4606 if (pVDesc->vardesc.memid == memid) {
4607 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4608 dump_TLBVarDesc(pVDesc);
4613 /* not found, look for it in inherited interfaces */
4614 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4615 /* recursive search */
4618 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4620 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4621 ITypeInfo_Release(pTInfo);
4624 WARN("Could not search inherited interface!\n");
4626 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4627 return DISP_E_MEMBERNOTFOUND;
4630 /* ITypeInfo::GetDocumentation
4632 * Retrieves the documentation string, the complete Help file name and path,
4633 * and the context ID for the Help topic for a specified type description.
4635 * (Can be tested by the Visual Basic Editor in Word for instance.)
4637 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4638 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4639 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4641 ICOM_THIS( ITypeInfoImpl, iface);
4642 TLBFuncDesc * pFDesc;
4643 TLBVarDesc * pVDesc;
4644 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4645 " HelpContext(%p) HelpFile(%p)\n",
4646 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4647 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4649 *pBstrName=SysAllocString(This->Name);
4651 *pBstrDocString=SysAllocString(This->DocString);
4653 *pdwHelpContext=This->dwHelpContext;
4655 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4657 }else {/* for a member */
4658 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4659 if(pFDesc->funcdesc.memid==memid){
4661 *pBstrName = SysAllocString(pFDesc->Name);
4663 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4665 *pdwHelpContext=pFDesc->helpcontext;
4668 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4669 if(pVDesc->vardesc.memid==memid){
4671 *pBstrName = SysAllocString(pVDesc->Name);
4673 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4675 *pdwHelpContext=pVDesc->HelpContext;
4679 return TYPE_E_ELEMENTNOTFOUND;
4682 /* ITypeInfo::GetDllEntry
4684 * Retrieves a description or specification of an entry point for a function
4687 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4688 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4691 ICOM_THIS( ITypeInfoImpl, iface);
4692 TLBFuncDesc *pFDesc;
4694 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4696 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4697 if(pFDesc->funcdesc.memid==memid){
4698 dump_TypeInfo(This);
4699 dump_TLBFuncDescOne(pFDesc);
4701 /* FIXME: This is wrong, but how do you find that out? */
4703 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4704 *pBstrDllName = SysAllocString(oleaut32W);
4707 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4709 *pBstrName = SysAllocString(pFDesc->Entry);
4717 *pwOrdinal = (DWORD)pFDesc->Entry;
4723 /* ITypeInfo::GetRefTypeInfo
4725 * If a type description references other type descriptions, it retrieves
4726 * the referenced type descriptions.
4728 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4731 ITypeInfo **ppTInfo)
4733 ICOM_THIS( ITypeInfoImpl, iface);
4734 HRESULT result = E_FAIL;
4737 if (hRefType == -1 &&
4738 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4739 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4741 /* when we meet a DUAL dispinterface, we must create the interface
4744 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4747 /* the interface version contains the same information as the dispinterface
4748 * copy the contents of the structs.
4750 *pTypeInfoImpl = *This;
4751 pTypeInfoImpl->ref = 1;
4753 /* change the type to interface */
4754 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4756 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4758 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4763 TLBRefType *pRefType;
4764 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4765 if(pRefType->reference == hRefType)
4769 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4770 if(pRefType && hRefType != -1) {
4771 ITypeLib *pTLib = NULL;
4773 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4775 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4777 if(pRefType->pImpTLInfo->pImpTypeLib) {
4778 TRACE("typeinfo in imported typelib that is already loaded\n");
4779 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4780 ITypeLib2_AddRef((ITypeLib*) pTLib);
4783 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4784 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4785 pRefType->pImpTLInfo->wVersionMajor,
4786 pRefType->pImpTLInfo->wVersionMinor,
4787 pRefType->pImpTLInfo->lcid,
4790 if(!SUCCEEDED(result)) {
4791 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4792 result=LoadTypeLib(libnam, &pTLib);
4793 SysFreeString(libnam);
4795 if(SUCCEEDED(result)) {
4796 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4797 ITypeLib2_AddRef(pTLib);
4801 if(SUCCEEDED(result)) {
4802 if(pRefType->index == TLB_REF_USE_GUID)
4803 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4807 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4811 ITypeLib2_Release(pTLib);
4815 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4816 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4820 /* ITypeInfo::AddressOfMember
4822 * Retrieves the addresses of static functions or variables, such as those
4825 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4826 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4828 ICOM_THIS( ITypeInfoImpl, iface);
4829 FIXME("(%p) stub!\n", This);
4833 /* ITypeInfo::CreateInstance
4835 * Creates a new instance of a type that describes a component object class
4838 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4839 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4841 ICOM_THIS( ITypeInfoImpl, iface);
4842 FIXME("(%p) stub!\n", This);
4846 /* ITypeInfo::GetMops
4848 * Retrieves marshalling information.
4850 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4853 ICOM_THIS( ITypeInfoImpl, iface);
4854 FIXME("(%p) stub!\n", This);
4858 /* ITypeInfo::GetContainingTypeLib
4860 * Retrieves the containing type library and the index of the type description
4861 * within that type library.
4863 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4864 ITypeLib * *ppTLib, UINT *pIndex)
4866 ICOM_THIS( ITypeInfoImpl, iface);
4868 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4870 *pIndex=This->index;
4871 TRACE("returning pIndex=%d", *pIndex);
4875 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4876 ITypeLib2_AddRef(*ppTLib);
4877 TRACE("returning ppTLib=%p", *ppTLib);
4883 /* ITypeInfo::ReleaseTypeAttr
4885 * Releases a TYPEATTR previously returned by GetTypeAttr.
4888 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4889 TYPEATTR* pTypeAttr)
4891 ICOM_THIS( ITypeInfoImpl, iface);
4892 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4895 /* ITypeInfo::ReleaseFuncDesc
4897 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4899 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
4901 FUNCDESC *pFuncDesc)
4903 ICOM_THIS( ITypeInfoImpl, iface);
4904 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4907 /* ITypeInfo::ReleaseVarDesc
4909 * Releases a VARDESC previously returned by GetVarDesc.
4911 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4914 ICOM_THIS( ITypeInfoImpl, iface);
4915 TRACE("(%p)->(%p)\n", This, pVarDesc);
4918 /* ITypeInfo2::GetTypeKind
4920 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4923 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4924 TYPEKIND *pTypeKind)
4926 ICOM_THIS( ITypeInfoImpl, iface);
4927 *pTypeKind=This->TypeAttr.typekind;
4928 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4932 /* ITypeInfo2::GetTypeFlags
4934 * Returns the type flags without any allocations. This returns a DWORD type
4935 * flag, which expands the type flags without growing the TYPEATTR (type
4939 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
4941 ICOM_THIS( ITypeInfoImpl, iface);
4942 *pTypeFlags=This->TypeAttr.wTypeFlags;
4943 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
4947 /* ITypeInfo2::GetFuncIndexOfMemId
4948 * Binds to a specific member based on a known DISPID, where the member name
4949 * is not known (for example, when binding to a default member).
4952 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4953 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4955 ICOM_THIS( ITypeInfoImpl, iface);
4956 TLBFuncDesc *pFuncInfo;
4959 /* FIXME: should check for invKind??? */
4960 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4961 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4967 result=E_INVALIDARG;
4969 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4970 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4974 /* TypeInfo2::GetVarIndexOfMemId
4976 * Binds to a specific member based on a known DISPID, where the member name
4977 * is not known (for example, when binding to a default member).
4980 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4981 MEMBERID memid, UINT *pVarIndex)
4983 ICOM_THIS( ITypeInfoImpl, iface);
4984 TLBVarDesc *pVarInfo;
4987 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4988 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4995 result=E_INVALIDARG;
4997 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4998 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5002 /* ITypeInfo2::GetCustData
5004 * Gets the custom data
5006 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5011 ICOM_THIS( ITypeInfoImpl, iface);
5012 TLBCustData *pCData;
5014 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5015 if( IsEqualIID(guid, &pCData->guid)) break;
5017 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5021 VariantInit( pVarVal);
5022 VariantCopy( pVarVal, &pCData->data);
5025 return E_INVALIDARG; /* FIXME: correct? */
5028 /* ITypeInfo2::GetFuncCustData
5030 * Gets the custom data
5032 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5038 ICOM_THIS( ITypeInfoImpl, iface);
5039 TLBCustData *pCData=NULL;
5040 TLBFuncDesc * pFDesc;
5042 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5043 pFDesc=pFDesc->next);
5046 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5047 if( IsEqualIID(guid, &pCData->guid)) break;
5049 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5052 VariantInit( pVarVal);
5053 VariantCopy( pVarVal, &pCData->data);
5056 return E_INVALIDARG; /* FIXME: correct? */
5059 /* ITypeInfo2::GetParamCustData
5061 * Gets the custom data
5063 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5070 ICOM_THIS( ITypeInfoImpl, iface);
5071 TLBCustData *pCData=NULL;
5072 TLBFuncDesc * pFDesc;
5075 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5077 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5078 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5079 pCData = pCData->next)
5080 if( IsEqualIID(guid, &pCData->guid)) break;
5082 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5086 VariantInit( pVarVal);
5087 VariantCopy( pVarVal, &pCData->data);
5090 return E_INVALIDARG; /* FIXME: correct? */
5093 /* ITypeInfo2::GetVarCustData
5095 * Gets the custom data
5097 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5103 ICOM_THIS( ITypeInfoImpl, iface);
5104 TLBCustData *pCData=NULL;
5105 TLBVarDesc * pVDesc;
5108 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5112 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5114 if( IsEqualIID(guid, &pCData->guid)) break;
5118 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5122 VariantInit( pVarVal);
5123 VariantCopy( pVarVal, &pCData->data);
5126 return E_INVALIDARG; /* FIXME: correct? */
5129 /* ITypeInfo2::GetImplCustData
5131 * Gets the custom data
5133 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5139 ICOM_THIS( ITypeInfoImpl, iface);
5140 TLBCustData *pCData=NULL;
5141 TLBImplType * pRDesc;
5144 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5148 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5150 if( IsEqualIID(guid, &pCData->guid)) break;
5154 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5158 VariantInit( pVarVal);
5159 VariantCopy( pVarVal, &pCData->data);
5162 return E_INVALIDARG; /* FIXME: correct? */
5165 /* ITypeInfo2::GetDocumentation2
5167 * Retrieves the documentation string, the complete Help file name and path,
5168 * the localization context to use, and the context ID for the library Help
5169 * topic in the Help file.
5172 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5176 BSTR *pbstrHelpString,
5177 DWORD *pdwHelpStringContext,
5178 BSTR *pbstrHelpStringDll)
5180 ICOM_THIS( ITypeInfoImpl, iface);
5181 TLBFuncDesc * pFDesc;
5182 TLBVarDesc * pVDesc;
5183 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5184 "HelpStringContext(%p) HelpStringDll(%p)\n",
5185 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5186 pbstrHelpStringDll );
5187 /* the help string should be obtained from the helpstringdll,
5188 * using the _DLLGetDocumentation function, based on the supplied
5189 * lcid. Nice to do sometime...
5191 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5193 *pbstrHelpString=SysAllocString(This->Name);
5194 if(pdwHelpStringContext)
5195 *pdwHelpStringContext=This->dwHelpStringContext;
5196 if(pbstrHelpStringDll)
5197 *pbstrHelpStringDll=
5198 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5200 }else {/* for a member */
5201 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5202 if(pFDesc->funcdesc.memid==memid){
5204 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5205 if(pdwHelpStringContext)
5206 *pdwHelpStringContext=pFDesc->HelpStringContext;
5207 if(pbstrHelpStringDll)
5208 *pbstrHelpStringDll=
5209 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5212 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5213 if(pVDesc->vardesc.memid==memid){
5215 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5216 if(pdwHelpStringContext)
5217 *pdwHelpStringContext=pVDesc->HelpStringContext;
5218 if(pbstrHelpStringDll)
5219 *pbstrHelpStringDll=
5220 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5224 return TYPE_E_ELEMENTNOTFOUND;
5227 /* ITypeInfo2::GetAllCustData
5229 * Gets all custom data items for the Type info.
5232 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5234 CUSTDATA *pCustData)
5236 ICOM_THIS( ITypeInfoImpl, iface);
5237 TLBCustData *pCData;
5240 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5242 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5243 if(pCustData->prgCustData ){
5244 pCustData->cCustData=This->ctCustData;
5245 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5246 pCustData->prgCustData[i].guid=pCData->guid;
5247 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5250 ERR(" OUT OF MEMORY! \n");
5251 return E_OUTOFMEMORY;
5256 /* ITypeInfo2::GetAllFuncCustData
5258 * Gets all custom data items for the specified Function
5261 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5264 CUSTDATA *pCustData)
5266 ICOM_THIS( ITypeInfoImpl, iface);
5267 TLBCustData *pCData;
5268 TLBFuncDesc * pFDesc;
5270 TRACE("(%p) index %d\n", This, index);
5271 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5272 pFDesc=pFDesc->next)
5275 pCustData->prgCustData =
5276 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5277 if(pCustData->prgCustData ){
5278 pCustData->cCustData=pFDesc->ctCustData;
5279 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5280 pCData = pCData->next){
5281 pCustData->prgCustData[i].guid=pCData->guid;
5282 VariantCopy(& pCustData->prgCustData[i].varValue,
5286 ERR(" OUT OF MEMORY! \n");
5287 return E_OUTOFMEMORY;
5291 return TYPE_E_ELEMENTNOTFOUND;
5294 /* ITypeInfo2::GetAllParamCustData
5296 * Gets all custom data items for the Functions
5299 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5300 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5302 ICOM_THIS( ITypeInfoImpl, iface);
5303 TLBCustData *pCData=NULL;
5304 TLBFuncDesc * pFDesc;
5306 TRACE("(%p) index %d\n", This, indexFunc);
5307 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5308 pFDesc=pFDesc->next)
5310 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5311 pCustData->prgCustData =
5312 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5313 sizeof(CUSTDATAITEM));
5314 if(pCustData->prgCustData ){
5315 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5316 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5317 pCData; i++, pCData = pCData->next){
5318 pCustData->prgCustData[i].guid=pCData->guid;
5319 VariantCopy(& pCustData->prgCustData[i].varValue,
5323 ERR(" OUT OF MEMORY! \n");
5324 return E_OUTOFMEMORY;
5328 return TYPE_E_ELEMENTNOTFOUND;
5331 /* ITypeInfo2::GetAllVarCustData
5333 * Gets all custom data items for the specified Variable
5336 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5337 UINT index, CUSTDATA *pCustData)
5339 ICOM_THIS( ITypeInfoImpl, iface);
5340 TLBCustData *pCData;
5341 TLBVarDesc * pVDesc;
5343 TRACE("(%p) index %d\n", This, index);
5344 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5345 pVDesc=pVDesc->next)
5348 pCustData->prgCustData =
5349 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5350 if(pCustData->prgCustData ){
5351 pCustData->cCustData=pVDesc->ctCustData;
5352 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5353 pCData = pCData->next){
5354 pCustData->prgCustData[i].guid=pCData->guid;
5355 VariantCopy(& pCustData->prgCustData[i].varValue,
5359 ERR(" OUT OF MEMORY! \n");
5360 return E_OUTOFMEMORY;
5364 return TYPE_E_ELEMENTNOTFOUND;
5367 /* ITypeInfo2::GetAllImplCustData
5369 * Gets all custom data items for the specified implementation type
5372 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5375 CUSTDATA *pCustData)
5377 ICOM_THIS( ITypeInfoImpl, iface);
5378 TLBCustData *pCData;
5379 TLBImplType * pRDesc;
5381 TRACE("(%p) index %d\n", This, index);
5382 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5383 pRDesc=pRDesc->next)
5386 pCustData->prgCustData =
5387 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5388 if(pCustData->prgCustData ){
5389 pCustData->cCustData=pRDesc->ctCustData;
5390 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5391 pCData = pCData->next){
5392 pCustData->prgCustData[i].guid=pCData->guid;
5393 VariantCopy(& pCustData->prgCustData[i].varValue,
5397 ERR(" OUT OF MEMORY! \n");
5398 return E_OUTOFMEMORY;
5402 return TYPE_E_ELEMENTNOTFOUND;
5405 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5407 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5409 ITypeInfo_fnQueryInterface,
5411 ITypeInfo_fnRelease,
5413 ITypeInfo_fnGetTypeAttr,
5414 ITypeInfo_fnGetTypeComp,
5415 ITypeInfo_fnGetFuncDesc,
5416 ITypeInfo_fnGetVarDesc,
5417 ITypeInfo_fnGetNames,
5418 ITypeInfo_fnGetRefTypeOfImplType,
5419 ITypeInfo_fnGetImplTypeFlags,
5420 ITypeInfo_fnGetIDsOfNames,
5422 ITypeInfo_fnGetDocumentation,
5423 ITypeInfo_fnGetDllEntry,
5424 ITypeInfo_fnGetRefTypeInfo,
5425 ITypeInfo_fnAddressOfMember,
5426 ITypeInfo_fnCreateInstance,
5427 ITypeInfo_fnGetMops,
5428 ITypeInfo_fnGetContainingTypeLib,
5429 ITypeInfo_fnReleaseTypeAttr,
5430 ITypeInfo_fnReleaseFuncDesc,
5431 ITypeInfo_fnReleaseVarDesc,
5433 ITypeInfo2_fnGetTypeKind,
5434 ITypeInfo2_fnGetTypeFlags,
5435 ITypeInfo2_fnGetFuncIndexOfMemId,
5436 ITypeInfo2_fnGetVarIndexOfMemId,
5437 ITypeInfo2_fnGetCustData,
5438 ITypeInfo2_fnGetFuncCustData,
5439 ITypeInfo2_fnGetParamCustData,
5440 ITypeInfo2_fnGetVarCustData,
5441 ITypeInfo2_fnGetImplTypeCustData,
5442 ITypeInfo2_fnGetDocumentation2,
5443 ITypeInfo2_fnGetAllCustData,
5444 ITypeInfo2_fnGetAllFuncCustData,
5445 ITypeInfo2_fnGetAllParamCustData,
5446 ITypeInfo2_fnGetAllVarCustData,
5447 ITypeInfo2_fnGetAllImplTypeCustData,
5450 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5452 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5454 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5457 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5459 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5461 return ITypeInfo_AddRef((ITypeInfo *)This);
5464 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5466 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5468 return ITypeInfo_Release((ITypeInfo *)This);
5471 static HRESULT WINAPI ITypeComp_fnBind(
5474 unsigned long lHash,
5475 unsigned short wFlags,
5476 ITypeInfo ** ppTInfo,
5477 DESCKIND * pDescKind,
5480 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5481 TLBFuncDesc * pFDesc;
5482 TLBVarDesc * pVDesc;
5484 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5486 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5487 if (pFDesc->funcdesc.invkind & wFlags)
5488 if (!strcmpW(pFDesc->Name, szName)) {
5494 *pDescKind = DESCKIND_FUNCDESC;
5495 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5496 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5499 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5501 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5502 if (!strcmpW(pVDesc->Name, szName)) {
5503 *pDescKind = DESCKIND_VARDESC;
5504 pBindPtr->lpvardesc = &pVDesc->vardesc;
5505 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5511 /* not found, look for it in inherited interfaces */
5512 if ((This->TypeAttr.typekind == TKIND_INTERFACE) && This->TypeAttr.cImplTypes) {
5513 /* recursive search */
5517 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5520 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5521 ITypeInfo_Release(pTInfo);
5525 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5526 ITypeComp_Release(pTComp);
5529 WARN("Could not search inherited interface!\n");
5531 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5532 *pDescKind = DESCKIND_NONE;
5533 pBindPtr->lpfuncdesc = NULL;
5535 return DISP_E_MEMBERNOTFOUND;
5538 static HRESULT WINAPI ITypeComp_fnBindType(
5541 unsigned long lHash,
5542 ITypeInfo ** ppTInfo,
5543 ITypeComp ** ppTComp)
5545 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5547 /* strange behaviour (does nothing) but like the
5550 if (!ppTInfo || !ppTComp)
5559 static ICOM_VTABLE(ITypeComp) tcompvt =
5561 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5563 ITypeComp_fnQueryInterface,
5565 ITypeComp_fnRelease,
5568 ITypeComp_fnBindType