4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
64 #define NONAMELESSUNION
65 #define NONAMELESSSTRUCT
73 #include "wine/unicode.h"
78 #include "wine/debug.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 /****************************************************************************
90 * Takes p_iVal (which is in little endian) and returns it
91 * in the host machine's byte order.
93 #ifdef WORDS_BIGENDIAN
94 static WORD FromLEWord(WORD p_iVal)
96 return (((p_iVal & 0x00FF) << 8) |
97 ((p_iVal & 0xFF00) >> 8));
101 static DWORD FromLEDWord(DWORD p_iVal)
103 return (((p_iVal & 0x000000FF) << 24) |
104 ((p_iVal & 0x0000FF00) << 8) |
105 ((p_iVal & 0x00FF0000) >> 8) |
106 ((p_iVal & 0xFF000000) >> 24));
109 #define FromLEWord(X) (X)
110 #define FromLEDWord(X) (X)
114 /****************************************************************************
117 * Fix byte order in any structure if necessary
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val, int p_iSize)
124 p_iSize /= sizeof(WORD);
127 *Val = FromLEWord(*Val);
134 static void FromLEDWords(void *p_Val, int p_iSize)
138 p_iSize /= sizeof(DWORD);
141 *Val = FromLEDWord(*Val);
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
152 /****************************************************************************
153 * QueryPathOfRegTypeLib [OLEAUT32.164]
158 QueryPathOfRegTypeLib(
159 REFGUID guid, /* [in] referenced guid */
160 WORD wMaj, /* [in] major version */
161 WORD wMin, /* [in] minor version */
162 LCID lcid, /* [in] locale id */
163 LPBSTR path ) /* [out] path of typelib */
165 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
166 string termination character on output strings */
173 char szTypeLibKey[100];
174 char szPath[MAX_PATH];
175 DWORD dwPathLen = sizeof(szPath);
183 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
189 sprintf(szTypeLibKey,
190 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
191 guid->Data1, guid->Data2, guid->Data3,
192 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
193 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
198 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
202 else if (myLCID == lcid)
204 /* try with sub-langid */
205 myLCID = SUBLANGID(lcid);
207 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
209 /* try with system langid */
219 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
220 BSTR bstrPath = SysAllocStringLen(NULL,len);
222 MultiByteToWideChar(CP_ACP,
234 TRACE_(typelib)("%s not found\n", szTypeLibKey);
239 /******************************************************************************
240 * CreateTypeLib [OLEAUT32.160] creates a typelib
246 HRESULT WINAPI CreateTypeLib(
247 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
249 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
252 /******************************************************************************
253 * LoadTypeLib [OLEAUT32.161]
254 * Loads and registers a type library
256 * Docs: OLECHAR FAR* szFile
257 * Docs: iTypeLib FAR* FAR* pptLib
263 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
265 HRESULT WINAPI LoadTypeLib(
266 const OLECHAR *szFile,/* [in] Name of file to load from */
267 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
270 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
273 /******************************************************************************
274 * LoadTypeLibEx [OLEAUT32.183]
275 * Loads and optionally registers a type library
281 HRESULT WINAPI LoadTypeLibEx(
282 LPCOLESTR szFile, /* [in] Name of file to load from */
283 REGKIND regkind, /* [in] Specify kind of registration */
284 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
286 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
291 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
294 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
297 /* Look for a trailing '\\' followed by an index */
298 pIndexStr = strrchrW(szFile, '\\');
299 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
300 index = atoiW(pIndexStr);
301 memcpy(szFileCopy, szFile,
302 (pIndexStr - szFile - 1) * sizeof(WCHAR));
303 szFileCopy[pIndexStr - szFile - 1] = '\0';
304 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
306 return TYPE_E_CANTLOADLIBRARY;
307 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
308 return TYPE_E_CANTLOADLIBRARY;
311 WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
314 lstrcpyW(tstpath,szFile);
316 for (i=0;i<strlenW(tstpath);i++) {
317 if (tstpath[i] == 's') {
318 if (!strcmpW(tstpath+i,stdole32tlb)) {
320 MESSAGE("**************************************************************************\n");
321 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
322 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
323 MESSAGE("on the Microsoft Download Pages.\n");
324 MESSAGE("**************************************************************************\n");
329 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
330 return TYPE_E_CANTLOADLIBRARY;
334 TRACE("File %s index %d\n", debugstr_w(szPath), index);
336 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
341 case REGKIND_DEFAULT:
342 /* FIXME: is this correct? */
343 if (!szFile || !szFile[0] ||
344 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
346 /* else fall-through */
347 case REGKIND_REGISTER:
348 /* FIXME: Help path? */
349 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
351 IUnknown_Release(*pptLib);
359 TRACE(" returns %08lx\n",res);
363 /******************************************************************************
364 * LoadRegTypeLib [OLEAUT32.162]
366 HRESULT WINAPI LoadRegTypeLib(
367 REFGUID rguid, /* [in] referenced guid */
368 WORD wVerMajor, /* [in] major version */
369 WORD wVerMinor, /* [in] minor version */
370 LCID lcid, /* [in] locale id */
371 ITypeLib **ppTLib) /* [out] path of typelib */
374 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
378 res= LoadTypeLib(bstr, ppTLib);
382 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
388 /******************************************************************************
389 * RegisterTypeLib [OLEAUT32.163]
390 * Adds information about a type library to the System Registry
392 * Docs: ITypeLib FAR * ptlib
393 * Docs: OLECHAR FAR* szFullPath
394 * Docs: OLECHAR FAR* szHelpDir
400 HRESULT WINAPI RegisterTypeLib(
401 ITypeLib * ptlib, /* [in] Pointer to the library*/
402 OLECHAR * szFullPath, /* [in] full Path of the library*/
403 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
414 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
416 if (ptlib == NULL || szFullPath == NULL)
419 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
422 StringFromGUID2(&attr->guid, guid, 80);
423 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
424 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
425 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
426 HeapFree(GetProcessHeap(), 0, guidA);
429 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
430 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
434 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
436 if (RegSetValueExW(key, NULL, 0, REG_SZ,
437 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
445 /* FIXME: This *seems* to be 0 always, not sure though */
446 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
447 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
449 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
450 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
458 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
459 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
462 /* FIXME: is %u correct? */
463 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
464 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
465 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
473 /* register OLE Automation-compatible interfaces for this typelib */
474 types = ITypeLib_GetTypeInfoCount(ptlib);
475 for (tidx=0; tidx<types; tidx++) {
476 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
477 LPOLESTR name = NULL;
478 ITypeInfo *tinfo = NULL;
480 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
482 case TKIND_INTERFACE:
483 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
484 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
487 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
488 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
491 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
492 /* coclasses should probably not be registered? */
495 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
499 TYPEATTR *tattr = NULL;
500 ITypeInfo_GetTypeAttr(tinfo, &tattr);
502 TRACE_(typelib)("guid=%s, flags=%04x (",
503 debugstr_guid(&tattr->guid),
505 if (TRACE_ON(typelib)) {
506 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
526 * FIXME: The 1 is just here until we implement rpcrt4
527 * stub/proxy handling. Until then it helps IShield
530 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
532 /* register interface<->typelib coupling */
533 StringFromGUID2(&tattr->guid, guid, 80);
534 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
535 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
536 HeapFree(GetProcessHeap(), 0, guidA);
538 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
539 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
541 RegSetValueExW(key, NULL, 0, REG_SZ,
542 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
544 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
545 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
546 RegSetValueExA(subKey, NULL, 0, REG_SZ,
550 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
551 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
552 RegSetValueExA(subKey, NULL, 0, REG_SZ,
557 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
558 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
560 StringFromGUID2(&attr->guid, guid, 80);
561 snprintf(ver, sizeof(ver), "%x.%x",
562 attr->wMajorVerNum, attr->wMinorVerNum);
563 RegSetValueExW(subKey, NULL, 0, REG_SZ,
564 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
565 RegSetValueExA(subKey, "Version", 0, REG_SZ,
572 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
574 ITypeInfo_Release(tinfo);
581 ITypeLib_ReleaseTLibAttr(ptlib, attr);
587 /******************************************************************************
588 * UnRegisterTypeLib [OLEAUT32.186]
589 * Removes information about a type library from the System Registry
596 HRESULT WINAPI UnRegisterTypeLib(
597 REFGUID libid, /* [in] Guid of the library */
598 WORD wVerMajor, /* [in] major version */
599 WORD wVerMinor, /* [in] minor version */
600 LCID lcid, /* [in] locale id */
603 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
604 return S_OK; /* FIXME: pretend everything is OK */
607 /*======================= ITypeLib implementation =======================*/
609 typedef struct tagTLBCustData
613 struct tagTLBCustData* next;
616 /* data structure for import typelibs */
617 typedef struct tagTLBImpLib
619 int offset; /* offset in the file (MSFT)
620 offset in nametable (SLTG)
621 just used to identify library while reading
623 GUID guid; /* libid */
624 BSTR name; /* name */
626 LCID lcid; /* lcid of imported typelib */
628 WORD wVersionMajor; /* major version number */
629 WORD wVersionMinor; /* minor version number */
631 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
632 NULL if not yet loaded */
633 struct tagTLBImpLib * next;
636 /* internal ITypeLib data */
637 typedef struct tagITypeLibImpl
639 ICOM_VFIELD(ITypeLib2);
640 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
642 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
644 /* strings can be stored in tlb as multibyte strings BUT they are *always*
645 * exported to the application as a UNICODE string.
651 unsigned long dwHelpContext;
652 int TypeInfoCount; /* nr of typeinfo's in librarry */
653 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
654 int ctCustData; /* number of items in cust data list */
655 TLBCustData * pCustData; /* linked list to cust data */
656 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
657 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
658 libary. Only used while read MSFT
661 /* typelibs are cached, keyed by path, so store the linked list info within them */
662 struct tagITypeLibImpl *next, *prev;
666 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
667 static struct ICOM_VTABLE(ITypeComp) tlbtcvt;
669 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
670 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
672 /* ITypeLib methods */
673 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
674 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
676 /*======================= ITypeInfo implementation =======================*/
678 /* data for refernced types */
679 typedef struct tagTLBRefType
681 INT index; /* Type index for internal ref or for external ref
682 it the format is SLTG. -2 indicates to
685 GUID guid; /* guid of the referenced type */
686 /* if index == TLB_REF_USE_GUID */
688 HREFTYPE reference; /* The href of this ref */
689 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
690 TLB_REF_INTERNAL for internal refs
691 TLB_REF_NOT_FOUND for broken refs */
693 struct tagTLBRefType * next;
696 #define TLB_REF_USE_GUID -2
698 #define TLB_REF_INTERNAL (void*)-2
699 #define TLB_REF_NOT_FOUND (void*)-1
701 /* internal Parameter data */
702 typedef struct tagTLBParDesc
706 TLBCustData * pCustData; /* linked list to cust data */
709 /* internal Function data */
710 typedef struct tagTLBFuncDesc
712 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
713 BSTR Name; /* the name of this function */
714 TLBParDesc *pParamDesc; /* array with param names and custom data */
716 int HelpStringContext;
718 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
720 TLBCustData * pCustData; /* linked list to cust data; */
721 struct tagTLBFuncDesc * next;
724 /* internal Variable data */
725 typedef struct tagTLBVarDesc
727 VARDESC vardesc; /* lots of info on the variable and its attributes. */
728 BSTR Name; /* the name of this variable */
730 int HelpStringContext; /* FIXME: where? */
733 TLBCustData * pCustData;/* linked list to cust data; */
734 struct tagTLBVarDesc * next;
737 /* internal implemented interface data */
738 typedef struct tagTLBImplType
740 HREFTYPE hRef; /* hRef of interface */
741 int implflags; /* IMPLFLAG_*s */
743 TLBCustData * pCustData;/* linked list to custom data; */
744 struct tagTLBImplType *next;
747 /* internal TypeInfo data */
748 typedef struct tagITypeInfoImpl
750 ICOM_VFIELD(ITypeInfo2);
751 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
753 TYPEATTR TypeAttr ; /* _lots_ of type information. */
754 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
755 int index; /* index in this typelib; */
756 /* type libs seem to store the doc strings in ascii
757 * so why should we do it in unicode?
761 unsigned long dwHelpContext;
762 unsigned long dwHelpStringContext;
765 TLBFuncDesc * funclist; /* linked list with function descriptions */
768 TLBVarDesc * varlist; /* linked list with variable descriptions */
770 /* Implemented Interfaces */
771 TLBImplType * impltypelist;
773 TLBRefType * reflist;
775 TLBCustData * pCustData; /* linked list to cust data; */
776 struct tagITypeInfoImpl * next;
779 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
780 static struct ICOM_VTABLE(ITypeComp) tcompvt;
782 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
784 typedef struct tagTLBContext
786 unsigned int oStart; /* start of TLB in file */
787 unsigned int pos; /* current pos */
788 unsigned int length; /* total length */
789 void *mapping; /* memory mapping */
790 MSFT_SegDir * pTblDir;
791 ITypeLibImpl* pLibInfo;
795 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
800 static void dump_VarType(VARTYPE vt,char *szVarType) {
801 /* FIXME : we could have better trace here, depending on the VARTYPE
804 if (vt & VT_RESERVED)
805 szVarType += strlen(strcpy(szVarType, "reserved | "));
807 szVarType += strlen(strcpy(szVarType, "ref to "));
809 szVarType += strlen(strcpy(szVarType, "array of "));
811 szVarType += strlen(strcpy(szVarType, "vector of "));
812 switch(vt & VT_TYPEMASK) {
813 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
814 case VT_I2: sprintf(szVarType, "VT_I2"); break;
815 case VT_I4: sprintf(szVarType, "VT_I4"); break;
816 case VT_R4: sprintf(szVarType, "VT_R4"); break;
817 case VT_R8: sprintf(szVarType, "VT_R8"); break;
818 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
819 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
820 case VT_CY: sprintf(szVarType, "VT_CY"); break;
821 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
822 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
823 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
824 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
825 case VT_I1: sprintf(szVarType, "VT_I1"); break;
826 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
827 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
828 case VT_INT: sprintf(szVarType, "VT_INT"); break;
829 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
830 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
831 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
832 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
833 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
837 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
838 if (pTD->vt & VT_RESERVED)
839 szVarType += strlen(strcpy(szVarType, "reserved | "));
840 if (pTD->vt & VT_BYREF)
841 szVarType += strlen(strcpy(szVarType, "ref to "));
842 if (pTD->vt & VT_ARRAY)
843 szVarType += strlen(strcpy(szVarType, "array of "));
844 if (pTD->vt & VT_VECTOR)
845 szVarType += strlen(strcpy(szVarType, "vector of "));
846 switch(pTD->vt & VT_TYPEMASK) {
847 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
848 case VT_I2: sprintf(szVarType, "VT_I2"); break;
849 case VT_I4: sprintf(szVarType, "VT_I4"); break;
850 case VT_R4: sprintf(szVarType, "VT_R4"); break;
851 case VT_R8: sprintf(szVarType, "VT_R8"); break;
852 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
853 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
854 case VT_CY: sprintf(szVarType, "VT_CY"); break;
855 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
856 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
857 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
858 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
859 case VT_I1: sprintf(szVarType, "VT_I1"); break;
860 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
861 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
862 case VT_INT: sprintf(szVarType, "VT_INT"); break;
863 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
864 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
865 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
866 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
867 pTD->u.hreftype); break;
868 case VT_PTR: sprintf(szVarType, "ptr to ");
869 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
871 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
872 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
874 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
875 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
876 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
879 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
883 void dump_ELEMDESC(ELEMDESC *edesc) {
885 dump_TypeDesc(&edesc->tdesc,buf);
886 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
887 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
888 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
890 void dump_FUNCDESC(FUNCDESC *funcdesc) {
892 MESSAGE("memid is %08lx\n",funcdesc->memid);
893 for (i=0;i<funcdesc->cParams;i++) {
894 MESSAGE("Param %d:\n",i);
895 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
897 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
898 switch (funcdesc->funckind) {
899 case FUNC_VIRTUAL: MESSAGE("virtual");break;
900 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
901 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
902 case FUNC_STATIC: MESSAGE("static");break;
903 case FUNC_DISPATCH: MESSAGE("dispatch");break;
904 default: MESSAGE("unknown");break;
906 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
907 switch (funcdesc->invkind) {
908 case INVOKE_FUNC: MESSAGE("func");break;
909 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
910 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
911 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
913 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
914 switch (funcdesc->callconv) {
915 case CC_CDECL: MESSAGE("cdecl");break;
916 case CC_PASCAL: MESSAGE("pascal");break;
917 case CC_STDCALL: MESSAGE("stdcall");break;
918 case CC_SYSCALL: MESSAGE("syscall");break;
921 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
922 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
923 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
926 void dump_IDLDESC(IDLDESC *idl) {
927 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
930 static char * typekind_desc[] =
943 void dump_TYPEATTR(TYPEATTR *tattr) {
945 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
946 MESSAGE("\tlcid: %ld\n",tattr->lcid);
947 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
948 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
949 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
950 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
951 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
952 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
953 MESSAGE("\tcVars: %d\n", tattr->cVars);
954 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
955 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
956 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
957 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
958 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
959 dump_TypeDesc(&tattr->tdescAlias,buf);
960 MESSAGE("\ttypedesc: %s\n", buf);
961 dump_IDLDESC(&tattr->idldescType);
964 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
967 if (!TRACE_ON(typelib))
969 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
970 for (i=0;i<pfd->funcdesc.cParams;i++)
971 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
974 dump_FUNCDESC(&(pfd->funcdesc));
976 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
977 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
979 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
983 dump_TLBFuncDescOne(pfd);
987 static void dump_TLBVarDesc(TLBVarDesc * pvd)
991 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
996 static void dump_TLBImpLib(TLBImpLib *import)
998 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
999 debugstr_w(import->name));
1000 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1001 import->wVersionMinor, import->lcid, import->offset);
1004 static void dump_TLBRefType(TLBRefType * prt)
1008 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1009 if(prt->index == -1)
1010 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1012 TRACE_(typelib)("type no: %d\n", prt->index);
1014 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1015 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1016 TRACE_(typelib)("in lib\n");
1017 dump_TLBImpLib(prt->pImpTLInfo);
1023 static void dump_TLBImplType(TLBImplType * impl)
1027 "implementing/inheriting interface hRef = %lx implflags %x\n",
1028 impl->hRef, impl->implflags);
1033 void dump_Variant(VARIANT * pvar)
1038 TRACE("(%p)\n", pvar);
1042 ZeroMemory(szVarType, sizeof(szVarType));
1044 /* FIXME : we could have better trace here, depending on the VARTYPE
1047 dump_VarType(V_VT(pvar),szVarType);
1049 TRACE("VARTYPE: %s\n", szVarType);
1051 if (V_VT(pvar) & VT_BYREF) {
1052 ref = V_UNION(pvar, byref);
1055 else ref = &V_UNION(pvar, cVal);
1057 if (V_VT(pvar) & VT_ARRAY) {
1061 if (V_VT(pvar) & VT_VECTOR) {
1066 switch (V_VT(pvar) & VT_TYPEMASK)
1069 TRACE("%d\n", *(short*)ref);
1074 TRACE("%u\n", *(UINT*)ref);
1079 TRACE("%d\n", *(INT*)ref);
1083 TRACE("%3.3e\n", *(float*)ref);
1087 TRACE("%3.3e\n", *(double*)ref);
1091 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1095 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1100 TRACE("%p\n", *(LPVOID*)ref);
1104 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1110 memset( &TM, 0, sizeof(TM) );
1112 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1113 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1115 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1116 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1117 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1123 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1128 TRACE("(?)%ld\n", *(long*)ref);
1133 static void dump_DispParms(DISPPARAMS * pdp)
1137 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1139 while (index < pdp->cArgs)
1141 dump_Variant( &pdp->rgvarg[index] );
1146 static void dump_TypeInfo(ITypeInfoImpl * pty)
1148 TRACE("%p ref=%u\n", pty, pty->ref);
1149 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1150 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1151 TRACE("fct:%u var:%u impl:%u\n",
1152 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1153 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1154 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1155 dump_TLBFuncDesc(pty->funclist);
1156 dump_TLBVarDesc(pty->varlist);
1157 dump_TLBImplType(pty->impltypelist);
1160 void dump_VARDESC(VARDESC *v)
1162 MESSAGE("memid %ld\n",v->memid);
1163 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1164 MESSAGE("oInst %ld\n",v->u.oInst);
1165 dump_ELEMDESC(&(v->elemdescVar));
1166 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1167 MESSAGE("varkind %d\n",v->varkind);
1170 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1172 /* VT_LPWSTR is largest type that */
1173 /* may appear in type description*/
1174 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1175 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1176 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1177 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1178 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1179 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1183 static void TLB_abort()
1187 static void * TLB_Alloc(unsigned size)
1190 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1192 ERR("cannot allocate memory\n");
1197 static void TLB_Free(void * ptr)
1199 HeapFree(GetProcessHeap(), 0, ptr);
1203 /**********************************************************************
1205 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1208 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1210 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1211 pcx->pos, count, pcx->oStart, pcx->length, where);
1213 if (where != DO_NOT_SEEK)
1215 where += pcx->oStart;
1216 if (where > pcx->length)
1219 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1224 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1225 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1230 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1235 ret = MSFT_Read(buffer, count, pcx, where);
1236 FromLEDWords(buffer, ret);
1241 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1246 ret = MSFT_Read(buffer, count, pcx, where);
1247 FromLEWords(buffer, ret);
1252 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1254 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1255 memset(pGuid,0, sizeof(GUID));
1258 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1259 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1260 pGuid->Data2 = FromLEWord(pGuid->Data2);
1261 pGuid->Data3 = FromLEWord(pGuid->Data3);
1262 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1265 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1268 MSFT_NameIntro niName;
1270 WCHAR* pwstring = NULL;
1271 BSTR bstrName = NULL;
1273 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1274 pcx->pTblDir->pNametab.offset+offset);
1275 niName.namelen &= 0xFF; /* FIXME: correct ? */
1276 name=TLB_Alloc((niName.namelen & 0xff) +1);
1277 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1278 name[niName.namelen & 0xff]='\0';
1280 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1283 /* no invalid characters in string */
1286 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1288 /* don't check for invalid character since this has been done previously */
1289 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1291 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1292 lengthInChars = SysStringLen(bstrName);
1293 HeapFree(GetProcessHeap(), 0, pwstring);
1296 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1300 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1307 if(offset<0) return NULL;
1308 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1309 if(length <= 0) return 0;
1310 string=TLB_Alloc(length +1);
1311 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1312 string[length]='\0';
1314 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1315 string, -1, NULL, 0);
1317 /* no invalid characters in string */
1320 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1322 /* don't check for invalid character since this has been done previously */
1323 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1325 bstr = SysAllocStringLen(pwstring, lengthInChars);
1326 lengthInChars = SysStringLen(bstr);
1327 HeapFree(GetProcessHeap(), 0, pwstring);
1330 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1334 * read a value and fill a VARIANT structure
1336 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1340 TRACE_(typelib)("\n");
1342 if(offset <0) { /* data are packed in here */
1343 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1344 V_UNION(pVar, iVal) = offset & 0xffff;
1347 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1348 pcx->pTblDir->pCustData.offset + offset );
1349 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1350 switch (V_VT(pVar)){
1351 case VT_EMPTY: /* FIXME: is this right? */
1352 case VT_NULL: /* FIXME: is this right? */
1353 case VT_I2 : /* this should not happen */
1364 case VT_VOID : /* FIXME: is this right? */
1372 case VT_DECIMAL : /* FIXME: is this right? */
1375 /* pointer types with known behaviour */
1378 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1380 FIXME("BSTR length = %d?\n", size);
1382 ptr=TLB_Alloc(size);/* allocate temp buffer */
1383 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1384 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1385 /* FIXME: do we need a AtoW conversion here? */
1386 V_UNION(pVar, bstrVal[size])=L'\0';
1387 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1392 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1399 case VT_USERDEFINED :
1405 case VT_STREAMED_OBJECT :
1406 case VT_STORED_OBJECT :
1407 case VT_BLOB_OBJECT :
1412 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1416 if(size>0) /* (big|small) endian correct? */
1417 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1421 * create a linked list with custom data
1423 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1429 TRACE_(typelib)("\n");
1433 pNew=TLB_Alloc(sizeof(TLBCustData));
1434 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1435 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1436 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1437 /* add new custom data at head of the list */
1438 pNew->next=*ppCustData;
1440 offset = entry.next;
1445 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1449 pTd->vt=type & VT_TYPEMASK;
1451 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1453 if(pTd->vt == VT_USERDEFINED)
1454 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1456 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1460 MSFT_DoFuncs(TLBContext* pcx,
1465 TLBFuncDesc** pptfd)
1468 * member information is stored in a data structure at offset
1469 * indicated by the memoffset field of the typeinfo structure
1470 * There are several distinctive parts.
1471 * the first part starts with a field that holds the total length
1472 * of this (first) part excluding this field. Then follow the records,
1473 * for each member there is one record.
1475 * First entry is always the length of the record (excluding this
1477 * Rest of the record depends on the type of the member. If there is
1478 * a field indicating the member type (function variable intereface etc)
1479 * I have not found it yet. At this time we depend on the information
1480 * in the type info and the usual order how things are stored.
1482 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1485 * Third is a equal sized array with file offsets to the name entry
1488 * Forth and last (?) part is an array with offsets to the records in the
1489 * first part of this file segment.
1492 int infolen, nameoffset, reclength, nrattributes, i;
1493 int recoffset = offset + sizeof(INT);
1496 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1498 TRACE_(typelib)("\n");
1500 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1502 for ( i = 0; i < cFuncs ; i++ )
1504 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1506 /* name, eventually add to a hash table */
1507 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1508 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1510 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1512 /* read the function information record */
1513 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1517 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1519 /* do the attributes */
1520 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1523 if ( nrattributes > 0 )
1525 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1527 if ( nrattributes > 1 )
1529 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1530 pFuncRec->OptAttr[1]) ;
1532 if ( nrattributes > 2 )
1534 if ( pFuncRec->FKCCIC & 0x2000 )
1536 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1540 (*pptfd)->Entry = MSFT_ReadString(pcx,
1541 pFuncRec->OptAttr[2]);
1543 if( nrattributes > 5 )
1545 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1547 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1550 pFuncRec->OptAttr[6],
1551 &(*pptfd)->pCustData);
1558 /* fill the FuncDesc Structure */
1559 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1560 offset + infolen + ( i + 1) * sizeof(INT));
1562 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1563 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1564 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1565 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1566 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1567 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1568 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1572 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1575 /* do the parameters/arguments */
1576 if(pFuncRec->nrargs)
1579 MSFT_ParameterInfo paraminfo;
1581 (*pptfd)->funcdesc.lprgelemdescParam =
1582 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1584 (*pptfd)->pParamDesc =
1585 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1587 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1588 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1590 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1592 TYPEDESC* lpArgTypeDesc = 0;
1596 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1599 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1601 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1603 /* SEEK value = jump to offset,
1604 * from there jump to the end of record,
1605 * go back by (j-1) arguments
1607 MSFT_ReadLEDWords( ¶minfo ,
1608 sizeof(MSFT_ParameterInfo), pcx,
1609 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1610 * sizeof(MSFT_ParameterInfo)));
1612 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1614 while ( lpArgTypeDesc != NULL )
1616 switch ( lpArgTypeDesc->vt )
1619 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1623 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1626 case VT_USERDEFINED:
1627 MSFT_DoRefType(pcx, pTI,
1628 lpArgTypeDesc->u.hreftype);
1630 lpArgTypeDesc = NULL;
1634 lpArgTypeDesc = NULL;
1640 /* parameter is the return value! */
1641 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1643 TYPEDESC* lpArgTypeDesc;
1645 (*pptfd)->funcdesc.elemdescFunc =
1646 (*pptfd)->funcdesc.lprgelemdescParam[j];
1648 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1650 while ( lpArgTypeDesc != NULL )
1652 switch ( lpArgTypeDesc->vt )
1655 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1659 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1663 case VT_USERDEFINED:
1666 lpArgTypeDesc->u.hreftype);
1668 lpArgTypeDesc = NULL;
1672 lpArgTypeDesc = NULL;
1677 /* second time around */
1678 for(j=0;j<pFuncRec->nrargs;j++)
1681 (*pptfd)->pParamDesc[j].Name =
1682 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1685 if ( (PARAMFLAG_FHASDEFAULT &
1686 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1687 ((pFuncRec->FKCCIC) & 0x1000) )
1689 INT* pInt = (INT *)((char *)pFuncRec +
1691 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1693 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1695 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1696 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1698 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1702 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1705 pFuncRec->OptAttr[7+j],
1706 &(*pptfd)->pParamDesc[j].pCustData);
1711 /* scode is not used: archaic win16 stuff FIXME: right? */
1712 (*pptfd)->funcdesc.cScodes = 0 ;
1713 (*pptfd)->funcdesc.lprgscode = NULL ;
1715 pptfd = & ((*pptfd)->next);
1716 recoffset += reclength;
1720 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1721 int cVars, int offset, TLBVarDesc ** pptvd)
1723 int infolen, nameoffset, reclength;
1725 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1729 TRACE_(typelib)("\n");
1731 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1732 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1733 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1734 recoffset += offset+sizeof(INT);
1735 for(i=0;i<cVars;i++){
1736 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1737 /* name, eventually add to a hash table */
1738 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1739 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1740 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1741 /* read the variable information record */
1742 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1744 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1746 if(reclength >(6*sizeof(INT)) )
1747 (*pptvd)->HelpContext=pVarRec->HelpContext;
1748 if(reclength >(7*sizeof(INT)) )
1749 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1750 if(reclength >(8*sizeof(INT)) )
1751 if(reclength >(9*sizeof(INT)) )
1752 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1753 /* fill the VarDesc Structure */
1754 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1755 offset + infolen + ( i + 1) * sizeof(INT));
1756 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1757 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1758 MSFT_GetTdesc(pcx, pVarRec->DataType,
1759 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1760 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1761 if(pVarRec->VarKind == VAR_CONST ){
1762 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1763 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1764 pVarRec->OffsValue, pcx);
1766 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1767 pptvd=&((*pptvd)->next);
1768 recoffset += reclength;
1771 /* fill in data for a hreftype (offset). When the refernced type is contained
1772 * in the typelib, it's just an (file) offset in the type info base dir.
1773 * If comes from import, it's an offset+1 in the ImpInfo table
1775 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1779 TLBRefType **ppRefType = &pTI->reflist;
1781 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1784 if((*ppRefType)->reference == offset)
1786 ppRefType = &(*ppRefType)->next;
1789 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1790 sizeof(**ppRefType));
1792 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1793 /* external typelib */
1794 MSFT_ImpInfo impinfo;
1795 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1797 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1799 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1800 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1801 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1802 if(pImpLib->offset==impinfo.oImpFile) break;
1803 pImpLib=pImpLib->next;
1806 (*ppRefType)->reference=offset;
1807 (*ppRefType)->pImpTLInfo = pImpLib;
1808 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1809 (*ppRefType)->index = TLB_REF_USE_GUID;
1811 ERR("Cannot find a reference\n");
1812 (*ppRefType)->reference=-1;
1813 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1816 /* in this typelib */
1817 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1818 (*ppRefType)->reference=offset;
1819 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1823 /* process Implemented Interfaces of a com class */
1824 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1828 MSFT_RefRecord refrec;
1829 TLBImplType **ppImpl = &pTI->impltypelist;
1831 TRACE_(typelib)("\n");
1833 for(i=0;i<count;i++){
1834 if(offset<0) break; /* paranoia */
1835 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1836 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1837 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1838 (*ppImpl)->hRef = refrec.reftype;
1839 (*ppImpl)->implflags=refrec.flags;
1840 (*ppImpl)->ctCustData=
1841 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1842 offset=refrec.onext;
1843 ppImpl=&((*ppImpl)->next);
1847 * process a typeinfo record
1849 ITypeInfoImpl * MSFT_DoTypeInfo(
1852 ITypeLibImpl * pLibInfo)
1854 MSFT_TypeInfoBase tiBase;
1855 ITypeInfoImpl *ptiRet;
1857 TRACE_(typelib)("count=%u\n", count);
1859 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1860 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1861 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1862 /* this is where we are coming from */
1863 ptiRet->pTypeLib = pLibInfo;
1864 ptiRet->index=count;
1865 /* fill in the typeattr fields */
1866 WARN("Assign constructor/destructor memid\n");
1868 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1869 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1870 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1871 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1872 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1873 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1874 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1875 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1876 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1877 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1878 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1879 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1880 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1881 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1882 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1883 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1884 MSFT_GetTdesc(pcx, tiBase.datatype1,
1885 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1888 /* IDLDESC idldescType; *//* never saw this one != zero */
1890 /* name, eventually add to a hash table */
1891 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1892 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1894 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1895 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1896 ptiRet->dwHelpContext=tiBase.helpcontext;
1897 /* note: InfoType's Help file and HelpStringDll come from the containing
1898 * library. Further HelpString and Docstring appear to be the same thing :(
1901 if(ptiRet->TypeAttr.cFuncs >0 )
1902 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1903 ptiRet->TypeAttr.cVars,
1904 tiBase.memoffset, & ptiRet->funclist);
1906 if(ptiRet->TypeAttr.cVars >0 )
1907 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1908 ptiRet->TypeAttr.cVars,
1909 tiBase.memoffset, & ptiRet->varlist);
1910 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1911 switch(ptiRet->TypeAttr.typekind)
1914 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1917 case TKIND_DISPATCH:
1918 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1920 if (tiBase.datatype1 != -1)
1922 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1923 ptiRet->impltypelist->hRef = tiBase.datatype1;
1926 { /* FIXME: This is a really bad hack to add IDispatch */
1927 char* szStdOle = "stdole2.tlb\0";
1928 int nStdOleLen = strlen(szStdOle);
1929 TLBRefType **ppRef = &ptiRet->reflist;
1932 if((*ppRef)->reference == -1)
1934 ppRef = &(*ppRef)->next;
1937 *ppRef = TLB_Alloc(sizeof(**ppRef));
1938 (*ppRef)->guid = IID_IDispatch;
1939 (*ppRef)->reference = -1;
1940 (*ppRef)->index = TLB_REF_USE_GUID;
1941 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1942 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1943 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1946 MultiByteToWideChar(CP_ACP,
1950 (*ppRef)->pImpTLInfo->name,
1951 SysStringLen((*ppRef)->pImpTLInfo->name));
1953 (*ppRef)->pImpTLInfo->lcid = 0;
1954 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1955 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1960 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1961 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1962 ptiRet->impltypelist->hRef = tiBase.datatype1;
1967 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1969 TRACE_(typelib)("%s guid: %s kind:%s\n",
1970 debugstr_w(ptiRet->Name),
1971 debugstr_guid(&ptiRet->TypeAttr.guid),
1972 typekind_desc[ptiRet->TypeAttr.typekind]);
1977 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
1978 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
1979 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
1982 static ITypeLibImpl *tlb_cache_first;
1983 static CRITICAL_SECTION cache_section;
1984 static CRITICAL_SECTION_DEBUG cache_section_debug =
1986 0, 0, &cache_section,
1987 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
1988 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
1990 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
1993 /****************************************************************************
1996 * find the type of the typelib file and map the typelib resource into
1999 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2000 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2001 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2003 ITypeLibImpl *entry;
2004 int ret = TYPE_E_CANTLOADLIBRARY;
2005 DWORD dwSignature = 0;
2008 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2012 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2013 EnterCriticalSection(&cache_section);
2014 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2016 if (!strcmpiW(entry->path, pszFileName))
2018 TRACE("cache hit\n");
2019 *ppTypeLib = (ITypeLib2*)entry;
2020 ITypeLib_AddRef(*ppTypeLib);
2021 LeaveCriticalSection(&cache_section);
2025 LeaveCriticalSection(&cache_section);
2027 /* check the signature of the file */
2028 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2029 if (INVALID_HANDLE_VALUE != hFile)
2031 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2034 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2037 /* retrieve file size */
2038 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2040 /* first try to load as *.tlb */
2041 dwSignature = FromLEDWord(*((DWORD*) pBase));
2042 if ( dwSignature == MSFT_SIGNATURE)
2044 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2046 else if ( dwSignature == SLTG_SIGNATURE)
2048 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2050 UnmapViewOfFile(pBase);
2052 CloseHandle(hMapping);
2057 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2059 /* find the typelibrary resource*/
2060 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2061 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2064 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2068 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2071 LPVOID pBase = LockResource(hGlobal);
2072 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2076 /* try to load as incore resource */
2077 dwSignature = FromLEDWord(*((DWORD*) pBase));
2078 if ( dwSignature == MSFT_SIGNATURE)
2080 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2082 else if ( dwSignature == SLTG_SIGNATURE)
2084 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2088 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2091 FreeResource( hGlobal );
2094 FreeLibrary(hinstDLL);
2099 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2101 TRACE("adding to cache\n");
2102 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2103 lstrcpyW(impl->path, pszFileName);
2104 /* We should really canonicalise the path here. */
2106 /* FIXME: check if it has added already in the meantime */
2107 EnterCriticalSection(&cache_section);
2108 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2110 tlb_cache_first = impl;
2111 LeaveCriticalSection(&cache_section);
2114 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2119 /*================== ITypeLib(2) Methods ===================================*/
2121 /****************************************************************************
2122 * ITypeLib2_Constructor_MSFT
2124 * loading an MSFT typelib from an in-memory image
2126 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2130 MSFT_Header tlbHeader;
2131 MSFT_SegDir tlbSegDir;
2132 ITypeLibImpl * pTypeLibImpl;
2134 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2136 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2137 if (!pTypeLibImpl) return NULL;
2139 pTypeLibImpl->lpVtbl = &tlbvt;
2140 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2141 pTypeLibImpl->ref = 1;
2143 /* get pointer to beginning of typelib data */
2147 cx.pLibInfo = pTypeLibImpl;
2148 cx.length = dwTLBLength;
2151 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2153 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2154 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2155 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2158 /* there is a small amount of information here until the next important
2160 * the segment directory . Try to calculate the amount of data */
2161 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2163 /* now read the segment directory */
2164 TRACE("read segment directory (at %ld)\n",lPSegDir);
2165 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2166 cx.pTblDir = &tlbSegDir;
2168 /* just check two entries */
2169 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2171 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2172 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2176 /* now fill our internal data */
2177 /* TLIBATTR fields */
2178 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2180 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2181 /* Windows seems to have zero here, is this correct? */
2182 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2183 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2185 pTypeLibImpl->LibAttr.lcid = 0;
2187 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2188 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2189 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2190 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2192 /* name, eventually add to a hash table */
2193 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2196 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2197 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2199 if( tlbHeader.varflags & HELPDLLFLAG)
2202 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2203 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2206 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2209 if(tlbHeader.CustomDataOffset >= 0)
2211 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2214 /* fill in typedescriptions */
2215 if(tlbSegDir.pTypdescTab.length > 0)
2217 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2219 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2220 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2223 /* FIXME: add several sanity checks here */
2224 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2225 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2227 /* FIXME: check safearray */
2229 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2231 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2233 else if(td[0] == VT_CARRAY)
2235 /* array descr table here */
2236 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2238 else if(td[0] == VT_USERDEFINED)
2240 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2242 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2245 /* second time around to fill the array subscript info */
2248 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2249 if(tlbSegDir.pArrayDescriptions.offset>0)
2251 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2252 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2255 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2257 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2259 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2261 for(j = 0; j<td[2]; j++)
2263 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2264 sizeof(INT), &cx, DO_NOT_SEEK);
2265 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2266 sizeof(INT), &cx, DO_NOT_SEEK);
2271 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2272 ERR("didn't find array description data\n");
2277 /* imported type libs */
2278 if(tlbSegDir.pImpFiles.offset>0)
2280 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2281 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2284 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2286 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2287 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2288 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2290 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2291 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2292 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2293 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2296 (*ppImpLib)->name = TLB_Alloc(size+1);
2297 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2298 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2299 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2301 ppImpLib = &(*ppImpLib)->next;
2306 if(tlbHeader.nrtypeinfos >= 0 )
2308 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2309 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2312 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2314 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2316 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2317 ppTI = &((*ppTI)->next);
2318 (pTypeLibImpl->TypeInfoCount)++;
2322 TRACE("(%p)\n", pTypeLibImpl);
2323 return (ITypeLib2*) pTypeLibImpl;
2327 static BSTR TLB_MultiByteToBSTR(char *ptr)
2333 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2334 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2335 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2336 ret = SysAllocString(nameW);
2337 HeapFree(GetProcessHeap(), 0, nameW);
2341 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2347 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2348 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2352 guid->Data4[0] = s >> 8;
2353 guid->Data4[1] = s & 0xff;
2356 for(i = 0; i < 6; i++) {
2357 memcpy(b, str + 24 + 2 * i, 2);
2358 guid->Data4[i + 2] = strtol(b, NULL, 16);
2363 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2370 bytelen = *(WORD*)ptr;
2371 if(bytelen == 0xffff) return 2;
2372 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2373 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2374 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2375 *pBstr = SysAllocStringLen(nameW, len);
2376 HeapFree(GetProcessHeap(), 0, nameW);
2380 static WORD SLTG_ReadStringA(char *ptr, char **str)
2385 bytelen = *(WORD*)ptr;
2386 if(bytelen == 0xffff) return 2;
2387 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2388 memcpy(*str, ptr + 2, bytelen);
2389 (*str)[bytelen] = '\0';
2393 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2395 char *ptr = pLibBlk;
2398 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2399 FIXME("libblk magic = %04x\n", w);
2404 if((w = *(WORD*)ptr) != 0xffff) {
2405 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2410 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2412 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2414 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2417 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2420 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2423 ptr += 4; /* skip res12 */
2425 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2428 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2431 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2434 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2435 ptr += sizeof(GUID);
2437 return ptr - (char*)pLibBlk;
2440 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2443 TYPEDESC *pTD = &pElem->tdesc;
2445 /* Handle [in/out] first */
2446 if((*pType & 0xc000) == 0xc000)
2447 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2448 else if(*pType & 0x8000)
2449 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2450 else if(*pType & 0x4000)
2451 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2453 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2456 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2459 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2462 if((*pType & 0xe00) == 0xe00) {
2464 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2466 pTD = pTD->u.lptdesc;
2468 switch(*pType & 0x7f) {
2471 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2473 pTD = pTD->u.lptdesc;
2476 case VT_USERDEFINED:
2477 pTD->vt = VT_USERDEFINED;
2478 pTD->u.hreftype = *(++pType) / 4;
2484 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2487 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2489 pTD->vt = VT_CARRAY;
2490 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2492 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2493 pTD->u.lpadesc->cDims = pSA->cDims;
2494 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2495 pSA->cDims * sizeof(SAFEARRAYBOUND));
2497 pTD = &pTD->u.lpadesc->tdescElem;
2503 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2507 pTD->vt = VT_SAFEARRAY;
2508 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2510 pTD = pTD->u.lptdesc;
2514 pTD->vt = *pType & 0x7f;
2524 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2529 TLBRefType **ppRefType;
2531 if(pRef->magic != SLTG_REF_MAGIC) {
2532 FIXME("Ref magic = %x\n", pRef->magic);
2535 name = ( (char*)(&pRef->names) + pRef->number);
2537 ppRefType = &pTI->reflist;
2538 for(ref = 0; ref < pRef->number >> 3; ref++) {
2540 unsigned int lib_offs, type_num;
2542 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2543 sizeof(**ppRefType));
2545 name += SLTG_ReadStringA(name, &refname);
2546 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2547 FIXME("Can't sscanf ref\n");
2548 if(lib_offs != 0xffff) {
2549 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2552 if((*import)->offset == lib_offs)
2554 import = &(*import)->next;
2557 char fname[MAX_PATH+1];
2560 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2562 (*import)->offset = lib_offs;
2563 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2565 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2566 &(*import)->wVersionMajor,
2567 &(*import)->wVersionMinor,
2568 &(*import)->lcid, fname) != 4) {
2569 FIXME("can't sscanf ref %s\n",
2570 pNameTable + lib_offs + 40);
2572 len = strlen(fname);
2573 if(fname[len-1] != '#')
2574 FIXME("fname = %s\n", fname);
2575 fname[len-1] = '\0';
2576 (*import)->name = TLB_MultiByteToBSTR(fname);
2578 (*ppRefType)->pImpTLInfo = *import;
2579 } else { /* internal ref */
2580 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2582 (*ppRefType)->reference = ref;
2583 (*ppRefType)->index = type_num;
2585 HeapFree(GetProcessHeap(), 0, refname);
2586 ppRefType = &(*ppRefType)->next;
2588 if((BYTE)*name != SLTG_REF_MAGIC)
2589 FIXME("End of ref block magic = %x\n", *name);
2590 dump_TLBRefType(pTI->reflist);
2593 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2596 SLTG_ImplInfo *info;
2597 TLBImplType **ppImplType = &pTI->impltypelist;
2598 /* I don't really get this structure, usually it's 0x16 bytes
2599 long, but iuser.tlb contains some that are 0x18 bytes long.
2600 That's ok because we can use the next ptr to jump to the next
2601 one. But how do we know the length of the last one? The WORD
2602 at offs 0x8 might be the clue. For now I'm just assuming that
2603 the last one is the regular 0x16 bytes. */
2605 info = (SLTG_ImplInfo*)pBlk;
2607 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2608 sizeof(**ppImplType));
2609 (*ppImplType)->hRef = info->ref;
2610 (*ppImplType)->implflags = info->impltypeflags;
2611 pTI->TypeAttr.cImplTypes++;
2612 ppImplType = &(*ppImplType)->next;
2614 if(info->next == 0xffff)
2617 FIXME("Interface inheriting more than one interface\n");
2618 info = (SLTG_ImplInfo*)(pBlk + info->next);
2620 info++; /* see comment at top of function */
2624 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2627 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2628 SLTG_MemberHeader *pMemHeader;
2629 char *pFirstItem, *pNextItem;
2631 if(pTIHeader->href_table != 0xffffffff) {
2632 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2637 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2639 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2641 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2642 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2645 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2649 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2652 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2653 SLTG_MemberHeader *pMemHeader;
2654 SLTG_Function *pFunc;
2655 char *pFirstItem, *pNextItem;
2656 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2659 if(pTIHeader->href_table != 0xffffffff) {
2660 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2664 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2666 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2668 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2669 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2672 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2673 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2678 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2679 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2680 FIXME("func magic = %02x\n", pFunc->magic);
2683 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2684 sizeof(**ppFuncDesc));
2685 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2687 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2688 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2689 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2690 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2691 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2692 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2694 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2695 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2697 if(pFunc->retnextopt & 0x80)
2698 pType = &pFunc->rettype;
2700 pType = (WORD*)(pFirstItem + pFunc->rettype);
2703 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2705 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2706 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2707 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2708 (*ppFuncDesc)->pParamDesc =
2709 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2710 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2712 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2714 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2715 char *paramName = pNameTable + *pArg;
2717 /* If arg type follows then paramName points to the 2nd
2718 letter of the name, else the next WORD is an offset to
2719 the arg type and paramName points to the first letter.
2720 So let's take one char off paramName and see if we're
2721 pointing at an alpha-numeric char. However if *pArg is
2722 0xffff or 0xfffe then the param has no name, the former
2723 meaning that the next WORD is the type, the latter
2724 meaning the the next WORD is an offset to the type. */
2729 else if(*pArg == 0xfffe) {
2733 else if(!isalnum(*(paramName-1)))
2738 if(HaveOffs) { /* the next word is an offset to type */
2739 pType = (WORD*)(pFirstItem + *pArg);
2740 SLTG_DoType(pType, pFirstItem,
2741 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2746 pArg = SLTG_DoType(pArg, pFirstItem,
2747 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2750 /* Are we an optional param ? */
2751 if((*ppFuncDesc)->funcdesc.cParams - param <=
2752 (*ppFuncDesc)->funcdesc.cParamsOpt)
2753 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2756 (*ppFuncDesc)->pParamDesc[param].Name =
2757 TLB_MultiByteToBSTR(paramName);
2761 ppFuncDesc = &((*ppFuncDesc)->next);
2762 if(pFunc->next == 0xffff) break;
2764 pTI->TypeAttr.cFuncs = num;
2765 dump_TLBFuncDesc(pTI->funclist);
2766 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2769 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2772 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2773 SLTG_MemberHeader *pMemHeader;
2774 SLTG_RecordItem *pItem;
2776 TLBVarDesc **ppVarDesc = &pTI->varlist;
2781 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2783 pFirstItem = (char*)(pMemHeader + 1);
2784 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2785 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2786 if(pItem->magic != SLTG_RECORD_MAGIC) {
2787 FIXME("record magic = %02x\n", pItem->magic);
2790 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2791 sizeof(**ppVarDesc));
2792 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2793 (*ppVarDesc)->vardesc.memid = pItem->memid;
2794 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2795 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2797 if(pItem->typepos == 0x02)
2798 pType = &pItem->type;
2799 else if(pItem->typepos == 0x00)
2800 pType = (WORD*)(pFirstItem + pItem->type);
2802 FIXME("typepos = %02x\n", pItem->typepos);
2806 SLTG_DoType(pType, pFirstItem,
2807 &(*ppVarDesc)->vardesc.elemdescVar);
2809 /* FIXME("helpcontext, helpstring\n"); */
2811 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2813 ppVarDesc = &((*ppVarDesc)->next);
2814 if(pItem->next == 0xffff) break;
2816 pTI->TypeAttr.cVars = num;
2817 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2820 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2823 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2824 SLTG_MemberHeader *pMemHeader;
2825 SLTG_AliasItem *pItem;
2828 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2829 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2832 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2833 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2834 if (pItem->vt == 0xffff) {
2835 if (i<(pMemHeader->cbExtra/4-1))
2836 FIXME("Endmarker too early in process alias data!\n");
2840 FIXME("Chain extends over last entry?\n");
2843 if (pItem->vt == VT_USERDEFINED) {
2844 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2845 /* guessing here ... */
2846 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2847 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2850 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2851 FIXME("alias %d: 0x%x\n",i,pItem->res02);
2855 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2858 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
2861 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2862 SLTG_MemberHeader *pMemHeader;
2863 SLTG_AliasItem *pItem;
2865 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2866 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2867 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
2868 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
2869 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2872 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2875 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2876 SLTG_MemberHeader *pMemHeader;
2877 SLTG_EnumItem *pItem;
2879 TLBVarDesc **ppVarDesc = &pTI->varlist;
2882 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2884 pFirstItem = (char*)(pMemHeader + 1);
2885 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2886 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2887 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2888 FIXME("enumitem magic = %04x\n", pItem->magic);
2891 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2892 sizeof(**ppVarDesc));
2893 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2894 (*ppVarDesc)->vardesc.memid = pItem->memid;
2895 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2897 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2898 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2899 *(INT*)(pItem->value + pFirstItem);
2900 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2901 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2902 /* FIXME("helpcontext, helpstring\n"); */
2904 ppVarDesc = &((*ppVarDesc)->next);
2905 if(pItem->next == 0xffff) break;
2907 pTI->TypeAttr.cVars = num;
2908 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2911 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2912 managable copy of it into this */
2925 } SLTG_InternalOtherTypeInfo;
2927 /****************************************************************************
2928 * ITypeLib2_Constructor_SLTG
2930 * loading a SLTG typelib from an in-memory image
2932 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2934 ITypeLibImpl *pTypeLibImpl;
2935 SLTG_Header *pHeader;
2936 SLTG_BlkEntry *pBlkEntry;
2940 LPVOID pBlk, pFirstBlk;
2941 SLTG_LibBlk *pLibBlk;
2942 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2943 char *pAfterOTIBlks = NULL;
2944 char *pNameTable, *ptr;
2947 ITypeInfoImpl **ppTypeInfoImpl;
2949 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2951 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2952 if (!pTypeLibImpl) return NULL;
2954 pTypeLibImpl->lpVtbl = &tlbvt;
2955 pTypeLibImpl->ref = 1;
2960 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2961 pHeader->nrOfFileBlks );
2962 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2963 FIXME("Header type magic 0x%08lx not supported.\n",
2964 pHeader->SLTG_magic);
2968 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2969 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2971 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2972 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2974 /* Next we have a magic block */
2975 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2977 /* Let's see if we're still in sync */
2978 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2979 sizeof(SLTG_COMPOBJ_MAGIC))) {
2980 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2983 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2984 sizeof(SLTG_DIR_MAGIC))) {
2985 FIXME("dir magic = %s\n", pMagic->dir_magic);
2989 pIndex = (SLTG_Index*)(pMagic+1);
2991 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2993 pFirstBlk = (LPVOID)(pPad9 + 1);
2995 /* We'll set up a ptr to the main library block, which is the last one. */
2997 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2998 pBlkEntry[order].next != 0;
2999 order = pBlkEntry[order].next - 1, i++) {
3000 pBlk = (char*)pBlk + pBlkEntry[order].len;
3004 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3006 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3011 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3013 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3014 sizeof(*pOtherTypeInfoBlks) *
3015 pTypeLibImpl->TypeInfoCount);
3018 ptr = (char*)pLibBlk + len;
3020 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3024 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3026 w = *(WORD*)(ptr + 2);
3029 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3031 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3032 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3034 w = *(WORD*)(ptr + 4 + len);
3036 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3038 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3040 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3041 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3043 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3044 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3045 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3047 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3049 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3052 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3053 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3054 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3055 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3056 len += sizeof(SLTG_OtherTypeInfo);
3060 pAfterOTIBlks = ptr;
3062 /* Skip this WORD and get the next DWORD */
3063 len = *(DWORD*)(pAfterOTIBlks + 2);
3065 /* Now add this to pLibBLk look at what we're pointing at and
3066 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3067 dust and we should be pointing at the beginning of the name
3070 pNameTable = (char*)pLibBlk + len;
3072 switch(*(WORD*)pNameTable) {
3079 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3083 pNameTable += 0x216;
3087 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3089 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3092 /* Hopefully we now have enough ptrs set up to actually read in
3093 some TypeInfos. It's not clear which order to do them in, so
3094 I'll just follow the links along the BlkEntry chain and read
3095 them in in the order in which they're in the file */
3097 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3099 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3100 pBlkEntry[order].next != 0;
3101 order = pBlkEntry[order].next - 1, i++) {
3103 SLTG_TypeInfoHeader *pTIHeader;
3104 SLTG_TypeInfoTail *pTITail;
3106 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3107 pOtherTypeInfoBlks[i].index_name)) {
3108 FIXME("Index strings don't match\n");
3113 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3114 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3117 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3118 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3119 (*ppTypeInfoImpl)->index = i;
3120 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3121 pOtherTypeInfoBlks[i].name_offs +
3123 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3124 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3126 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3127 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3128 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3129 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3130 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3132 if((pTIHeader->typeflags1 & 7) != 2)
3133 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3134 if(pTIHeader->typeflags3 != 2)
3135 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3137 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3138 debugstr_w((*ppTypeInfoImpl)->Name),
3139 typekind_desc[pTIHeader->typekind],
3140 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3141 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3143 switch(pTIHeader->typekind) {
3145 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3149 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3152 case TKIND_INTERFACE:
3153 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3157 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3161 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3162 if (pTITail->tdescalias_vt)
3163 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3166 case TKIND_DISPATCH:
3167 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3171 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3177 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3178 but we've already set those */
3179 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3180 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3181 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3183 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3205 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3206 pBlk = (char*)pBlk + pBlkEntry[order].len;
3209 if(i != pTypeLibImpl->TypeInfoCount) {
3210 FIXME("Somehow processed %d TypeInfos\n", i);
3214 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3215 return (ITypeLib2*)pTypeLibImpl;
3218 /* ITypeLib::QueryInterface
3220 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3225 ICOM_THIS( ITypeLibImpl, iface);
3227 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3230 if(IsEqualIID(riid, &IID_IUnknown) ||
3231 IsEqualIID(riid,&IID_ITypeLib)||
3232 IsEqualIID(riid,&IID_ITypeLib2))
3239 ITypeLib2_AddRef(iface);
3240 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3243 TRACE("-- Interface: E_NOINTERFACE\n");
3244 return E_NOINTERFACE;
3249 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3251 ICOM_THIS( ITypeLibImpl, iface);
3253 TRACE("(%p)->ref was %u\n",This, This->ref);
3255 return ++(This->ref);
3258 /* ITypeLib::Release
3260 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3262 ICOM_THIS( ITypeLibImpl, iface);
3266 TRACE("(%p)->(%u)\n",This, This->ref);
3270 /* remove cache entry */
3271 TRACE("removing from cache list\n");
3272 EnterCriticalSection(&cache_section);
3273 if (This->next) This->next->prev = This->prev;
3274 if (This->prev) This->prev->next = This->next;
3275 else tlb_cache_first = This->next;
3276 LeaveCriticalSection(&cache_section);
3278 /* FIXME destroy child objects */
3279 TRACE(" destroying ITypeLib(%p)\n",This);
3283 SysFreeString(This->Name);
3287 if (This->DocString)
3289 SysFreeString(This->DocString);
3290 This->DocString = NULL;
3295 SysFreeString(This->HelpFile);
3296 This->HelpFile = NULL;
3299 if (This->HelpStringDll)
3301 SysFreeString(This->HelpStringDll);
3302 This->HelpStringDll = NULL;
3305 if (This->pTypeInfo) /* can be NULL */
3306 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3307 HeapFree(GetProcessHeap(),0,This);
3314 /* ITypeLib::GetTypeInfoCount
3316 * Returns the number of type descriptions in the type library
3318 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3320 ICOM_THIS( ITypeLibImpl, iface);
3321 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3322 return This->TypeInfoCount;
3325 /* ITypeLib::GetTypeInfo
3327 * retrieves the specified type description in the library.
3329 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3332 ITypeInfo **ppTInfo)
3336 ICOM_THIS( ITypeLibImpl, iface);
3337 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3339 TRACE("(%p)->(index=%d) \n", This, index);
3341 if (!ppTInfo) return E_INVALIDARG;
3343 /* search element n in list */
3344 for(i=0; i < index; i++)
3346 pTypeInfo = pTypeInfo->next;
3349 TRACE("-- element not found\n");
3350 return TYPE_E_ELEMENTNOTFOUND;
3354 *ppTInfo = (ITypeInfo *) pTypeInfo;
3356 ITypeInfo_AddRef(*ppTInfo);
3357 TRACE("-- found (%p)\n",*ppTInfo);
3362 /* ITypeLibs::GetTypeInfoType
3364 * Retrieves the type of a type description.
3366 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3371 ICOM_THIS( ITypeLibImpl, iface);
3373 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3375 TRACE("(%p) index %d \n",This, index);
3377 if(!pTKind) return E_INVALIDARG;
3379 /* search element n in list */
3380 for(i=0; i < index; i++)
3384 TRACE("-- element not found\n");
3385 return TYPE_E_ELEMENTNOTFOUND;
3387 pTInfo = pTInfo->next;
3390 *pTKind = pTInfo->TypeAttr.typekind;
3391 TRACE("-- found Type (%d)\n", *pTKind);
3395 /* ITypeLib::GetTypeInfoOfGuid
3397 * Retrieves the type description that corresponds to the specified GUID.
3400 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3403 ITypeInfo **ppTInfo)
3405 ICOM_THIS( ITypeLibImpl, iface);
3406 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3408 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3410 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3412 /* search linked list for guid */
3413 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3415 pTypeInfo = pTypeInfo->next;
3419 /* end of list reached */
3420 TRACE("-- element not found\n");
3421 return TYPE_E_ELEMENTNOTFOUND;
3425 TRACE("-- found (%p, %s)\n",
3427 debugstr_w(pTypeInfo->Name));
3429 *ppTInfo = (ITypeInfo*)pTypeInfo;
3430 ITypeInfo_AddRef(*ppTInfo);
3434 /* ITypeLib::GetLibAttr
3436 * Retrieves the structure that contains the library's attributes.
3439 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3441 LPTLIBATTR *ppTLibAttr)
3443 ICOM_THIS( ITypeLibImpl, iface);
3444 TRACE("(%p)\n",This);
3445 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3446 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3450 /* ITypeLib::GetTypeComp
3452 * Enables a client compiler to bind to a library's types, variables,
3453 * constants, and global functions.
3456 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3458 ITypeComp **ppTComp)
3460 ICOM_THIS( ITypeLibImpl, iface);
3462 TRACE("(%p)->(%p)\n",This,ppTComp);
3463 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3464 ITypeComp_AddRef(*ppTComp);
3469 /* ITypeLib::GetDocumentation
3471 * Retrieves the library's documentation string, the complete Help file name
3472 * and path, and the context identifier for the library Help topic in the Help
3475 * On a successful return all non-null BSTR pointers will have been set,
3478 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3482 BSTR *pBstrDocString,
3483 DWORD *pdwHelpContext,
3484 BSTR *pBstrHelpFile)
3486 ICOM_THIS( ITypeLibImpl, iface);
3488 HRESULT result = E_INVALIDARG;
3493 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3495 pBstrName, pBstrDocString,
3496 pdwHelpContext, pBstrHelpFile);
3500 /* documentation for the typelib */
3504 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3510 if (This->DocString)
3511 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3512 else if (This->Name)
3513 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3515 *pBstrDocString = NULL;
3519 *pdwHelpContext = This->dwHelpContext;
3524 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3526 *pBstrHelpFile = NULL;
3533 /* for a typeinfo */
3534 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3536 if(SUCCEEDED(result))
3538 result = ITypeInfo_GetDocumentation(pTInfo,
3542 pdwHelpContext, pBstrHelpFile);
3544 ITypeInfo_Release(pTInfo);
3549 if (pBstrDocString) SysFreeString (*pBstrDocString);
3551 if (pBstrName) SysFreeString (*pBstrName);
3553 return STG_E_INSUFFICIENTMEMORY;
3558 * Indicates whether a passed-in string contains the name of a type or member
3559 * described in the library.
3562 static HRESULT WINAPI ITypeLib2_fnIsName(
3568 ICOM_THIS( ITypeLibImpl, iface);
3569 ITypeInfoImpl *pTInfo;
3570 TLBFuncDesc *pFInfo;
3573 UINT nNameBufLen = SysStringLen(szNameBuf);
3575 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3579 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3580 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3581 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3582 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3583 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3584 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3585 goto ITypeLib2_fnIsName_exit;
3587 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3588 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3593 ITypeLib2_fnIsName_exit:
3594 TRACE("(%p)slow! search for %s: %s found!\n", This,
3595 debugstr_w(szNameBuf), *pfName?"NOT":"");
3600 /* ITypeLib::FindName
3602 * Finds occurrences of a type description in a type library. This may be used
3603 * to quickly verify that a name exists in a type library.
3606 static HRESULT WINAPI ITypeLib2_fnFindName(
3610 ITypeInfo **ppTInfo,
3614 ICOM_THIS( ITypeLibImpl, iface);
3615 ITypeInfoImpl *pTInfo;
3616 TLBFuncDesc *pFInfo;
3620 UINT nNameBufLen = SysStringLen(szNameBuf);
3622 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3623 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3624 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3625 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3626 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3627 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3628 goto ITypeLib2_fnFindName_exit;
3630 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3631 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3633 ITypeLib2_fnFindName_exit:
3634 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3635 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3638 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3639 This, *pcFound, debugstr_w(szNameBuf), j);
3646 /* ITypeLib::ReleaseTLibAttr
3648 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3651 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3653 TLIBATTR *pTLibAttr)
3655 ICOM_THIS( ITypeLibImpl, iface);
3656 TRACE("freeing (%p)\n",This);
3657 HeapFree(GetProcessHeap(),0,pTLibAttr);
3661 /* ITypeLib2::GetCustData
3663 * gets the custom data
3665 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3670 ICOM_THIS( ITypeLibImpl, iface);
3671 TLBCustData *pCData;
3673 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3675 if( IsEqualIID(guid, &pCData->guid)) break;
3678 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3682 VariantInit( pVarVal);
3683 VariantCopy( pVarVal, &pCData->data);
3686 return E_INVALIDARG; /* FIXME: correct? */
3689 /* ITypeLib2::GetLibStatistics
3691 * Returns statistics about a type library that are required for efficient
3692 * sizing of hash tables.
3695 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3697 ULONG *pcUniqueNames,
3698 ULONG *pcchUniqueNames)
3700 ICOM_THIS( ITypeLibImpl, iface);
3702 FIXME("(%p): stub!\n", This);
3704 if(pcUniqueNames) *pcUniqueNames=1;
3705 if(pcchUniqueNames) *pcchUniqueNames=1;
3709 /* ITypeLib2::GetDocumentation2
3711 * Retrieves the library's documentation string, the complete Help file name
3712 * and path, the localization context to use, and the context ID for the
3713 * library Help topic in the Help file.
3716 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3720 BSTR *pbstrHelpString,
3721 DWORD *pdwHelpStringContext,
3722 BSTR *pbstrHelpStringDll)
3724 ICOM_THIS( ITypeLibImpl, iface);
3728 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3730 /* the help string should be obtained from the helpstringdll,
3731 * using the _DLLGetDocumentation function, based on the supplied
3732 * lcid. Nice to do sometime...
3736 /* documentation for the typelib */
3738 *pbstrHelpString=SysAllocString(This->DocString);
3739 if(pdwHelpStringContext)
3740 *pdwHelpStringContext=This->dwHelpContext;
3741 if(pbstrHelpStringDll)
3742 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3748 /* for a typeinfo */
3749 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3751 if(SUCCEEDED(result))
3753 ITypeInfo2 * pTInfo2;
3754 result = ITypeInfo_QueryInterface(pTInfo,
3756 (LPVOID*) &pTInfo2);
3758 if(SUCCEEDED(result))
3760 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3764 pdwHelpStringContext,
3765 pbstrHelpStringDll);
3767 ITypeInfo2_Release(pTInfo2);
3770 ITypeInfo_Release(pTInfo);
3776 /* ITypeLib2::GetAllCustData
3778 * Gets all custom data items for the library.
3781 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3783 CUSTDATA *pCustData)
3785 ICOM_THIS( ITypeLibImpl, iface);
3786 TLBCustData *pCData;
3788 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3789 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3790 if(pCustData->prgCustData ){
3791 pCustData->cCustData=This->ctCustData;
3792 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3793 pCustData->prgCustData[i].guid=pCData->guid;
3794 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3797 ERR(" OUT OF MEMORY! \n");
3798 return E_OUTOFMEMORY;
3803 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3804 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3805 ITypeLib2_fnQueryInterface,
3807 ITypeLib2_fnRelease,
3808 ITypeLib2_fnGetTypeInfoCount,
3809 ITypeLib2_fnGetTypeInfo,
3810 ITypeLib2_fnGetTypeInfoType,
3811 ITypeLib2_fnGetTypeInfoOfGuid,
3812 ITypeLib2_fnGetLibAttr,
3813 ITypeLib2_fnGetTypeComp,
3814 ITypeLib2_fnGetDocumentation,
3816 ITypeLib2_fnFindName,
3817 ITypeLib2_fnReleaseTLibAttr,
3819 ITypeLib2_fnGetCustData,
3820 ITypeLib2_fnGetLibStatistics,
3821 ITypeLib2_fnGetDocumentation2,
3822 ITypeLib2_fnGetAllCustData
3826 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3828 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3830 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3833 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3835 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3837 return ITypeInfo_AddRef((ITypeInfo *)This);
3840 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3842 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3844 return ITypeInfo_Release((ITypeInfo *)This);
3847 static HRESULT WINAPI ITypeLibComp_fnBind(
3850 unsigned long lHash,
3851 unsigned short wFlags,
3852 ITypeInfo ** ppTInfo,
3853 DESCKIND * pDescKind,
3856 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
3860 static HRESULT WINAPI ITypeLibComp_fnBindType(
3863 unsigned long lHash,
3864 ITypeInfo ** ppTInfo,
3865 ITypeComp ** ppTComp)
3867 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
3871 static ICOM_VTABLE(ITypeComp) tlbtcvt =
3873 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3875 ITypeLibComp_fnQueryInterface,
3876 ITypeLibComp_fnAddRef,
3877 ITypeLibComp_fnRelease,
3879 ITypeLibComp_fnBind,
3880 ITypeLibComp_fnBindType
3883 /*================== ITypeInfo(2) Methods ===================================*/
3884 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3886 ITypeInfoImpl * pTypeInfoImpl;
3888 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3891 pTypeInfoImpl->lpVtbl = &tinfvt;
3892 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
3893 pTypeInfoImpl->ref=1;
3895 TRACE("(%p)\n", pTypeInfoImpl);
3896 return (ITypeInfo2*) pTypeInfoImpl;
3899 /* ITypeInfo::QueryInterface
3901 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3906 ICOM_THIS( ITypeLibImpl, iface);
3908 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3911 if(IsEqualIID(riid, &IID_IUnknown) ||
3912 IsEqualIID(riid,&IID_ITypeInfo)||
3913 IsEqualIID(riid,&IID_ITypeInfo2))
3917 ITypeInfo_AddRef(iface);
3918 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3921 TRACE("-- Interface: E_NOINTERFACE\n");
3922 return E_NOINTERFACE;
3925 /* ITypeInfo::AddRef
3927 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3929 ICOM_THIS( ITypeInfoImpl, iface);
3933 TRACE("(%p)->ref is %u\n",This, This->ref);
3937 /* ITypeInfo::Release
3939 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3941 ICOM_THIS( ITypeInfoImpl, iface);
3945 TRACE("(%p)->(%u)\n",This, This->ref);
3949 FIXME("destroy child objects\n");
3951 TRACE("destroying ITypeInfo(%p)\n",This);
3954 SysFreeString(This->Name);
3958 if (This->DocString)
3960 SysFreeString(This->DocString);
3961 This->DocString = 0;
3966 ITypeInfo_Release((ITypeInfo*)This->next);
3969 HeapFree(GetProcessHeap(),0,This);
3975 /* ITypeInfo::GetTypeAttr
3977 * Retrieves a TYPEATTR structure that contains the attributes of the type
3981 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3982 LPTYPEATTR *ppTypeAttr)
3984 ICOM_THIS( ITypeInfoImpl, iface);
3985 TRACE("(%p)\n",This);
3986 /* FIXME: must do a copy here */
3987 *ppTypeAttr=&This->TypeAttr;
3991 /* ITypeInfo::GetTypeComp
3993 * Retrieves the ITypeComp interface for the type description, which enables a
3994 * client compiler to bind to the type description's members.
3997 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3998 ITypeComp * *ppTComp)
4000 ICOM_THIS( ITypeInfoImpl, iface);
4002 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4004 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4005 ITypeComp_AddRef(*ppTComp);
4009 /* ITypeInfo::GetFuncDesc
4011 * Retrieves the FUNCDESC structure that contains information about a
4012 * specified function.
4015 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4016 LPFUNCDESC *ppFuncDesc)
4018 ICOM_THIS( ITypeInfoImpl, iface);
4020 TLBFuncDesc * pFDesc;
4021 TRACE("(%p) index %d\n", This, index);
4022 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4025 /* FIXME: must do a copy here */
4026 *ppFuncDesc=&pFDesc->funcdesc;
4029 return E_INVALIDARG;
4032 /* ITypeInfo::GetVarDesc
4034 * Retrieves a VARDESC structure that describes the specified variable.
4037 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4038 LPVARDESC *ppVarDesc)
4040 ICOM_THIS( ITypeInfoImpl, iface);
4042 TLBVarDesc * pVDesc;
4043 TRACE("(%p) index %d\n", This, index);
4044 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4047 /* FIXME: must do a copy here */
4048 *ppVarDesc=&pVDesc->vardesc;
4051 return E_INVALIDARG;
4054 /* ITypeInfo_GetNames
4056 * Retrieves the variable with the specified member ID (or the name of the
4057 * property or method and its parameters) that correspond to the specified
4060 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4061 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4063 ICOM_THIS( ITypeInfoImpl, iface);
4064 TLBFuncDesc * pFDesc;
4065 TLBVarDesc * pVDesc;
4067 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4068 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4071 /* function found, now return function and parameter names */
4072 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4075 *rgBstrNames=SysAllocString(pFDesc->Name);
4077 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4083 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4086 *rgBstrNames=SysAllocString(pVDesc->Name);
4091 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
4093 /* recursive search */
4096 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4098 if(SUCCEEDED(result))
4100 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4101 ITypeInfo_Release(pTInfo);
4104 WARN("Could not search inherited interface!\n");
4108 WARN("no names found\n");
4111 return TYPE_E_ELEMENTNOTFOUND;
4118 /* ITypeInfo::GetRefTypeOfImplType
4120 * If a type description describes a COM class, it retrieves the type
4121 * description of the implemented interface types. For an interface,
4122 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4126 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4131 ICOM_THIS( ITypeInfoImpl, iface);
4133 TLBImplType *pImpl = This->impltypelist;
4135 TRACE("(%p) index %d\n", This, index);
4136 if (TRACE_ON(ole)) dump_TypeInfo(This);
4140 /* only valid on dual interfaces;
4141 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4143 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4145 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4146 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4152 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4153 *pRefType = pImpl->hRef;
4158 /* get element n from linked list */
4159 for(i=0; pImpl && i<index; i++)
4161 pImpl = pImpl->next;
4164 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4166 *pRefType = pImpl->hRef;
4168 TRACE("-- 0x%08lx\n", pImpl->hRef );
4175 /* ITypeInfo::GetImplTypeFlags
4177 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4178 * or base interface in a type description.
4180 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4181 UINT index, INT *pImplTypeFlags)
4183 ICOM_THIS( ITypeInfoImpl, iface);
4187 TRACE("(%p) index %d\n", This, index);
4188 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4189 i++, pImpl=pImpl->next)
4191 if(i==index && pImpl){
4192 *pImplTypeFlags=pImpl->implflags;
4196 return TYPE_E_ELEMENTNOTFOUND;
4200 * Maps between member names and member IDs, and parameter names and
4203 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4204 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4206 ICOM_THIS( ITypeInfoImpl, iface);
4207 TLBFuncDesc * pFDesc;
4208 TLBVarDesc * pVDesc;
4211 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4213 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4215 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4216 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4217 for(i=1; i < cNames; i++){
4218 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4219 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4221 if( j<pFDesc->funcdesc.cParams)
4224 ret=DISP_E_UNKNOWNNAME;
4229 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4230 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4231 if(cNames) *pMemId=pVDesc->vardesc.memid;
4235 /* not found, see if this is and interface with an inheritance */
4236 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4237 This->TypeAttr.cImplTypes ){
4238 /* recursive search */
4240 ret=ITypeInfo_GetRefTypeInfo(iface,
4241 This->impltypelist->hRef, &pTInfo);
4243 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4244 ITypeInfo_Release(pTInfo);
4247 WARN("Could not search inherited interface!\n");
4249 WARN("no names found\n");
4250 return DISP_E_UNKNOWNNAME;
4253 /* ITypeInfo::Invoke
4255 * Invokes a method, or accesses a property of an object, that implements the
4256 * interface described by the type description.
4259 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4262 if (TRACE_ON(ole)) {
4264 TRACE("Calling %p(",func);
4265 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4277 res = func(args[0]);
4280 res = func(args[0],args[1]);
4283 res = func(args[0],args[1],args[2]);
4286 res = func(args[0],args[1],args[2],args[3]);
4289 res = func(args[0],args[1],args[2],args[3],args[4]);
4292 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4295 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4298 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4301 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4304 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4310 FIXME("unsupported calling convention %d\n",callconv);
4314 TRACE("returns %08lx\n",res);
4318 extern int const _argsize(DWORD vt);
4320 /****************************************************************************
4321 * Helper functions for Dispcall / Invoke, which copies one variant
4322 * with target type onto the argument stack.
4325 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4326 DWORD *argpos, VARIANT *arg, VARTYPE vt
4328 UINT arglen = _argsize(vt)*sizeof(DWORD);
4331 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4332 memcpy(argpos,&arg,sizeof(void*));
4336 if (V_VT(arg) == vt) {
4337 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4341 if (vt == VT_VARIANT) {
4342 memcpy(argpos, arg, arglen);
4345 /* Deref BYREF vars if there is need */
4346 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4347 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4350 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4351 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4352 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4355 if ((vt == VT_PTR) && tdesc)
4356 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4357 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4362 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4364 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));
4365 memcpy(argpos, &V_UNION(arg,lVal), 4);
4368 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4369 switch (tattr->typekind) {
4371 switch ( V_VT( arg ) ) {
4373 *argpos = V_UNION(arg,iVal);
4376 memcpy(argpos, &V_UNION(arg,lVal), 4);
4379 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4384 tdesc = &(tattr->tdescAlias);
4385 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4386 ITypeInfo_Release(tinfo2);
4389 case TKIND_INTERFACE:
4390 if (V_VT(arg) == VT_DISPATCH) {
4392 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4393 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4396 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4397 if (SUCCEEDED(hres)) {
4398 memcpy(argpos,&disp,4);
4399 IUnknown_Release(V_UNION(arg,pdispVal));
4402 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4405 if (V_VT(arg) == VT_UNKNOWN) {
4406 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4409 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4411 case TKIND_DISPATCH:
4412 if (V_VT(arg) == VT_DISPATCH) {
4413 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4416 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4419 FIXME("TKIND_RECORD unhandled.\n");
4422 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4428 if (VariantChangeType(arg,arg,0,vt)==S_OK) {
4429 FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt, vt);
4430 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4433 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4437 /***********************************************************************
4438 * DispCallFunc (OLEAUT32.@)
4442 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4443 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4445 int i, argsize, argspos;
4449 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4450 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4452 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4453 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4455 for (i=0;i<cActuals;i++) {
4456 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4457 dump_Variant(prgpvarg[i]);
4458 argsize += _argsize(prgvt[i]);
4460 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4461 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4463 for (i=0;i<cActuals;i++) {
4464 VARIANT *arg = prgpvarg[i];
4465 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4466 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4467 argspos += _argsize(prgvt[i]);
4470 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4472 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4477 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4478 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4479 FIXME("Method returned %lx\n",hres);
4481 HeapFree(GetProcessHeap(),0,args);
4485 static HRESULT WINAPI ITypeInfo_fnInvoke(
4490 DISPPARAMS *pDispParams,
4491 VARIANT *pVarResult,
4492 EXCEPINFO *pExcepInfo,
4495 ICOM_THIS( ITypeInfoImpl, iface);
4496 TLBFuncDesc * pFDesc;
4497 TLBVarDesc * pVDesc;
4501 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4502 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4504 dump_DispParms(pDispParams);
4506 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4507 if (pFDesc->funcdesc.memid == memid) {
4508 if (pFDesc->funcdesc.invkind & dwFlags)
4513 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4514 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4515 switch (pFDesc->funcdesc.funckind) {
4516 case FUNC_PUREVIRTUAL:
4517 case FUNC_VIRTUAL: {
4519 int numargs, numargs2, argspos, args2pos;
4520 DWORD *args , *args2;
4523 numargs = 1; numargs2 = 0;
4524 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4525 if (i<pDispParams->cArgs)
4526 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4528 numargs += 1; /* sizeof(lpvoid) */
4529 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4533 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4534 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4536 args[0] = (DWORD)pIUnk;
4537 argspos = 1; args2pos = 0;
4538 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4539 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4540 if (i<pDispParams->cArgs) {
4541 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4542 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4543 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4544 if (FAILED(hres)) return hres;
4547 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4548 if (tdesc->vt != VT_PTR)
4549 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4550 /*FIXME: give pointers for the rest, so propertyget works*/
4551 args[argspos] = (DWORD)&args2[args2pos];
4553 /* If pointer to variant, pass reference it. */
4554 if ((tdesc->vt == VT_PTR) &&
4555 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4558 args[argspos]= (DWORD)pVarResult;
4563 if (pFDesc->funcdesc.cParamsOpt)
4564 FIXME("Does not support optional parameters (%d)\n",
4565 pFDesc->funcdesc.cParamsOpt
4568 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4569 pFDesc->funcdesc.callconv,
4573 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4575 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4576 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4577 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4579 i4_tdesc.vt = VT_I4;
4581 /* If we are a pointer to a variant, we are done already */
4582 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4585 VariantInit(pVarResult);
4586 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4588 if (tdesc->vt == VT_PTR)
4589 tdesc = tdesc->u.lptdesc;
4590 if (tdesc->vt == VT_USERDEFINED) {
4594 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4596 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4599 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4600 switch (tattr->typekind) {
4602 /* force the return type to be VT_I4 */
4606 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4607 tdesc = &(tattr->tdescAlias);
4610 case TKIND_INTERFACE:
4611 FIXME("TKIND_INTERFACE unhandled.\n");
4613 case TKIND_DISPATCH:
4614 FIXME("TKIND_DISPATCH unhandled.\n");
4617 FIXME("TKIND_RECORD unhandled.\n");
4620 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4623 ITypeInfo_Release(tinfo2);
4625 V_VT(pVarResult) = tdesc->vt;
4627 /* HACK: VB5 likes this.
4628 * I do not know why. There is 1 example in MSDN which uses
4629 * this which appears broken (mixes int vals and
4632 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4633 V_VT(pVarResult) = VT_DISPATCH;
4634 TRACE("storing into variant:\n");
4635 dump_Variant(pVarResult);
4639 HeapFree(GetProcessHeap(),0,args2);
4640 HeapFree(GetProcessHeap(),0,args);
4643 case FUNC_DISPATCH: {
4647 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4649 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4652 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4653 hr = IDispatch_Invoke(
4654 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4655 pVarResult,pExcepInfo,pArgErr
4658 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4659 IDispatch_Release(disp);
4663 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4667 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4668 if (pVDesc->vardesc.memid == memid) {
4669 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4670 dump_TLBVarDesc(pVDesc);
4675 /* not found, look for it in inherited interfaces */
4676 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4677 /* recursive search */
4680 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4682 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4683 ITypeInfo_Release(pTInfo);
4686 WARN("Could not search inherited interface!\n");
4688 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4689 return DISP_E_MEMBERNOTFOUND;
4692 /* ITypeInfo::GetDocumentation
4694 * Retrieves the documentation string, the complete Help file name and path,
4695 * and the context ID for the Help topic for a specified type description.
4697 * (Can be tested by the Visual Basic Editor in Word for instance.)
4699 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4700 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4701 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4703 ICOM_THIS( ITypeInfoImpl, iface);
4704 TLBFuncDesc * pFDesc;
4705 TLBVarDesc * pVDesc;
4706 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4707 " HelpContext(%p) HelpFile(%p)\n",
4708 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4709 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4711 *pBstrName=SysAllocString(This->Name);
4713 *pBstrDocString=SysAllocString(This->DocString);
4715 *pdwHelpContext=This->dwHelpContext;
4717 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4719 }else {/* for a member */
4720 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4721 if(pFDesc->funcdesc.memid==memid){
4723 *pBstrName = SysAllocString(pFDesc->Name);
4725 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4727 *pdwHelpContext=pFDesc->helpcontext;
4730 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4731 if(pVDesc->vardesc.memid==memid){
4733 *pBstrName = SysAllocString(pVDesc->Name);
4735 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4737 *pdwHelpContext=pVDesc->HelpContext;
4741 return TYPE_E_ELEMENTNOTFOUND;
4744 /* ITypeInfo::GetDllEntry
4746 * Retrieves a description or specification of an entry point for a function
4749 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4750 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4753 ICOM_THIS( ITypeInfoImpl, iface);
4754 TLBFuncDesc *pFDesc;
4756 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4758 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4759 if(pFDesc->funcdesc.memid==memid){
4760 dump_TypeInfo(This);
4761 dump_TLBFuncDescOne(pFDesc);
4763 /* FIXME: This is wrong, but how do you find that out? */
4765 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4766 *pBstrDllName = SysAllocString(oleaut32W);
4769 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4771 *pBstrName = SysAllocString(pFDesc->Entry);
4779 *pwOrdinal = (DWORD)pFDesc->Entry;
4785 /* ITypeInfo::GetRefTypeInfo
4787 * If a type description references other type descriptions, it retrieves
4788 * the referenced type descriptions.
4790 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4793 ITypeInfo **ppTInfo)
4795 ICOM_THIS( ITypeInfoImpl, iface);
4796 HRESULT result = E_FAIL;
4799 if (hRefType == -1 &&
4800 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4801 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4803 /* when we meet a DUAL dispinterface, we must create the interface
4806 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4809 /* the interface version contains the same information as the dispinterface
4810 * copy the contents of the structs.
4812 *pTypeInfoImpl = *This;
4813 pTypeInfoImpl->ref = 1;
4815 /* change the type to interface */
4816 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4818 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4820 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4825 TLBRefType *pRefType;
4826 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4827 if(pRefType->reference == hRefType)
4831 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4832 if(pRefType && hRefType != -1) {
4833 ITypeLib *pTLib = NULL;
4835 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4837 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4839 if(pRefType->pImpTLInfo->pImpTypeLib) {
4840 TRACE("typeinfo in imported typelib that is already loaded\n");
4841 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4842 ITypeLib2_AddRef((ITypeLib*) pTLib);
4845 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4846 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4847 pRefType->pImpTLInfo->wVersionMajor,
4848 pRefType->pImpTLInfo->wVersionMinor,
4849 pRefType->pImpTLInfo->lcid,
4852 if(!SUCCEEDED(result)) {
4853 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4854 result=LoadTypeLib(libnam, &pTLib);
4855 SysFreeString(libnam);
4857 if(SUCCEEDED(result)) {
4858 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4859 ITypeLib2_AddRef(pTLib);
4863 if(SUCCEEDED(result)) {
4864 if(pRefType->index == TLB_REF_USE_GUID)
4865 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4869 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4873 ITypeLib2_Release(pTLib);
4877 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4878 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4882 /* ITypeInfo::AddressOfMember
4884 * Retrieves the addresses of static functions or variables, such as those
4887 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4888 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4890 ICOM_THIS( ITypeInfoImpl, iface);
4891 FIXME("(%p) stub!\n", This);
4895 /* ITypeInfo::CreateInstance
4897 * Creates a new instance of a type that describes a component object class
4900 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4901 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4903 ICOM_THIS( ITypeInfoImpl, iface);
4904 FIXME("(%p) stub!\n", This);
4908 /* ITypeInfo::GetMops
4910 * Retrieves marshalling information.
4912 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4915 ICOM_THIS( ITypeInfoImpl, iface);
4916 FIXME("(%p) stub!\n", This);
4920 /* ITypeInfo::GetContainingTypeLib
4922 * Retrieves the containing type library and the index of the type description
4923 * within that type library.
4925 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4926 ITypeLib * *ppTLib, UINT *pIndex)
4928 ICOM_THIS( ITypeInfoImpl, iface);
4930 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4932 *pIndex=This->index;
4933 TRACE("returning pIndex=%d\n", *pIndex);
4937 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4938 ITypeLib2_AddRef(*ppTLib);
4939 TRACE("returning ppTLib=%p\n", *ppTLib);
4945 /* ITypeInfo::ReleaseTypeAttr
4947 * Releases a TYPEATTR previously returned by GetTypeAttr.
4950 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4951 TYPEATTR* pTypeAttr)
4953 ICOM_THIS( ITypeInfoImpl, iface);
4954 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4957 /* ITypeInfo::ReleaseFuncDesc
4959 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4961 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
4963 FUNCDESC *pFuncDesc)
4965 ICOM_THIS( ITypeInfoImpl, iface);
4966 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4969 /* ITypeInfo::ReleaseVarDesc
4971 * Releases a VARDESC previously returned by GetVarDesc.
4973 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4976 ICOM_THIS( ITypeInfoImpl, iface);
4977 TRACE("(%p)->(%p)\n", This, pVarDesc);
4980 /* ITypeInfo2::GetTypeKind
4982 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4985 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4986 TYPEKIND *pTypeKind)
4988 ICOM_THIS( ITypeInfoImpl, iface);
4989 *pTypeKind=This->TypeAttr.typekind;
4990 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4994 /* ITypeInfo2::GetTypeFlags
4996 * Returns the type flags without any allocations. This returns a DWORD type
4997 * flag, which expands the type flags without growing the TYPEATTR (type
5001 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5003 ICOM_THIS( ITypeInfoImpl, iface);
5004 *pTypeFlags=This->TypeAttr.wTypeFlags;
5005 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5009 /* ITypeInfo2::GetFuncIndexOfMemId
5010 * Binds to a specific member based on a known DISPID, where the member name
5011 * is not known (for example, when binding to a default member).
5014 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5015 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5017 ICOM_THIS( ITypeInfoImpl, iface);
5018 TLBFuncDesc *pFuncInfo;
5021 /* FIXME: should check for invKind??? */
5022 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
5023 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
5029 result=E_INVALIDARG;
5031 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5032 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
5036 /* TypeInfo2::GetVarIndexOfMemId
5038 * Binds to a specific member based on a known DISPID, where the member name
5039 * is not known (for example, when binding to a default member).
5042 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5043 MEMBERID memid, UINT *pVarIndex)
5045 ICOM_THIS( ITypeInfoImpl, iface);
5046 TLBVarDesc *pVarInfo;
5049 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5050 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5057 result=E_INVALIDARG;
5059 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5060 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5064 /* ITypeInfo2::GetCustData
5066 * Gets the custom data
5068 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5073 ICOM_THIS( ITypeInfoImpl, iface);
5074 TLBCustData *pCData;
5076 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5077 if( IsEqualIID(guid, &pCData->guid)) break;
5079 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5083 VariantInit( pVarVal);
5084 VariantCopy( pVarVal, &pCData->data);
5087 return E_INVALIDARG; /* FIXME: correct? */
5090 /* ITypeInfo2::GetFuncCustData
5092 * Gets the custom data
5094 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5100 ICOM_THIS( ITypeInfoImpl, iface);
5101 TLBCustData *pCData=NULL;
5102 TLBFuncDesc * pFDesc;
5104 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5105 pFDesc=pFDesc->next);
5108 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5109 if( IsEqualIID(guid, &pCData->guid)) break;
5111 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5114 VariantInit( pVarVal);
5115 VariantCopy( pVarVal, &pCData->data);
5118 return E_INVALIDARG; /* FIXME: correct? */
5121 /* ITypeInfo2::GetParamCustData
5123 * Gets the custom data
5125 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5132 ICOM_THIS( ITypeInfoImpl, iface);
5133 TLBCustData *pCData=NULL;
5134 TLBFuncDesc * pFDesc;
5137 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5139 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5140 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5141 pCData = pCData->next)
5142 if( IsEqualIID(guid, &pCData->guid)) break;
5144 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5148 VariantInit( pVarVal);
5149 VariantCopy( pVarVal, &pCData->data);
5152 return E_INVALIDARG; /* FIXME: correct? */
5155 /* ITypeInfo2::GetVarCustData
5157 * Gets the custom data
5159 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5165 ICOM_THIS( ITypeInfoImpl, iface);
5166 TLBCustData *pCData=NULL;
5167 TLBVarDesc * pVDesc;
5170 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5174 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5176 if( IsEqualIID(guid, &pCData->guid)) break;
5180 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5184 VariantInit( pVarVal);
5185 VariantCopy( pVarVal, &pCData->data);
5188 return E_INVALIDARG; /* FIXME: correct? */
5191 /* ITypeInfo2::GetImplCustData
5193 * Gets the custom data
5195 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5201 ICOM_THIS( ITypeInfoImpl, iface);
5202 TLBCustData *pCData=NULL;
5203 TLBImplType * pRDesc;
5206 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5210 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5212 if( IsEqualIID(guid, &pCData->guid)) break;
5216 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5220 VariantInit( pVarVal);
5221 VariantCopy( pVarVal, &pCData->data);
5224 return E_INVALIDARG; /* FIXME: correct? */
5227 /* ITypeInfo2::GetDocumentation2
5229 * Retrieves the documentation string, the complete Help file name and path,
5230 * the localization context to use, and the context ID for the library Help
5231 * topic in the Help file.
5234 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5238 BSTR *pbstrHelpString,
5239 DWORD *pdwHelpStringContext,
5240 BSTR *pbstrHelpStringDll)
5242 ICOM_THIS( ITypeInfoImpl, iface);
5243 TLBFuncDesc * pFDesc;
5244 TLBVarDesc * pVDesc;
5245 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5246 "HelpStringContext(%p) HelpStringDll(%p)\n",
5247 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5248 pbstrHelpStringDll );
5249 /* the help string should be obtained from the helpstringdll,
5250 * using the _DLLGetDocumentation function, based on the supplied
5251 * lcid. Nice to do sometime...
5253 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5255 *pbstrHelpString=SysAllocString(This->Name);
5256 if(pdwHelpStringContext)
5257 *pdwHelpStringContext=This->dwHelpStringContext;
5258 if(pbstrHelpStringDll)
5259 *pbstrHelpStringDll=
5260 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5262 }else {/* for a member */
5263 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5264 if(pFDesc->funcdesc.memid==memid){
5266 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5267 if(pdwHelpStringContext)
5268 *pdwHelpStringContext=pFDesc->HelpStringContext;
5269 if(pbstrHelpStringDll)
5270 *pbstrHelpStringDll=
5271 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5274 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5275 if(pVDesc->vardesc.memid==memid){
5277 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5278 if(pdwHelpStringContext)
5279 *pdwHelpStringContext=pVDesc->HelpStringContext;
5280 if(pbstrHelpStringDll)
5281 *pbstrHelpStringDll=
5282 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5286 return TYPE_E_ELEMENTNOTFOUND;
5289 /* ITypeInfo2::GetAllCustData
5291 * Gets all custom data items for the Type info.
5294 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5296 CUSTDATA *pCustData)
5298 ICOM_THIS( ITypeInfoImpl, iface);
5299 TLBCustData *pCData;
5302 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5304 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5305 if(pCustData->prgCustData ){
5306 pCustData->cCustData=This->ctCustData;
5307 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5308 pCustData->prgCustData[i].guid=pCData->guid;
5309 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5312 ERR(" OUT OF MEMORY! \n");
5313 return E_OUTOFMEMORY;
5318 /* ITypeInfo2::GetAllFuncCustData
5320 * Gets all custom data items for the specified Function
5323 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5326 CUSTDATA *pCustData)
5328 ICOM_THIS( ITypeInfoImpl, iface);
5329 TLBCustData *pCData;
5330 TLBFuncDesc * pFDesc;
5332 TRACE("(%p) index %d\n", This, index);
5333 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5334 pFDesc=pFDesc->next)
5337 pCustData->prgCustData =
5338 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5339 if(pCustData->prgCustData ){
5340 pCustData->cCustData=pFDesc->ctCustData;
5341 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5342 pCData = pCData->next){
5343 pCustData->prgCustData[i].guid=pCData->guid;
5344 VariantCopy(& pCustData->prgCustData[i].varValue,
5348 ERR(" OUT OF MEMORY! \n");
5349 return E_OUTOFMEMORY;
5353 return TYPE_E_ELEMENTNOTFOUND;
5356 /* ITypeInfo2::GetAllParamCustData
5358 * Gets all custom data items for the Functions
5361 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5362 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5364 ICOM_THIS( ITypeInfoImpl, iface);
5365 TLBCustData *pCData=NULL;
5366 TLBFuncDesc * pFDesc;
5368 TRACE("(%p) index %d\n", This, indexFunc);
5369 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5370 pFDesc=pFDesc->next)
5372 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5373 pCustData->prgCustData =
5374 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5375 sizeof(CUSTDATAITEM));
5376 if(pCustData->prgCustData ){
5377 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5378 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5379 pCData; i++, pCData = pCData->next){
5380 pCustData->prgCustData[i].guid=pCData->guid;
5381 VariantCopy(& pCustData->prgCustData[i].varValue,
5385 ERR(" OUT OF MEMORY! \n");
5386 return E_OUTOFMEMORY;
5390 return TYPE_E_ELEMENTNOTFOUND;
5393 /* ITypeInfo2::GetAllVarCustData
5395 * Gets all custom data items for the specified Variable
5398 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5399 UINT index, CUSTDATA *pCustData)
5401 ICOM_THIS( ITypeInfoImpl, iface);
5402 TLBCustData *pCData;
5403 TLBVarDesc * pVDesc;
5405 TRACE("(%p) index %d\n", This, index);
5406 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5407 pVDesc=pVDesc->next)
5410 pCustData->prgCustData =
5411 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5412 if(pCustData->prgCustData ){
5413 pCustData->cCustData=pVDesc->ctCustData;
5414 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5415 pCData = pCData->next){
5416 pCustData->prgCustData[i].guid=pCData->guid;
5417 VariantCopy(& pCustData->prgCustData[i].varValue,
5421 ERR(" OUT OF MEMORY! \n");
5422 return E_OUTOFMEMORY;
5426 return TYPE_E_ELEMENTNOTFOUND;
5429 /* ITypeInfo2::GetAllImplCustData
5431 * Gets all custom data items for the specified implementation type
5434 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5437 CUSTDATA *pCustData)
5439 ICOM_THIS( ITypeInfoImpl, iface);
5440 TLBCustData *pCData;
5441 TLBImplType * pRDesc;
5443 TRACE("(%p) index %d\n", This, index);
5444 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5445 pRDesc=pRDesc->next)
5448 pCustData->prgCustData =
5449 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5450 if(pCustData->prgCustData ){
5451 pCustData->cCustData=pRDesc->ctCustData;
5452 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5453 pCData = pCData->next){
5454 pCustData->prgCustData[i].guid=pCData->guid;
5455 VariantCopy(& pCustData->prgCustData[i].varValue,
5459 ERR(" OUT OF MEMORY! \n");
5460 return E_OUTOFMEMORY;
5464 return TYPE_E_ELEMENTNOTFOUND;
5467 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5469 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5471 ITypeInfo_fnQueryInterface,
5473 ITypeInfo_fnRelease,
5475 ITypeInfo_fnGetTypeAttr,
5476 ITypeInfo_fnGetTypeComp,
5477 ITypeInfo_fnGetFuncDesc,
5478 ITypeInfo_fnGetVarDesc,
5479 ITypeInfo_fnGetNames,
5480 ITypeInfo_fnGetRefTypeOfImplType,
5481 ITypeInfo_fnGetImplTypeFlags,
5482 ITypeInfo_fnGetIDsOfNames,
5484 ITypeInfo_fnGetDocumentation,
5485 ITypeInfo_fnGetDllEntry,
5486 ITypeInfo_fnGetRefTypeInfo,
5487 ITypeInfo_fnAddressOfMember,
5488 ITypeInfo_fnCreateInstance,
5489 ITypeInfo_fnGetMops,
5490 ITypeInfo_fnGetContainingTypeLib,
5491 ITypeInfo_fnReleaseTypeAttr,
5492 ITypeInfo_fnReleaseFuncDesc,
5493 ITypeInfo_fnReleaseVarDesc,
5495 ITypeInfo2_fnGetTypeKind,
5496 ITypeInfo2_fnGetTypeFlags,
5497 ITypeInfo2_fnGetFuncIndexOfMemId,
5498 ITypeInfo2_fnGetVarIndexOfMemId,
5499 ITypeInfo2_fnGetCustData,
5500 ITypeInfo2_fnGetFuncCustData,
5501 ITypeInfo2_fnGetParamCustData,
5502 ITypeInfo2_fnGetVarCustData,
5503 ITypeInfo2_fnGetImplTypeCustData,
5504 ITypeInfo2_fnGetDocumentation2,
5505 ITypeInfo2_fnGetAllCustData,
5506 ITypeInfo2_fnGetAllFuncCustData,
5507 ITypeInfo2_fnGetAllParamCustData,
5508 ITypeInfo2_fnGetAllVarCustData,
5509 ITypeInfo2_fnGetAllImplTypeCustData,
5512 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5514 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5516 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5519 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5521 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5523 return ITypeInfo_AddRef((ITypeInfo *)This);
5526 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5528 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5530 return ITypeInfo_Release((ITypeInfo *)This);
5533 static HRESULT WINAPI ITypeComp_fnBind(
5536 unsigned long lHash,
5537 unsigned short wFlags,
5538 ITypeInfo ** ppTInfo,
5539 DESCKIND * pDescKind,
5542 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5543 TLBFuncDesc * pFDesc;
5544 TLBVarDesc * pVDesc;
5546 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5548 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5549 if (pFDesc->funcdesc.invkind & wFlags)
5550 if (!strcmpW(pFDesc->Name, szName)) {
5556 *pDescKind = DESCKIND_FUNCDESC;
5557 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5558 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5561 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5563 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5564 if (!strcmpW(pVDesc->Name, szName)) {
5565 *pDescKind = DESCKIND_VARDESC;
5566 pBindPtr->lpvardesc = &pVDesc->vardesc;
5567 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5573 /* not found, look for it in inherited interfaces */
5574 if ((This->TypeAttr.typekind == TKIND_INTERFACE) && This->TypeAttr.cImplTypes) {
5575 /* recursive search */
5579 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5582 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5583 ITypeInfo_Release(pTInfo);
5587 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5588 ITypeComp_Release(pTComp);
5591 WARN("Could not search inherited interface!\n");
5593 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5594 *pDescKind = DESCKIND_NONE;
5595 pBindPtr->lpfuncdesc = NULL;
5597 return DISP_E_MEMBERNOTFOUND;
5600 static HRESULT WINAPI ITypeComp_fnBindType(
5603 unsigned long lHash,
5604 ITypeInfo ** ppTInfo,
5605 ITypeComp ** ppTComp)
5607 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5609 /* strange behaviour (does nothing) but like the
5612 if (!ppTInfo || !ppTComp)
5621 static ICOM_VTABLE(ITypeComp) tcompvt =
5623 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5625 ITypeComp_fnQueryInterface,
5627 ITypeComp_fnRelease,
5630 ITypeComp_fnBindType