4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
64 #include "winnls.h" /* for PRIMARYLANGID */
65 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
68 #include "wine/unicode.h"
69 #include "wine/obj_base.h"
73 #include "wine/debug.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 /****************************************************************************
82 * Takes p_iVal (which is in little endian) and returns it
83 * in the host machine's byte order.
85 #ifdef WORDS_BIGENDIAN
86 static WORD FromLEWord(WORD p_iVal)
88 return (((p_iVal & 0x00FF) << 8) |
89 ((p_iVal & 0xFF00) >> 8));
93 static DWORD FromLEDWord(DWORD p_iVal)
95 return (((p_iVal & 0x000000FF) << 24) |
96 ((p_iVal & 0x0000FF00) << 8) |
97 ((p_iVal & 0x00FF0000) >> 8) |
98 ((p_iVal & 0xFF000000) >> 24));
101 #define FromLEWord(X) (X)
102 #define FromLEDWord(X) (X)
106 /****************************************************************************
109 * Fix byte order in any structure if necessary
111 #ifdef WORDS_BIGENDIAN
112 static void FromLEWords(void *p_Val, int p_iSize)
116 p_iSize /= sizeof(WORD);
119 *Val = FromLEWord(*Val);
126 static void FromLEDWords(void *p_Val, int p_iSize)
130 p_iSize /= sizeof(DWORD);
133 *Val = FromLEDWord(*Val);
139 #define FromLEWords(X,Y) /*nothing*/
140 #define FromLEDWords(X,Y) /*nothing*/
144 /****************************************************************************
145 * QueryPathOfRegTypeLib [TYPELIB.14]
147 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
152 QueryPathOfRegTypeLib16(
153 REFGUID guid, /* [in] referenced guid */
154 WORD wMaj, /* [in] major version */
155 WORD wMin, /* [in] minor version */
156 LCID lcid, /* [in] locale id */
157 LPBSTR16 path /* [out] path of typelib */
160 char typelibkey[100],pathname[260];
166 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
167 guid->Data1, guid->Data2, guid->Data3,
168 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
169 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
172 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
173 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
176 plen = sizeof(pathname);
177 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
178 /* try again without lang specific id */
180 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
181 FIXME("key %s not found\n",typelibkey);
184 *path = SysAllocString16(pathname);
188 /****************************************************************************
189 * QueryPathOfRegTypeLib [OLEAUT32.164]
194 QueryPathOfRegTypeLib(
195 REFGUID guid, /* [in] referenced guid */
196 WORD wMaj, /* [in] major version */
197 WORD wMin, /* [in] minor version */
198 LCID lcid, /* [in] locale id */
199 LPBSTR path ) /* [out] path of typelib */
201 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
202 string termination character on output strings */
209 char szTypeLibKey[100];
210 char szPath[MAX_PATH];
211 DWORD dwPathLen = sizeof(szPath);
219 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
225 sprintf(szTypeLibKey,
226 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
227 guid->Data1, guid->Data2, guid->Data3,
228 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
229 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
234 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
238 else if (myLCID == lcid)
240 /* try with sub-langid */
241 myLCID = SUBLANGID(lcid);
243 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
245 /* try with system langid */
255 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
256 BSTR bstrPath = SysAllocStringLen(NULL,len);
258 MultiByteToWideChar(CP_ACP,
270 TRACE_(typelib)("%s not found\n", szTypeLibKey);
275 /******************************************************************************
276 * CreateTypeLib [OLEAUT32.160] creates a typelib
282 HRESULT WINAPI CreateTypeLib(
283 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
285 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
288 /******************************************************************************
289 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
291 * Docs: OLECHAR FAR* szFile
292 * Docs: iTypeLib FAR* FAR* pptLib
298 HRESULT WINAPI LoadTypeLib16(
299 LPOLESTR szFile, /* [in] Name of file to load from */
300 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
302 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
310 /******************************************************************************
311 * LoadTypeLib [OLEAUT32.161]
312 * Loads and registers a type library
314 * Docs: OLECHAR FAR* szFile
315 * Docs: iTypeLib FAR* FAR* pptLib
321 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
323 HRESULT WINAPI LoadTypeLib(
324 const OLECHAR *szFile,/* [in] Name of file to load from */
325 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
328 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
331 /******************************************************************************
332 * LoadTypeLibEx [OLEAUT32.183]
333 * Loads and optionally registers a type library
339 HRESULT WINAPI LoadTypeLibEx(
340 LPCOLESTR szFile, /* [in] Name of file to load from */
341 REGKIND regkind, /* [in] Specify kind of registration */
342 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
344 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
348 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
350 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
353 /* Look for a trailing '\\' followed by an index */
354 pIndexStr = strrchrW(szFile, '\\');
355 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
356 index = atoiW(pIndexStr);
357 memcpy(szFileCopy, szFile,
358 (pIndexStr - szFile - 1) * sizeof(WCHAR));
359 szFileCopy[pIndexStr - szFile - 1] = '\0';
360 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
362 return TYPE_E_CANTLOADLIBRARY;
363 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
364 return TYPE_E_CANTLOADLIBRARY;
366 return TYPE_E_CANTLOADLIBRARY;
369 TRACE("File %s index %d\n", debugstr_w(szPath), index);
371 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
376 case REGKIND_DEFAULT:
377 /* FIXME: is this correct? */
378 if (!szFile || !szFile[0] ||
379 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
381 /* else fall-through */
382 case REGKIND_REGISTER:
383 /* FIXME: Help path? */
384 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
386 IUnknown_Release(*pptLib);
394 TRACE(" returns %08lx\n",res);
398 /******************************************************************************
399 * LoadRegTypeLib [OLEAUT32.162]
401 HRESULT WINAPI LoadRegTypeLib(
402 REFGUID rguid, /* [in] referenced guid */
403 WORD wVerMajor, /* [in] major version */
404 WORD wVerMinor, /* [in] minor version */
405 LCID lcid, /* [in] locale id */
406 ITypeLib **ppTLib) /* [out] path of typelib */
409 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
413 res= LoadTypeLib(bstr, ppTLib);
417 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
423 /******************************************************************************
424 * RegisterTypeLib [OLEAUT32.163]
425 * Adds information about a type library to the System Registry
427 * Docs: ITypeLib FAR * ptlib
428 * Docs: OLECHAR FAR* szFullPath
429 * Docs: OLECHAR FAR* szHelpDir
435 HRESULT WINAPI RegisterTypeLib(
436 ITypeLib * ptlib, /* [in] Pointer to the library*/
437 OLECHAR * szFullPath, /* [in] full Path of the library*/
438 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
449 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
451 if (ptlib == NULL || szFullPath == NULL)
454 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
457 StringFromGUID2(&attr->guid, guid, 80);
458 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
459 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
460 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
461 HeapFree(GetProcessHeap(), 0, guidA);
464 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
465 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
469 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
471 if (RegSetValueExW(key, NULL, 0, REG_SZ,
472 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
480 /* FIXME: This *seems* to be 0 always, not sure though */
481 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
482 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
484 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
485 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
493 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
494 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
497 /* FIXME: is %u correct? */
498 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
499 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
500 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
508 /* register OLE Automation-compatible interfaces for this typelib */
509 types = ITypeLib_GetTypeInfoCount(ptlib);
510 for (tidx=0; tidx<types; tidx++) {
511 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
512 LPOLESTR name = NULL;
513 ITypeInfo *tinfo = NULL;
515 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
517 case TKIND_INTERFACE:
518 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
519 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
522 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
523 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
526 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
527 /* coclasses should probably not be registered? */
530 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
534 TYPEATTR *tattr = NULL;
535 ITypeInfo_GetTypeAttr(tinfo, &tattr);
537 TRACE_(typelib)("guid=%s, flags=%04x (",
538 debugstr_guid(&tattr->guid),
540 if (TRACE_ON(typelib)) {
541 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
561 * FIXME: The 1 is just here until we implement rpcrt4
562 * stub/proxy handling. Until then it helps IShield
565 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
567 /* register interface<->typelib coupling */
568 StringFromGUID2(&tattr->guid, guid, 80);
569 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
570 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
571 HeapFree(GetProcessHeap(), 0, guidA);
573 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
574 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
576 RegSetValueExW(key, NULL, 0, REG_SZ,
577 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
579 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
580 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
581 RegSetValueExA(subKey, NULL, 0, REG_SZ,
585 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
586 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
587 RegSetValueExA(subKey, NULL, 0, REG_SZ,
592 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
593 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
595 StringFromGUID2(&attr->guid, guid, 80);
596 snprintf(ver, sizeof(ver), "%x.%x",
597 attr->wMajorVerNum, attr->wMinorVerNum);
598 RegSetValueExW(subKey, NULL, 0, REG_SZ,
599 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
600 RegSetValueExA(subKey, "Version", 0, REG_SZ,
607 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
609 ITypeInfo_Release(tinfo);
616 ITypeLib_ReleaseTLibAttr(ptlib, attr);
622 /******************************************************************************
623 * UnRegisterTypeLib [OLEAUT32.186]
624 * Removes information about a type library from the System Registry
631 HRESULT WINAPI UnRegisterTypeLib(
632 REFGUID libid, /* [in] Guid of the library */
633 WORD wVerMajor, /* [in] major version */
634 WORD wVerMinor, /* [in] minor version */
635 LCID lcid, /* [in] locale id */
638 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
639 return S_OK; /* FIXME: pretend everything is OK */
642 /****************************************************************************
643 * OaBuildVersion (TYPELIB.15)
645 * known TYPELIB.DLL versions:
647 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
648 * OLE 2.02 1993-94 02 3002
651 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
652 * OLE 2.1 NT 1993-95 ?? ???
653 * OLE 2.3.1 W95 23 700
654 * OLE2 4.0 NT4SP6 1993-98 40 4277
656 DWORD WINAPI OaBuildVersion16(void)
658 /* FIXME: I'd like to return the highest currently known version value
659 * in case the user didn't force a --winver, but I don't know how
660 * to retrieve the "versionForced" info from misc/version.c :(
661 * (this would be useful in other places, too) */
662 FIXME("If you get version error messages, please report them\n");
663 switch(GetVersion() & 0x8000ffff) /* mask off build number */
665 case 0x80000a03: /* WIN31 */
666 return MAKELONG(3027, 3); /* WfW 3.11 */
667 case 0x80000004: /* WIN95 */
668 return MAKELONG(700, 23); /* Win95A */
669 case 0x80000a04: /* WIN98 */
670 return MAKELONG(3024, 10); /* W98 SE */
671 case 0x00000004: /* NT4 */
672 return MAKELONG(4277, 40); /* NT4 SP6 */
674 FIXME("Version value not known yet. Please investigate it!\n");
679 /* for better debugging info leave the static out for the time being */
682 /*======================= ITypeLib implementation =======================*/
684 typedef struct tagTLBCustData
688 struct tagTLBCustData* next;
691 /* data structure for import typelibs */
692 typedef struct tagTLBImpLib
694 int offset; /* offset in the file (MSFT)
695 offset in nametable (SLTG)
696 just used to identify library while reading
698 GUID guid; /* libid */
699 BSTR name; /* name */
701 LCID lcid; /* lcid of imported typelib */
703 WORD wVersionMajor; /* major version number */
704 WORD wVersionMinor; /* minor version number */
706 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
707 NULL if not yet loaded */
708 struct tagTLBImpLib * next;
711 /* internal ITypeLib data */
712 typedef struct tagITypeLibImpl
714 ICOM_VFIELD(ITypeLib2);
716 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
718 /* strings can be stored in tlb as multibyte strings BUT they are *always*
719 * exported to the application as a UNICODE string.
725 unsigned long dwHelpContext;
726 int TypeInfoCount; /* nr of typeinfo's in librarry */
727 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
728 int ctCustData; /* number of items in cust data list */
729 TLBCustData * pCustData; /* linked list to cust data */
730 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
731 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
732 libary. Only used while read MSFT
736 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
738 /* ITypeLib methods */
739 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
740 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
742 /*======================= ITypeInfo implementation =======================*/
744 /* data for refernced types */
745 typedef struct tagTLBRefType
747 INT index; /* Type index for internal ref or for external ref
748 it the format is SLTG. -2 indicates to
751 GUID guid; /* guid of the referenced type */
752 /* if index == TLB_REF_USE_GUID */
754 HREFTYPE reference; /* The href of this ref */
755 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
756 TLB_REF_INTERNAL for internal refs
757 TLB_REF_NOT_FOUND for broken refs */
759 struct tagTLBRefType * next;
762 #define TLB_REF_USE_GUID -2
764 #define TLB_REF_INTERNAL (void*)-2
765 #define TLB_REF_NOT_FOUND (void*)-1
767 /* internal Parameter data */
768 typedef struct tagTLBParDesc
772 TLBCustData * pCustData; /* linked list to cust data */
775 /* internal Function data */
776 typedef struct tagTLBFuncDesc
778 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
779 BSTR Name; /* the name of this function */
780 TLBParDesc *pParamDesc; /* array with param names and custom data */
782 int HelpStringContext;
784 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
786 TLBCustData * pCustData; /* linked list to cust data; */
787 struct tagTLBFuncDesc * next;
790 /* internal Variable data */
791 typedef struct tagTLBVarDesc
793 VARDESC vardesc; /* lots of info on the variable and its attributes. */
794 BSTR Name; /* the name of this variable */
796 int HelpStringContext; /* FIXME: where? */
799 TLBCustData * pCustData;/* linked list to cust data; */
800 struct tagTLBVarDesc * next;
803 /* internal implemented interface data */
804 typedef struct tagTLBImplType
806 HREFTYPE hRef; /* hRef of interface */
807 int implflags; /* IMPLFLAG_*s */
809 TLBCustData * pCustData;/* linked list to custom data; */
810 struct tagTLBImplType *next;
813 /* internal TypeInfo data */
814 typedef struct tagITypeInfoImpl
816 ICOM_VFIELD(ITypeInfo2);
818 TYPEATTR TypeAttr ; /* _lots_ of type information. */
819 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
820 int index; /* index in this typelib; */
821 /* type libs seem to store the doc strings in ascii
822 * so why should we do it in unicode?
826 unsigned long dwHelpContext;
827 unsigned long dwHelpStringContext;
830 TLBFuncDesc * funclist; /* linked list with function descriptions */
833 TLBVarDesc * varlist; /* linked list with variable descriptions */
835 /* Implemented Interfaces */
836 TLBImplType * impltypelist;
838 TLBRefType * reflist;
840 TLBCustData * pCustData; /* linked list to cust data; */
841 struct tagITypeInfoImpl * next;
844 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
846 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
848 typedef struct tagTLBContext
850 unsigned int oStart; /* start of TLB in file */
851 unsigned int pos; /* current pos */
852 unsigned int length; /* total length */
853 void *mapping; /* memory mapping */
854 MSFT_SegDir * pTblDir;
855 ITypeLibImpl* pLibInfo;
859 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
864 static void dump_VarType(VARTYPE vt,char *szVarType) {
865 /* FIXME : we could have better trace here, depending on the VARTYPE
868 if (vt & VT_RESERVED)
869 szVarType += strlen(strcpy(szVarType, "reserved | "));
871 szVarType += strlen(strcpy(szVarType, "ref to "));
873 szVarType += strlen(strcpy(szVarType, "array of "));
875 szVarType += strlen(strcpy(szVarType, "vector of "));
876 switch(vt & VT_TYPEMASK) {
877 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
878 case VT_I2: sprintf(szVarType, "VT_I2"); break;
879 case VT_I4: sprintf(szVarType, "VT_I4"); break;
880 case VT_R4: sprintf(szVarType, "VT_R4"); break;
881 case VT_R8: sprintf(szVarType, "VT_R8"); break;
882 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
883 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
884 case VT_CY: sprintf(szVarType, "VT_CY"); break;
885 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
886 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
887 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
888 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
889 case VT_I1: sprintf(szVarType, "VT_I1"); break;
890 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
891 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
892 case VT_INT: sprintf(szVarType, "VT_INT"); break;
893 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
894 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
895 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
896 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
897 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
901 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
902 if (pTD->vt & VT_RESERVED)
903 szVarType += strlen(strcpy(szVarType, "reserved | "));
904 if (pTD->vt & VT_BYREF)
905 szVarType += strlen(strcpy(szVarType, "ref to "));
906 if (pTD->vt & VT_ARRAY)
907 szVarType += strlen(strcpy(szVarType, "array of "));
908 if (pTD->vt & VT_VECTOR)
909 szVarType += strlen(strcpy(szVarType, "vector of "));
910 switch(pTD->vt & VT_TYPEMASK) {
911 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
912 case VT_I2: sprintf(szVarType, "VT_I2"); break;
913 case VT_I4: sprintf(szVarType, "VT_I4"); break;
914 case VT_R4: sprintf(szVarType, "VT_R4"); break;
915 case VT_R8: sprintf(szVarType, "VT_R8"); break;
916 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
917 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
918 case VT_CY: sprintf(szVarType, "VT_CY"); break;
919 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
920 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
921 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
922 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
923 case VT_I1: sprintf(szVarType, "VT_I1"); break;
924 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
925 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
926 case VT_INT: sprintf(szVarType, "VT_INT"); break;
927 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
928 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
929 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
930 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
931 pTD->u.hreftype); break;
932 case VT_PTR: sprintf(szVarType, "ptr to ");
933 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
935 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
936 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
938 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
939 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
940 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
943 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
947 void dump_ELEMDESC(ELEMDESC *edesc) {
949 dump_TypeDesc(&edesc->tdesc,buf);
950 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
951 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
952 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
954 void dump_FUNCDESC(FUNCDESC *funcdesc) {
956 MESSAGE("memid is %08lx\n",funcdesc->memid);
957 for (i=0;i<funcdesc->cParams;i++) {
958 MESSAGE("Param %d:\n",i);
959 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
961 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
962 switch (funcdesc->funckind) {
963 case FUNC_VIRTUAL: MESSAGE("virtual");break;
964 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
965 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
966 case FUNC_STATIC: MESSAGE("static");break;
967 case FUNC_DISPATCH: MESSAGE("dispatch");break;
968 default: MESSAGE("unknown");break;
970 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
971 switch (funcdesc->invkind) {
972 case INVOKE_FUNC: MESSAGE("func");break;
973 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
974 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
975 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
977 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
978 switch (funcdesc->callconv) {
979 case CC_CDECL: MESSAGE("cdecl");break;
980 case CC_PASCAL: MESSAGE("pascal");break;
981 case CC_STDCALL: MESSAGE("stdcall");break;
982 case CC_SYSCALL: MESSAGE("syscall");break;
985 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
986 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
987 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
990 void dump_IDLDESC(IDLDESC *idl) {
991 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
994 static char * typekind_desc[] =
1007 void dump_TYPEATTR(TYPEATTR *tattr) {
1009 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1010 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1011 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1012 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1013 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1014 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1015 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1016 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1017 MESSAGE("\tcVars: %d\n", tattr->cVars);
1018 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1019 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1020 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1021 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1022 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1023 dump_TypeDesc(&tattr->tdescAlias,buf);
1024 MESSAGE("\ttypedesc: %s\n", buf);
1025 dump_IDLDESC(&tattr->idldescType);
1028 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1031 if (!TRACE_ON(typelib))
1033 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1034 for (i=0;i<pfd->funcdesc.cParams;i++)
1035 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1038 dump_FUNCDESC(&(pfd->funcdesc));
1040 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1041 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1043 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1047 dump_TLBFuncDescOne(pfd);
1051 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1055 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1060 static void dump_TLBImpLib(TLBImpLib *import)
1062 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1063 debugstr_w(import->name));
1064 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1065 import->wVersionMinor, import->lcid, import->offset);
1068 static void dump_TLBRefType(TLBRefType * prt)
1072 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1073 if(prt->index == -1)
1074 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1076 TRACE_(typelib)("type no: %d\n", prt->index);
1078 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1079 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1080 TRACE_(typelib)("in lib\n");
1081 dump_TLBImpLib(prt->pImpTLInfo);
1087 static void dump_TLBImplType(TLBImplType * impl)
1091 "implementing/inheriting interface hRef = %lx implflags %x\n",
1092 impl->hRef, impl->implflags);
1097 void dump_Variant(VARIANT * pvar)
1102 TRACE("(%p)\n", pvar);
1106 ZeroMemory(szVarType, sizeof(szVarType));
1108 /* FIXME : we could have better trace here, depending on the VARTYPE
1111 dump_VarType(V_VT(pvar),szVarType);
1113 TRACE("VARTYPE: %s\n", szVarType);
1115 if (V_VT(pvar) & VT_BYREF) {
1116 ref = V_UNION(pvar, byref);
1119 else ref = &V_UNION(pvar, cVal);
1121 if (V_VT(pvar) & VT_ARRAY) {
1125 if (V_VT(pvar) & VT_VECTOR) {
1130 switch (V_VT(pvar) & VT_TYPEMASK)
1133 TRACE("%d\n", *(short*)ref);
1137 TRACE("%d\n", *(INT*)ref);
1141 TRACE("%3.3e\n", *(float*)ref);
1145 TRACE("%3.3e\n", *(double*)ref);
1149 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1153 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1158 TRACE("%p\n", *(LPVOID*)ref);
1162 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1168 memset( &TM, 0, sizeof(TM) );
1170 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1171 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1173 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1174 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1175 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1181 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1186 TRACE("(?)%ld\n", *(long*)ref);
1191 static void dump_DispParms(DISPPARAMS * pdp)
1195 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1197 while (index < pdp->cArgs)
1199 dump_Variant( &pdp->rgvarg[index] );
1204 static void dump_TypeInfo(ITypeInfoImpl * pty)
1206 TRACE("%p ref=%u\n", pty, pty->ref);
1207 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1208 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1209 TRACE("fct:%u var:%u impl:%u\n",
1210 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1211 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1212 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1213 dump_TLBFuncDesc(pty->funclist);
1214 dump_TLBVarDesc(pty->varlist);
1215 dump_TLBImplType(pty->impltypelist);
1218 void dump_VARDESC(VARDESC *v)
1220 MESSAGE("memid %ld\n",v->memid);
1221 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1222 MESSAGE("oInst %ld\n",v->u.oInst);
1223 dump_ELEMDESC(&(v->elemdescVar));
1224 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1225 MESSAGE("varkind %d\n",v->varkind);
1228 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1230 /* VT_LPWSTR is largest type that */
1231 /* may appear in type description*/
1232 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1233 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1234 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1235 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1236 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1237 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1241 static void TLB_abort()
1245 static void * TLB_Alloc(unsigned size)
1248 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1250 ERR("cannot allocate memory\n");
1255 static void TLB_Free(void * ptr)
1257 HeapFree(GetProcessHeap(), 0, ptr);
1261 /**********************************************************************
1263 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1266 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1268 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1269 pcx->pos, count, pcx->oStart, pcx->length, where);
1271 if (where != DO_NOT_SEEK)
1273 where += pcx->oStart;
1274 if (where > pcx->length)
1277 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1282 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1283 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1288 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1293 ret = MSFT_Read(buffer, count, pcx, where);
1294 FromLEDWords(buffer, ret);
1299 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1304 ret = MSFT_Read(buffer, count, pcx, where);
1305 FromLEWords(buffer, ret);
1310 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1312 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1313 memset(pGuid,0, sizeof(GUID));
1316 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1317 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1318 pGuid->Data2 = FromLEWord(pGuid->Data2);
1319 pGuid->Data3 = FromLEWord(pGuid->Data3);
1320 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1323 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1326 MSFT_NameIntro niName;
1328 WCHAR* pwstring = NULL;
1329 BSTR bstrName = NULL;
1331 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1332 pcx->pTblDir->pNametab.offset+offset);
1333 niName.namelen &= 0xFF; /* FIXME: correct ? */
1334 name=TLB_Alloc((niName.namelen & 0xff) +1);
1335 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1336 name[niName.namelen & 0xff]='\0';
1338 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1341 /* no invalid characters in string */
1344 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1346 /* don't check for invalid character since this has been done previously */
1347 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1349 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1350 lengthInChars = SysStringLen(bstrName);
1351 HeapFree(GetProcessHeap(), 0, pwstring);
1354 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1358 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1365 if(offset<0) return NULL;
1366 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1367 if(length <= 0) return 0;
1368 string=TLB_Alloc(length +1);
1369 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1370 string[length]='\0';
1372 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1373 string, -1, NULL, 0);
1375 /* no invalid characters in string */
1378 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1380 /* don't check for invalid character since this has been done previously */
1381 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1383 bstr = SysAllocStringLen(pwstring, lengthInChars);
1384 lengthInChars = SysStringLen(bstr);
1385 HeapFree(GetProcessHeap(), 0, pwstring);
1388 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1392 * read a value and fill a VARIANT structure
1394 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1398 TRACE_(typelib)("\n");
1400 if(offset <0) { /* data are packed in here */
1401 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1402 V_UNION(pVar, iVal) = offset & 0xffff;
1405 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1406 pcx->pTblDir->pCustData.offset + offset );
1407 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1408 switch (V_VT(pVar)){
1409 case VT_EMPTY: /* FIXME: is this right? */
1410 case VT_NULL: /* FIXME: is this right? */
1411 case VT_I2 : /* this should not happen */
1422 case VT_VOID : /* FIXME: is this right? */
1430 case VT_DECIMAL : /* FIXME: is this right? */
1433 /* pointer types with known behaviour */
1436 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1438 FIXME("BSTR length = %d?\n", size);
1440 ptr=TLB_Alloc(size);/* allocate temp buffer */
1441 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1442 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1443 /* FIXME: do we need a AtoW conversion here? */
1444 V_UNION(pVar, bstrVal[size])=L'\0';
1445 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1450 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1457 case VT_USERDEFINED :
1463 case VT_STREAMED_OBJECT :
1464 case VT_STORED_OBJECT :
1465 case VT_BLOB_OBJECT :
1470 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1474 if(size>0) /* (big|small) endian correct? */
1475 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1479 * create a linked list with custom data
1481 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1487 TRACE_(typelib)("\n");
1491 pNew=TLB_Alloc(sizeof(TLBCustData));
1492 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1493 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1494 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1495 /* add new custom data at head of the list */
1496 pNew->next=*ppCustData;
1498 offset = entry.next;
1503 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1507 pTd->vt=type & VT_TYPEMASK;
1509 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1511 if(pTd->vt == VT_USERDEFINED)
1512 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1514 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1518 MSFT_DoFuncs(TLBContext* pcx,
1523 TLBFuncDesc** pptfd)
1526 * member information is stored in a data structure at offset
1527 * indicated by the memoffset field of the typeinfo structure
1528 * There are several distinctive parts.
1529 * the first part starts with a field that holds the total length
1530 * of this (first) part excluding this field. Then follow the records,
1531 * for each member there is one record.
1533 * First entry is always the length of the record (excluding this
1535 * Rest of the record depends on the type of the member. If there is
1536 * a field indicating the member type (function variable intereface etc)
1537 * I have not found it yet. At this time we depend on the information
1538 * in the type info and the usual order how things are stored.
1540 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1543 * Third is a equal sized array with file offsets to the name entry
1546 * Forth and last (?) part is an array with offsets to the records in the
1547 * first part of this file segment.
1550 int infolen, nameoffset, reclength, nrattributes, i;
1551 int recoffset = offset + sizeof(INT);
1554 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1556 TRACE_(typelib)("\n");
1558 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1560 for ( i = 0; i < cFuncs ; i++ )
1562 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1564 /* name, eventually add to a hash table */
1565 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1566 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1568 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1570 /* read the function information record */
1571 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1575 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1577 /* do the attributes */
1578 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1581 if ( nrattributes > 0 )
1583 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1585 if ( nrattributes > 1 )
1587 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1588 pFuncRec->OptAttr[1]) ;
1590 if ( nrattributes > 2 )
1592 if ( pFuncRec->FKCCIC & 0x2000 )
1594 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1598 (*pptfd)->Entry = MSFT_ReadString(pcx,
1599 pFuncRec->OptAttr[2]);
1601 if( nrattributes > 5 )
1603 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1605 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1608 pFuncRec->OptAttr[6],
1609 &(*pptfd)->pCustData);
1616 /* fill the FuncDesc Structure */
1617 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1618 offset + infolen + ( i + 1) * sizeof(INT));
1620 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1621 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1622 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1623 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1624 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1625 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1626 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1630 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1633 /* do the parameters/arguments */
1634 if(pFuncRec->nrargs)
1637 MSFT_ParameterInfo paraminfo;
1639 (*pptfd)->funcdesc.lprgelemdescParam =
1640 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1642 (*pptfd)->pParamDesc =
1643 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1645 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1646 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1648 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1650 TYPEDESC* lpArgTypeDesc = 0;
1654 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1657 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1659 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1661 /* SEEK value = jump to offset,
1662 * from there jump to the end of record,
1663 * go back by (j-1) arguments
1665 MSFT_ReadLEDWords( ¶minfo ,
1666 sizeof(MSFT_ParameterInfo), pcx,
1667 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1668 * sizeof(MSFT_ParameterInfo)));
1670 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1672 while ( lpArgTypeDesc != NULL )
1674 switch ( lpArgTypeDesc->vt )
1677 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1681 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1684 case VT_USERDEFINED:
1685 MSFT_DoRefType(pcx, pTI,
1686 lpArgTypeDesc->u.hreftype);
1688 lpArgTypeDesc = NULL;
1692 lpArgTypeDesc = NULL;
1698 /* parameter is the return value! */
1699 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1701 TYPEDESC* lpArgTypeDesc;
1703 (*pptfd)->funcdesc.elemdescFunc =
1704 (*pptfd)->funcdesc.lprgelemdescParam[j];
1706 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1708 while ( lpArgTypeDesc != NULL )
1710 switch ( lpArgTypeDesc->vt )
1713 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1717 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1721 case VT_USERDEFINED:
1724 lpArgTypeDesc->u.hreftype);
1726 lpArgTypeDesc = NULL;
1730 lpArgTypeDesc = NULL;
1735 /* second time around */
1736 for(j=0;j<pFuncRec->nrargs;j++)
1739 (*pptfd)->pParamDesc[j].Name =
1740 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1743 if ( (PARAMFLAG_FHASDEFAULT &
1744 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1745 ((pFuncRec->FKCCIC) & 0x1000) )
1747 INT* pInt = (INT *)((char *)pFuncRec +
1749 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1751 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1753 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1754 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1756 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1760 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1763 pFuncRec->OptAttr[7+j],
1764 &(*pptfd)->pParamDesc[j].pCustData);
1769 /* scode is not used: archaic win16 stuff FIXME: right? */
1770 (*pptfd)->funcdesc.cScodes = 0 ;
1771 (*pptfd)->funcdesc.lprgscode = NULL ;
1773 pptfd = & ((*pptfd)->next);
1774 recoffset += reclength;
1777 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1778 int cVars, int offset, TLBVarDesc ** pptvd)
1780 int infolen, nameoffset, reclength;
1782 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1786 TRACE_(typelib)("\n");
1788 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1789 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1790 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1791 recoffset += offset+sizeof(INT);
1792 for(i=0;i<cVars;i++){
1793 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1794 /* name, eventually add to a hash table */
1795 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1796 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1797 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1798 /* read the variable information record */
1799 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1801 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1803 if(reclength >(6*sizeof(INT)) )
1804 (*pptvd)->HelpContext=pVarRec->HelpContext;
1805 if(reclength >(7*sizeof(INT)) )
1806 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1807 if(reclength >(8*sizeof(INT)) )
1808 if(reclength >(9*sizeof(INT)) )
1809 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1810 /* fill the VarDesc Structure */
1811 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1812 offset + infolen + ( i + 1) * sizeof(INT));
1813 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1814 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1815 MSFT_GetTdesc(pcx, pVarRec->DataType,
1816 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1817 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1818 if(pVarRec->VarKind == VAR_CONST ){
1819 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1820 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1821 pVarRec->OffsValue, pcx);
1823 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1824 pptvd=&((*pptvd)->next);
1825 recoffset += reclength;
1828 /* fill in data for a hreftype (offset). When the refernced type is contained
1829 * in the typelib, it's just an (file) offset in the type info base dir.
1830 * If comes from import, it's an offset+1 in the ImpInfo table
1832 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1836 TLBRefType **ppRefType = &pTI->reflist;
1838 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1841 if((*ppRefType)->reference == offset)
1843 ppRefType = &(*ppRefType)->next;
1846 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1847 sizeof(**ppRefType));
1849 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1850 /* external typelib */
1851 MSFT_ImpInfo impinfo;
1852 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1854 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1856 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1857 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1858 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1859 if(pImpLib->offset==impinfo.oImpFile) break;
1860 pImpLib=pImpLib->next;
1863 (*ppRefType)->reference=offset;
1864 (*ppRefType)->pImpTLInfo = pImpLib;
1865 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1866 (*ppRefType)->index = TLB_REF_USE_GUID;
1868 ERR("Cannot find a reference\n");
1869 (*ppRefType)->reference=-1;
1870 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1873 /* in this typelib */
1874 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1875 (*ppRefType)->reference=offset;
1876 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1880 /* process Implemented Interfaces of a com class */
1881 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1885 MSFT_RefRecord refrec;
1886 TLBImplType **ppImpl = &pTI->impltypelist;
1888 TRACE_(typelib)("\n");
1890 for(i=0;i<count;i++){
1891 if(offset<0) break; /* paranoia */
1892 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1893 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1894 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1895 (*ppImpl)->hRef = refrec.reftype;
1896 (*ppImpl)->implflags=refrec.flags;
1897 (*ppImpl)->ctCustData=
1898 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1899 offset=refrec.onext;
1900 ppImpl=&((*ppImpl)->next);
1904 * process a typeinfo record
1906 ITypeInfoImpl * MSFT_DoTypeInfo(
1909 ITypeLibImpl * pLibInfo)
1911 MSFT_TypeInfoBase tiBase;
1912 ITypeInfoImpl *ptiRet;
1914 TRACE_(typelib)("count=%u\n", count);
1916 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1917 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1918 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1919 /* this is where we are coming from */
1920 ptiRet->pTypeLib = pLibInfo;
1921 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1922 ptiRet->index=count;
1923 /* fill in the typeattr fields */
1924 FIXME("Assign constructor/destructor memid\n");
1926 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1927 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1928 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1929 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1930 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1931 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1932 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1933 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1934 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1935 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1936 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1937 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1938 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1939 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1940 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1941 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1942 MSFT_GetTdesc(pcx, tiBase.datatype1,
1943 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1946 /* IDLDESC idldescType; *//* never saw this one != zero */
1948 /* name, eventually add to a hash table */
1949 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1950 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1952 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1953 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1954 ptiRet->dwHelpContext=tiBase.helpcontext;
1955 /* note: InfoType's Help file and HelpStringDll come from the containing
1956 * library. Further HelpString and Docstring appear to be the same thing :(
1959 if(ptiRet->TypeAttr.cFuncs >0 )
1960 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1961 ptiRet->TypeAttr.cVars,
1962 tiBase.memoffset, & ptiRet->funclist);
1964 if(ptiRet->TypeAttr.cVars >0 )
1965 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1966 ptiRet->TypeAttr.cVars,
1967 tiBase.memoffset, & ptiRet->varlist);
1968 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1969 switch(ptiRet->TypeAttr.typekind)
1972 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1975 case TKIND_DISPATCH:
1976 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1978 if (tiBase.datatype1 != -1)
1980 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1981 ptiRet->impltypelist->hRef = tiBase.datatype1;
1984 { /* FIXME: This is a really bad hack to add IDispatch */
1985 char* szStdOle = "stdole2.tlb\0";
1986 int nStdOleLen = strlen(szStdOle);
1987 TLBRefType **ppRef = &ptiRet->reflist;
1990 if((*ppRef)->reference == -1)
1992 ppRef = &(*ppRef)->next;
1995 *ppRef = TLB_Alloc(sizeof(**ppRef));
1996 (*ppRef)->guid = IID_IDispatch;
1997 (*ppRef)->reference = -1;
1998 (*ppRef)->index = TLB_REF_USE_GUID;
1999 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2000 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2001 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2004 MultiByteToWideChar(CP_ACP,
2008 (*ppRef)->pImpTLInfo->name,
2009 SysStringLen((*ppRef)->pImpTLInfo->name));
2011 (*ppRef)->pImpTLInfo->lcid = 0;
2012 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2013 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2018 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2019 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2020 ptiRet->impltypelist->hRef = tiBase.datatype1;
2025 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2027 TRACE_(typelib)("%s guid: %s kind:%s\n",
2028 debugstr_w(ptiRet->Name),
2029 debugstr_guid(&ptiRet->TypeAttr.guid),
2030 typekind_desc[ptiRet->TypeAttr.typekind]);
2035 /****************************************************************************
2038 * find the type of the typelib file and map the typelib resource into
2041 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2042 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2043 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2045 int ret = TYPE_E_CANTLOADLIBRARY;
2046 DWORD dwSignature = 0;
2049 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2053 /* check the signature of the file */
2054 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2055 if (INVALID_HANDLE_VALUE != hFile)
2057 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2060 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2063 /* retrieve file size */
2064 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2066 /* first try to load as *.tlb */
2067 dwSignature = FromLEDWord(*((DWORD*) pBase));
2068 if ( dwSignature == MSFT_SIGNATURE)
2070 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2072 else if ( dwSignature == SLTG_SIGNATURE)
2074 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2076 UnmapViewOfFile(pBase);
2078 CloseHandle(hMapping);
2083 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2085 /* find the typelibrary resource*/
2086 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2087 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2090 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2094 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2097 LPVOID pBase = LockResource(hGlobal);
2098 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2102 /* try to load as incore resource */
2103 dwSignature = FromLEDWord(*((DWORD*) pBase));
2104 if ( dwSignature == MSFT_SIGNATURE)
2106 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2108 else if ( dwSignature == SLTG_SIGNATURE)
2110 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2114 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2117 FreeResource( hGlobal );
2120 FreeLibrary(hinstDLL);
2127 ERR("Loading of typelib %s failed with error %ld\n",
2128 debugstr_w(pszFileName), GetLastError());
2133 /*================== ITypeLib(2) Methods ===================================*/
2135 /****************************************************************************
2136 * ITypeLib2_Constructor_MSFT
2138 * loading an MSFT typelib from an in-memory image
2140 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2144 MSFT_Header tlbHeader;
2145 MSFT_SegDir tlbSegDir;
2146 ITypeLibImpl * pTypeLibImpl;
2148 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2150 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2151 if (!pTypeLibImpl) return NULL;
2153 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2154 pTypeLibImpl->ref = 1;
2156 /* get pointer to beginning of typelib data */
2160 cx.pLibInfo = pTypeLibImpl;
2161 cx.length = dwTLBLength;
2164 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2166 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2167 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2168 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2171 /* there is a small amount of information here until the next important
2173 * the segment directory . Try to calculate the amount of data */
2174 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2176 /* now read the segment directory */
2177 TRACE("read segment directory (at %ld)\n",lPSegDir);
2178 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2179 cx.pTblDir = &tlbSegDir;
2181 /* just check two entries */
2182 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2184 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2185 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2189 /* now fill our internal data */
2190 /* TLIBATTR fields */
2191 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2193 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2194 /* Windows seems to have zero here, is this correct? */
2195 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2196 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2198 pTypeLibImpl->LibAttr.lcid = 0;
2200 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2201 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2202 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2203 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2205 /* name, eventually add to a hash table */
2206 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2209 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2210 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2212 if( tlbHeader.varflags & HELPDLLFLAG)
2215 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2216 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2219 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2222 if(tlbHeader.CustomDataOffset >= 0)
2224 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2227 /* fill in typedescriptions */
2228 if(tlbSegDir.pTypdescTab.length > 0)
2230 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2232 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2233 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2236 /* FIXME: add several sanity checks here */
2237 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2238 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2240 /* FIXME: check safearray */
2242 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2244 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2246 else if(td[0] == VT_CARRAY)
2248 /* array descr table here */
2249 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2251 else if(td[0] == VT_USERDEFINED)
2253 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2255 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2258 /* second time around to fill the array subscript info */
2261 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2262 if(tlbSegDir.pArrayDescriptions.offset>0)
2264 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2265 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2268 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2270 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2272 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2274 for(j = 0; j<td[2]; j++)
2276 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2277 sizeof(INT), &cx, DO_NOT_SEEK);
2278 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2279 sizeof(INT), &cx, DO_NOT_SEEK);
2284 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2285 ERR("didn't find array description data\n");
2290 /* imported type libs */
2291 if(tlbSegDir.pImpFiles.offset>0)
2293 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2294 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2297 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2299 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2300 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2301 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2303 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2304 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2305 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2306 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2309 (*ppImpLib)->name = TLB_Alloc(size+1);
2310 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2311 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2312 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2314 ppImpLib = &(*ppImpLib)->next;
2319 if(tlbHeader.nrtypeinfos >= 0 )
2321 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2322 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2325 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2327 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2329 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2330 ppTI = &((*ppTI)->next);
2331 (pTypeLibImpl->TypeInfoCount)++;
2335 TRACE("(%p)\n", pTypeLibImpl);
2336 return (ITypeLib2*) pTypeLibImpl;
2340 static BSTR TLB_MultiByteToBSTR(char *ptr)
2346 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2347 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2348 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2349 ret = SysAllocString(nameW);
2350 HeapFree(GetProcessHeap(), 0, nameW);
2354 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2360 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2361 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2365 guid->Data4[0] = s >> 8;
2366 guid->Data4[1] = s & 0xff;
2369 for(i = 0; i < 6; i++) {
2370 memcpy(b, str + 24 + 2 * i, 2);
2371 guid->Data4[i + 2] = strtol(b, NULL, 16);
2376 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2383 bytelen = *(WORD*)ptr;
2384 if(bytelen == 0xffff) return 2;
2385 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2386 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2387 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2388 *pBstr = SysAllocStringLen(nameW, len);
2389 HeapFree(GetProcessHeap(), 0, nameW);
2393 static WORD SLTG_ReadStringA(char *ptr, char **str)
2398 bytelen = *(WORD*)ptr;
2399 if(bytelen == 0xffff) return 2;
2400 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2401 memcpy(*str, ptr + 2, bytelen);
2402 (*str)[bytelen] = '\0';
2406 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2408 char *ptr = pLibBlk;
2411 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2412 FIXME("libblk magic = %04x\n", w);
2417 if((w = *(WORD*)ptr) != 0xffff) {
2418 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2423 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2425 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2427 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2430 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2433 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2436 ptr += 4; /* skip res12 */
2438 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2441 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2444 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2447 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2448 ptr += sizeof(GUID);
2450 return ptr - (char*)pLibBlk;
2453 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2456 TYPEDESC *pTD = &pElem->tdesc;
2458 /* Handle [in/out] first */
2459 if((*pType & 0xc000) == 0xc000)
2460 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2461 else if(*pType & 0x8000)
2462 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2463 else if(*pType & 0x4000)
2464 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2466 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2469 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2472 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2475 if((*pType & 0xe00) == 0xe00) {
2477 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2479 pTD = pTD->u.lptdesc;
2481 switch(*pType & 0x7f) {
2484 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2486 pTD = pTD->u.lptdesc;
2489 case VT_USERDEFINED:
2490 pTD->vt = VT_USERDEFINED;
2491 pTD->u.hreftype = *(++pType) / 4;
2497 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2500 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2502 pTD->vt = VT_CARRAY;
2503 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2505 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2506 pTD->u.lpadesc->cDims = pSA->cDims;
2507 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2508 pSA->cDims * sizeof(SAFEARRAYBOUND));
2510 pTD = &pTD->u.lpadesc->tdescElem;
2516 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2520 pTD->vt = VT_SAFEARRAY;
2521 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2523 pTD = pTD->u.lptdesc;
2527 pTD->vt = *pType & 0x7f;
2537 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2542 TLBRefType **ppRefType;
2544 if(pRef->magic != SLTG_REF_MAGIC) {
2545 FIXME("Ref magic = %x\n", pRef->magic);
2548 name = ( (char*)(&pRef->names) + pRef->number);
2550 ppRefType = &pTI->reflist;
2551 for(ref = 0; ref < pRef->number >> 3; ref++) {
2553 unsigned int lib_offs, type_num;
2555 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2556 sizeof(**ppRefType));
2558 name += SLTG_ReadStringA(name, &refname);
2559 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2560 FIXME("Can't sscanf ref\n");
2561 if(lib_offs != 0xffff) {
2562 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2565 if((*import)->offset == lib_offs)
2567 import = &(*import)->next;
2570 char fname[MAX_PATH+1];
2573 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2575 (*import)->offset = lib_offs;
2576 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2578 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2579 &(*import)->wVersionMajor,
2580 &(*import)->wVersionMinor,
2581 &(*import)->lcid, fname) != 4) {
2582 FIXME("can't sscanf ref %s\n",
2583 pNameTable + lib_offs + 40);
2585 len = strlen(fname);
2586 if(fname[len-1] != '#')
2587 FIXME("fname = %s\n", fname);
2588 fname[len-1] = '\0';
2589 (*import)->name = TLB_MultiByteToBSTR(fname);
2591 (*ppRefType)->pImpTLInfo = *import;
2592 } else { /* internal ref */
2593 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2595 (*ppRefType)->reference = ref;
2596 (*ppRefType)->index = type_num;
2598 HeapFree(GetProcessHeap(), 0, refname);
2599 ppRefType = &(*ppRefType)->next;
2601 if((BYTE)*name != SLTG_REF_MAGIC)
2602 FIXME("End of ref block magic = %x\n", *name);
2603 dump_TLBRefType(pTI->reflist);
2606 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2609 SLTG_ImplInfo *info;
2610 TLBImplType **ppImplType = &pTI->impltypelist;
2611 /* I don't really get this structure, usually it's 0x16 bytes
2612 long, but iuser.tlb contains some that are 0x18 bytes long.
2613 That's ok because we can use the next ptr to jump to the next
2614 one. But how do we know the length of the last one? The WORD
2615 at offs 0x8 might be the clue. For now I'm just assuming that
2616 the last one is the regular 0x16 bytes. */
2618 info = (SLTG_ImplInfo*)pBlk;
2620 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2621 sizeof(**ppImplType));
2622 (*ppImplType)->hRef = info->ref;
2623 (*ppImplType)->implflags = info->impltypeflags;
2624 pTI->TypeAttr.cImplTypes++;
2625 ppImplType = &(*ppImplType)->next;
2627 if(info->next == 0xffff)
2630 FIXME("Interface inheriting more than one interface\n");
2631 info = (SLTG_ImplInfo*)(pBlk + info->next);
2633 info++; /* see comment at top of function */
2637 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2640 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2641 SLTG_MemberHeader *pMemHeader;
2642 char *pFirstItem, *pNextItem;
2644 if(pTIHeader->href_table != 0xffffffff) {
2645 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2650 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2652 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2654 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2655 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2658 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2662 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2665 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2666 SLTG_MemberHeader *pMemHeader;
2667 SLTG_Function *pFunc;
2668 char *pFirstItem, *pNextItem;
2669 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2672 if(pTIHeader->href_table != 0xffffffff) {
2673 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2677 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2679 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2681 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2682 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2685 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2686 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2691 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2692 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2693 FIXME("func magic = %02x\n", pFunc->magic);
2696 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2697 sizeof(**ppFuncDesc));
2698 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2700 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2701 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2702 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2703 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2704 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2705 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2707 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2708 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2710 if(pFunc->retnextopt & 0x80)
2711 pType = &pFunc->rettype;
2713 pType = (WORD*)(pFirstItem + pFunc->rettype);
2716 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2718 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2719 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2720 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2721 (*ppFuncDesc)->pParamDesc =
2722 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2723 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2725 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2727 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2728 char *paramName = pNameTable + *pArg;
2730 /* If arg type follows then paramName points to the 2nd
2731 letter of the name, else the next WORD is an offset to
2732 the arg type and paramName points to the first letter.
2733 So let's take one char off paramName and see if we're
2734 pointing at an alpha-numeric char. However if *pArg is
2735 0xffff or 0xfffe then the param has no name, the former
2736 meaning that the next WORD is the type, the latter
2737 meaning the the next WORD is an offset to the type. */
2742 else if(*pArg == 0xfffe) {
2746 else if(!isalnum(*(paramName-1)))
2751 if(HaveOffs) { /* the next word is an offset to type */
2752 pType = (WORD*)(pFirstItem + *pArg);
2753 SLTG_DoType(pType, pFirstItem,
2754 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2759 pArg = SLTG_DoType(pArg, pFirstItem,
2760 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2763 /* Are we an optional param ? */
2764 if((*ppFuncDesc)->funcdesc.cParams - param <=
2765 (*ppFuncDesc)->funcdesc.cParamsOpt)
2766 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2769 (*ppFuncDesc)->pParamDesc[param].Name =
2770 TLB_MultiByteToBSTR(paramName);
2774 ppFuncDesc = &((*ppFuncDesc)->next);
2775 if(pFunc->next == 0xffff) break;
2777 pTI->TypeAttr.cFuncs = num;
2778 dump_TLBFuncDesc(pTI->funclist);
2779 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2782 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2785 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2786 SLTG_MemberHeader *pMemHeader;
2787 SLTG_RecordItem *pItem;
2789 TLBVarDesc **ppVarDesc = &pTI->varlist;
2794 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2796 pFirstItem = (char*)(pMemHeader + 1);
2797 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2798 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2799 if(pItem->magic != SLTG_RECORD_MAGIC) {
2800 FIXME("record magic = %02x\n", pItem->magic);
2803 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2804 sizeof(**ppVarDesc));
2805 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2806 (*ppVarDesc)->vardesc.memid = pItem->memid;
2807 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2808 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2810 if(pItem->typepos == 0x02)
2811 pType = &pItem->type;
2812 else if(pItem->typepos == 0x00)
2813 pType = (WORD*)(pFirstItem + pItem->type);
2815 FIXME("typepos = %02x\n", pItem->typepos);
2819 SLTG_DoType(pType, pFirstItem,
2820 &(*ppVarDesc)->vardesc.elemdescVar);
2822 /* FIXME("helpcontext, helpstring\n"); */
2824 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2826 ppVarDesc = &((*ppVarDesc)->next);
2827 if(pItem->next == 0xffff) break;
2829 pTI->TypeAttr.cVars = num;
2830 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2833 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2836 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2837 SLTG_MemberHeader *pMemHeader;
2838 SLTG_EnumItem *pItem;
2840 TLBVarDesc **ppVarDesc = &pTI->varlist;
2843 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2845 pFirstItem = (char*)(pMemHeader + 1);
2846 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2847 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2848 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2849 FIXME("enumitem magic = %04x\n", pItem->magic);
2852 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2853 sizeof(**ppVarDesc));
2854 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2855 (*ppVarDesc)->vardesc.memid = pItem->memid;
2856 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2858 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2859 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2860 *(INT*)(pItem->value + pFirstItem);
2861 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2862 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2863 /* FIXME("helpcontext, helpstring\n"); */
2865 ppVarDesc = &((*ppVarDesc)->next);
2866 if(pItem->next == 0xffff) break;
2868 pTI->TypeAttr.cVars = num;
2869 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2872 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2873 managable copy of it into this */
2886 } SLTG_InternalOtherTypeInfo;
2888 /****************************************************************************
2889 * ITypeLib2_Constructor_SLTG
2891 * loading a SLTG typelib from an in-memory image
2893 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2895 ITypeLibImpl *pTypeLibImpl;
2896 SLTG_Header *pHeader;
2897 SLTG_BlkEntry *pBlkEntry;
2901 LPVOID pBlk, pFirstBlk;
2902 SLTG_LibBlk *pLibBlk;
2903 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2904 char *pAfterOTIBlks = NULL;
2905 char *pNameTable, *ptr;
2908 ITypeInfoImpl **ppTypeInfoImpl;
2910 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2912 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2913 if (!pTypeLibImpl) return NULL;
2915 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2916 pTypeLibImpl->ref = 1;
2921 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2922 pHeader->nrOfFileBlks );
2923 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2924 FIXME("Header type magic 0x%08lx not supported.\n",
2925 pHeader->SLTG_magic);
2929 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2930 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2932 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2933 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2935 /* Next we have a magic block */
2936 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2938 /* Let's see if we're still in sync */
2939 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2940 sizeof(SLTG_COMPOBJ_MAGIC))) {
2941 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2944 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2945 sizeof(SLTG_DIR_MAGIC))) {
2946 FIXME("dir magic = %s\n", pMagic->dir_magic);
2950 pIndex = (SLTG_Index*)(pMagic+1);
2952 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2954 pFirstBlk = (LPVOID)(pPad9 + 1);
2956 /* We'll set up a ptr to the main library block, which is the last one. */
2958 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2959 pBlkEntry[order].next != 0;
2960 order = pBlkEntry[order].next - 1, i++) {
2961 pBlk = (char*)pBlk + pBlkEntry[order].len;
2965 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2967 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2972 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2974 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2975 sizeof(*pOtherTypeInfoBlks) *
2976 pTypeLibImpl->TypeInfoCount);
2979 ptr = (char*)pLibBlk + len;
2981 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2985 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2987 w = *(WORD*)(ptr + 2);
2990 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2992 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2993 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2995 w = *(WORD*)(ptr + 4 + len);
2997 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2999 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3001 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3002 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3004 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3005 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3006 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3008 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3010 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3013 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3014 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3015 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3016 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3017 len += sizeof(SLTG_OtherTypeInfo);
3021 pAfterOTIBlks = ptr;
3023 /* Skip this WORD and get the next DWORD */
3024 len = *(DWORD*)(pAfterOTIBlks + 2);
3026 /* Now add this to pLibBLk look at what we're pointing at and
3027 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3028 dust and we should be pointing at the beginning of the name
3031 pNameTable = (char*)pLibBlk + len;
3033 switch(*(WORD*)pNameTable) {
3040 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3044 pNameTable += 0x216;
3048 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3050 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3053 /* Hopefully we now have enough ptrs set up to actually read in
3054 some TypeInfos. It's not clear which order to do them in, so
3055 I'll just follow the links along the BlkEntry chain and read
3056 them in in the order in which they're in the file */
3058 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3060 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3061 pBlkEntry[order].next != 0;
3062 order = pBlkEntry[order].next - 1, i++) {
3064 SLTG_TypeInfoHeader *pTIHeader;
3065 SLTG_TypeInfoTail *pTITail;
3067 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3068 pOtherTypeInfoBlks[i].index_name)) {
3069 FIXME("Index strings don't match\n");
3074 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3075 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3078 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3079 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3080 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
3081 (*ppTypeInfoImpl)->index = i;
3082 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3083 pOtherTypeInfoBlks[i].name_offs +
3085 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3086 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3088 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3089 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3090 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3091 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3092 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3094 if((pTIHeader->typeflags1 & 7) != 2)
3095 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3096 if(pTIHeader->typeflags3 != 2)
3097 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3099 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3100 debugstr_w((*ppTypeInfoImpl)->Name),
3101 typekind_desc[pTIHeader->typekind],
3102 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3103 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3105 switch(pTIHeader->typekind) {
3107 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3111 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3114 case TKIND_INTERFACE:
3115 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3119 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3123 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3129 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3130 but we've already set those */
3131 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3132 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3133 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3135 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3136 pBlk = (char*)pBlk + pBlkEntry[order].len;
3139 if(i != pTypeLibImpl->TypeInfoCount) {
3140 FIXME("Somehow processed %d TypeInfos\n", i);
3144 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3145 return (ITypeLib2*)pTypeLibImpl;
3148 /* ITypeLib::QueryInterface
3150 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3155 ICOM_THIS( ITypeLibImpl, iface);
3157 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3160 if(IsEqualIID(riid, &IID_IUnknown) ||
3161 IsEqualIID(riid,&IID_ITypeLib)||
3162 IsEqualIID(riid,&IID_ITypeLib2))
3169 ITypeLib2_AddRef(iface);
3170 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3173 TRACE("-- Interface: E_NOINTERFACE\n");
3174 return E_NOINTERFACE;
3179 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3181 ICOM_THIS( ITypeLibImpl, iface);
3183 TRACE("(%p)->ref is %u\n",This, This->ref);
3185 return ++(This->ref);
3188 /* ITypeLib::Release
3190 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3192 ICOM_THIS( ITypeLibImpl, iface);
3196 TRACE("(%p)->(%u)\n",This, This->ref);
3200 /* FIXME destroy child objects */
3202 TRACE(" destroying ITypeLib(%p)\n",This);
3206 SysFreeString(This->Name);
3210 if (This->DocString)
3212 SysFreeString(This->DocString);
3213 This->DocString = NULL;
3218 SysFreeString(This->HelpFile);
3219 This->HelpFile = NULL;
3222 if (This->HelpStringDll)
3224 SysFreeString(This->HelpStringDll);
3225 This->HelpStringDll = NULL;
3228 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3229 HeapFree(GetProcessHeap(),0,This);
3236 /* ITypeLib::GetTypeInfoCount
3238 * Returns the number of type descriptions in the type library
3240 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3242 ICOM_THIS( ITypeLibImpl, iface);
3243 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3244 return This->TypeInfoCount;
3247 /* ITypeLib::GetTypeInfo
3249 * retrieves the specified type description in the library.
3251 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3254 ITypeInfo **ppTInfo)
3258 ICOM_THIS( ITypeLibImpl, iface);
3259 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3261 TRACE("(%p)->(index=%d) \n", This, index);
3263 if (!ppTInfo) return E_INVALIDARG;
3265 /* search element n in list */
3266 for(i=0; i < index; i++)
3268 pTypeInfo = pTypeInfo->next;
3271 TRACE("-- element not found\n");
3272 return TYPE_E_ELEMENTNOTFOUND;
3276 *ppTInfo = (ITypeInfo *) pTypeInfo;
3278 ITypeInfo_AddRef(*ppTInfo);
3279 TRACE("-- found (%p)\n",*ppTInfo);
3284 /* ITypeLibs::GetTypeInfoType
3286 * Retrieves the type of a type description.
3288 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3293 ICOM_THIS( ITypeLibImpl, iface);
3295 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3297 TRACE("(%p) index %d \n",This, index);
3299 if(!pTKind) return E_INVALIDARG;
3301 /* search element n in list */
3302 for(i=0; i < index; i++)
3306 TRACE("-- element not found\n");
3307 return TYPE_E_ELEMENTNOTFOUND;
3309 pTInfo = pTInfo->next;
3312 *pTKind = pTInfo->TypeAttr.typekind;
3313 TRACE("-- found Type (%d)\n", *pTKind);
3317 /* ITypeLib::GetTypeInfoOfGuid
3319 * Retrieves the type description that corresponds to the specified GUID.
3322 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3325 ITypeInfo **ppTInfo)
3327 ICOM_THIS( ITypeLibImpl, iface);
3328 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3330 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3332 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3334 /* search linked list for guid */
3335 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3337 pTypeInfo = pTypeInfo->next;
3341 /* end of list reached */
3342 TRACE("-- element not found\n");
3343 return TYPE_E_ELEMENTNOTFOUND;
3347 TRACE("-- found (%p, %s)\n",
3349 debugstr_w(pTypeInfo->Name));
3351 *ppTInfo = (ITypeInfo*)pTypeInfo;
3352 ITypeInfo_AddRef(*ppTInfo);
3356 /* ITypeLib::GetLibAttr
3358 * Retrieves the structure that contains the library's attributes.
3361 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3363 LPTLIBATTR *ppTLibAttr)
3365 ICOM_THIS( ITypeLibImpl, iface);
3366 TRACE("(%p)\n",This);
3367 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3368 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3372 /* ITypeLib::GetTypeComp
3374 * Enables a client compiler to bind to a library's types, variables,
3375 * constants, and global functions.
3378 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3380 ITypeComp **ppTComp)
3382 ICOM_THIS( ITypeLibImpl, iface);
3383 FIXME("(%p): stub!\n",This);
3387 /* ITypeLib::GetDocumentation
3389 * Retrieves the library's documentation string, the complete Help file name
3390 * and path, and the context identifier for the library Help topic in the Help
3393 * On a successful return all non-null BSTR pointers will have been set,
3396 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3400 BSTR *pBstrDocString,
3401 DWORD *pdwHelpContext,
3402 BSTR *pBstrHelpFile)
3404 ICOM_THIS( ITypeLibImpl, iface);
3406 HRESULT result = E_INVALIDARG;
3411 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3413 pBstrName, pBstrDocString,
3414 pdwHelpContext, pBstrHelpFile);
3418 /* documentation for the typelib */
3422 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3428 if (This->DocString)
3429 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3430 else if (This->Name)
3431 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3433 *pBstrDocString = NULL;
3437 *pdwHelpContext = This->dwHelpContext;
3442 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3444 *pBstrHelpFile = NULL;
3451 /* for a typeinfo */
3452 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3454 if(SUCCEEDED(result))
3456 result = ITypeInfo_GetDocumentation(pTInfo,
3460 pdwHelpContext, pBstrHelpFile);
3462 ITypeInfo_Release(pTInfo);
3467 if (pBstrDocString) SysFreeString (*pBstrDocString);
3469 if (pBstrName) SysFreeString (*pBstrName);
3471 return STG_E_INSUFFICIENTMEMORY;
3476 * Indicates whether a passed-in string contains the name of a type or member
3477 * described in the library.
3480 static HRESULT WINAPI ITypeLib2_fnIsName(
3486 ICOM_THIS( ITypeLibImpl, iface);
3487 ITypeInfoImpl *pTInfo;
3488 TLBFuncDesc *pFInfo;
3491 UINT nNameBufLen = SysStringLen(szNameBuf);
3493 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3497 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3498 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3499 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3500 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3501 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3502 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3503 goto ITypeLib2_fnIsName_exit;
3505 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3506 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3511 ITypeLib2_fnIsName_exit:
3512 TRACE("(%p)slow! search for %s: %s found!\n", This,
3513 debugstr_w(szNameBuf), *pfName?"NOT":"");
3518 /* ITypeLib::FindName
3520 * Finds occurrences of a type description in a type library. This may be used
3521 * to quickly verify that a name exists in a type library.
3524 static HRESULT WINAPI ITypeLib2_fnFindName(
3528 ITypeInfo **ppTInfo,
3532 ICOM_THIS( ITypeLibImpl, iface);
3533 ITypeInfoImpl *pTInfo;
3534 TLBFuncDesc *pFInfo;
3538 UINT nNameBufLen = SysStringLen(szNameBuf);
3540 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3541 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3542 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3543 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3544 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3545 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3546 goto ITypeLib2_fnFindName_exit;
3548 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3549 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3551 ITypeLib2_fnFindName_exit:
3552 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3553 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3556 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3557 This, *pcFound, debugstr_w(szNameBuf), j);
3564 /* ITypeLib::ReleaseTLibAttr
3566 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3569 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3571 TLIBATTR *pTLibAttr)
3573 ICOM_THIS( ITypeLibImpl, iface);
3574 TRACE("freeing (%p)\n",This);
3575 HeapFree(GetProcessHeap(),0,pTLibAttr);
3579 /* ITypeLib2::GetCustData
3581 * gets the custom data
3583 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3588 ICOM_THIS( ITypeLibImpl, iface);
3589 TLBCustData *pCData;
3591 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3593 if( IsEqualIID(guid, &pCData->guid)) break;
3596 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3600 VariantInit( pVarVal);
3601 VariantCopy( pVarVal, &pCData->data);
3604 return E_INVALIDARG; /* FIXME: correct? */
3607 /* ITypeLib2::GetLibStatistics
3609 * Returns statistics about a type library that are required for efficient
3610 * sizing of hash tables.
3613 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3615 ULONG *pcUniqueNames,
3616 ULONG *pcchUniqueNames)
3618 ICOM_THIS( ITypeLibImpl, iface);
3620 FIXME("(%p): stub!\n", This);
3622 if(pcUniqueNames) *pcUniqueNames=1;
3623 if(pcchUniqueNames) *pcchUniqueNames=1;
3627 /* ITypeLib2::GetDocumentation2
3629 * Retrieves the library's documentation string, the complete Help file name
3630 * and path, the localization context to use, and the context ID for the
3631 * library Help topic in the Help file.
3634 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3638 BSTR *pbstrHelpString,
3639 DWORD *pdwHelpStringContext,
3640 BSTR *pbstrHelpStringDll)
3642 ICOM_THIS( ITypeLibImpl, iface);
3646 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3648 /* the help string should be obtained from the helpstringdll,
3649 * using the _DLLGetDocumentation function, based on the supplied
3650 * lcid. Nice to do sometime...
3654 /* documentation for the typelib */
3656 *pbstrHelpString=SysAllocString(This->DocString);
3657 if(pdwHelpStringContext)
3658 *pdwHelpStringContext=This->dwHelpContext;
3659 if(pbstrHelpStringDll)
3660 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3666 /* for a typeinfo */
3667 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3669 if(SUCCEEDED(result))
3671 ITypeInfo2 * pTInfo2;
3672 result = ITypeInfo_QueryInterface(pTInfo,
3674 (LPVOID*) &pTInfo2);
3676 if(SUCCEEDED(result))
3678 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3682 pdwHelpStringContext,
3683 pbstrHelpStringDll);
3685 ITypeInfo2_Release(pTInfo2);
3688 ITypeInfo_Release(pTInfo);
3694 /* ITypeLib2::GetAllCustData
3696 * Gets all custom data items for the library.
3699 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3701 CUSTDATA *pCustData)
3703 ICOM_THIS( ITypeLibImpl, iface);
3704 TLBCustData *pCData;
3706 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3707 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3708 if(pCustData->prgCustData ){
3709 pCustData->cCustData=This->ctCustData;
3710 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3711 pCustData->prgCustData[i].guid=pCData->guid;
3712 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3715 ERR(" OUT OF MEMORY! \n");
3716 return E_OUTOFMEMORY;
3721 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3722 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3723 ITypeLib2_fnQueryInterface,
3725 ITypeLib2_fnRelease,
3726 ITypeLib2_fnGetTypeInfoCount,
3727 ITypeLib2_fnGetTypeInfo,
3728 ITypeLib2_fnGetTypeInfoType,
3729 ITypeLib2_fnGetTypeInfoOfGuid,
3730 ITypeLib2_fnGetLibAttr,
3731 ITypeLib2_fnGetTypeComp,
3732 ITypeLib2_fnGetDocumentation,
3734 ITypeLib2_fnFindName,
3735 ITypeLib2_fnReleaseTLibAttr,
3737 ITypeLib2_fnGetCustData,
3738 ITypeLib2_fnGetLibStatistics,
3739 ITypeLib2_fnGetDocumentation2,
3740 ITypeLib2_fnGetAllCustData
3743 /*================== ITypeInfo(2) Methods ===================================*/
3744 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3746 ITypeInfoImpl * pTypeInfoImpl;
3748 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3751 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3752 pTypeInfoImpl->ref=1;
3754 TRACE("(%p)\n", pTypeInfoImpl);
3755 return (ITypeInfo2*) pTypeInfoImpl;
3758 /* ITypeInfo::QueryInterface
3760 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3765 ICOM_THIS( ITypeLibImpl, iface);
3767 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3770 if(IsEqualIID(riid, &IID_IUnknown) ||
3771 IsEqualIID(riid,&IID_ITypeInfo)||
3772 IsEqualIID(riid,&IID_ITypeInfo2))
3776 ITypeInfo_AddRef(iface);
3777 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3780 TRACE("-- Interface: E_NOINTERFACE\n");
3781 return E_NOINTERFACE;
3784 /* ITypeInfo::AddRef
3786 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3788 ICOM_THIS( ITypeInfoImpl, iface);
3792 TRACE("(%p)->ref is %u\n",This, This->ref);
3796 /* ITypeInfo::Release
3798 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3800 ICOM_THIS( ITypeInfoImpl, iface);
3804 TRACE("(%p)->(%u)\n",This, This->ref);
3808 FIXME("destroy child objects\n");
3810 TRACE("destroying ITypeInfo(%p)\n",This);
3813 SysFreeString(This->Name);
3817 if (This->DocString)
3819 SysFreeString(This->DocString);
3820 This->DocString = 0;
3825 ITypeInfo_Release((ITypeInfo*)This->next);
3828 HeapFree(GetProcessHeap(),0,This);
3834 /* ITypeInfo::GetTypeAttr
3836 * Retrieves a TYPEATTR structure that contains the attributes of the type
3840 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3841 LPTYPEATTR *ppTypeAttr)
3843 ICOM_THIS( ITypeInfoImpl, iface);
3844 TRACE("(%p)\n",This);
3845 /* FIXME: must do a copy here */
3846 *ppTypeAttr=&This->TypeAttr;
3850 /* ITypeInfo::GetTypeComp
3852 * Retrieves the ITypeComp interface for the type description, which enables a
3853 * client compiler to bind to the type description's members.
3856 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3857 ITypeComp * *ppTComp)
3859 ICOM_THIS( ITypeInfoImpl, iface);
3860 FIXME("(%p) stub!\n", This);
3864 /* ITypeInfo::GetFuncDesc
3866 * Retrieves the FUNCDESC structure that contains information about a
3867 * specified function.
3870 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3871 LPFUNCDESC *ppFuncDesc)
3873 ICOM_THIS( ITypeInfoImpl, iface);
3875 TLBFuncDesc * pFDesc;
3876 TRACE("(%p) index %d\n", This, index);
3877 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3880 /* FIXME: must do a copy here */
3881 *ppFuncDesc=&pFDesc->funcdesc;
3884 return E_INVALIDARG;
3887 /* ITypeInfo::GetVarDesc
3889 * Retrieves a VARDESC structure that describes the specified variable.
3892 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3893 LPVARDESC *ppVarDesc)
3895 ICOM_THIS( ITypeInfoImpl, iface);
3897 TLBVarDesc * pVDesc;
3898 TRACE("(%p) index %d\n", This, index);
3899 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3902 /* FIXME: must do a copy here */
3903 *ppVarDesc=&pVDesc->vardesc;
3906 return E_INVALIDARG;
3909 /* ITypeInfo_GetNames
3911 * Retrieves the variable with the specified member ID (or the name of the
3912 * property or method and its parameters) that correspond to the specified
3915 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3916 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3918 ICOM_THIS( ITypeInfoImpl, iface);
3919 TLBFuncDesc * pFDesc;
3920 TLBVarDesc * pVDesc;
3922 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3923 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3926 /* function found, now return function and parameter names */
3927 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3930 *rgBstrNames=SysAllocString(pFDesc->Name);
3932 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3938 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3941 *rgBstrNames=SysAllocString(pVDesc->Name);
3946 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3948 /* recursive search */
3951 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3953 if(SUCCEEDED(result))
3955 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3956 ITypeInfo_Release(pTInfo);
3959 WARN("Could not search inherited interface!\n");
3963 WARN("no names found\n");
3966 return TYPE_E_ELEMENTNOTFOUND;
3973 /* ITypeInfo::GetRefTypeOfImplType
3975 * If a type description describes a COM class, it retrieves the type
3976 * description of the implemented interface types. For an interface,
3977 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3981 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3986 ICOM_THIS( ITypeInfoImpl, iface);
3988 TLBImplType *pImpl = This->impltypelist;
3990 TRACE("(%p) index %d\n", This, index);
3991 dump_TypeInfo(This);
3995 /* only valid on dual interfaces;
3996 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3998 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4000 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4001 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4007 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4008 *pRefType = pImpl->hRef;
4013 /* get element n from linked list */
4014 for(i=0; pImpl && i<index; i++)
4016 pImpl = pImpl->next;
4019 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4021 *pRefType = pImpl->hRef;
4023 TRACE("-- 0x%08lx\n", pImpl->hRef );
4030 /* ITypeInfo::GetImplTypeFlags
4032 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4033 * or base interface in a type description.
4035 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4036 UINT index, INT *pImplTypeFlags)
4038 ICOM_THIS( ITypeInfoImpl, iface);
4042 TRACE("(%p) index %d\n", This, index);
4043 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4044 i++, pImpl=pImpl->next)
4046 if(i==index && pImpl){
4047 *pImplTypeFlags=pImpl->implflags;
4051 return TYPE_E_ELEMENTNOTFOUND;
4055 * Maps between member names and member IDs, and parameter names and
4058 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4059 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4061 ICOM_THIS( ITypeInfoImpl, iface);
4062 TLBFuncDesc * pFDesc;
4063 TLBVarDesc * pVDesc;
4066 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4068 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4070 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4071 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4072 for(i=1; i < cNames; i++){
4073 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4074 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4076 if( j<pFDesc->funcdesc.cParams)
4079 ret=DISP_E_UNKNOWNNAME;
4084 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4085 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4086 if(cNames) *pMemId=pVDesc->vardesc.memid;
4090 /* not found, see if this is and interface with an inheritance */
4091 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4092 This->TypeAttr.cImplTypes ){
4093 /* recursive search */
4095 ret=ITypeInfo_GetRefTypeInfo(iface,
4096 This->impltypelist->hRef, &pTInfo);
4098 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4099 ITypeInfo_Release(pTInfo);
4102 WARN("Could not search inherited interface!\n");
4104 WARN("no names found\n");
4105 return DISP_E_UNKNOWNNAME;
4108 /* ITypeInfo::Invoke
4110 * Invokes a method, or accesses a property of an object, that implements the
4111 * interface described by the type description.
4114 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
4117 if (TRACE_ON(ole)) {
4119 MESSAGE("Calling %p(",func);
4120 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
4129 DWORD (WINAPI *xfunc)() = func;
4134 DWORD (WINAPI *xfunc)(DWORD) = func;
4135 res = xfunc(args[0]);
4139 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
4140 res = xfunc(args[0],args[1]);
4144 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
4145 res = xfunc(args[0],args[1],args[2]);
4149 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
4150 res = xfunc(args[0],args[1],args[2],args[3]);
4154 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4155 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4159 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4160 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4164 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4165 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4169 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4170 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4174 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4175 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4179 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4185 FIXME("unsupported calling convention %d\n",callconv);
4189 TRACE("returns %08lx\n",res);
4193 extern int const _argsize(DWORD vt);
4195 /***********************************************************************
4196 * DispCallFunc (OLEAUT32.@)
4200 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4201 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4203 int i, argsize, argspos;
4207 FIXME("(%p, %ld, %d, %d, %d, %p, %p, %p)\n",
4208 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult
4211 for (i=0;i<cActuals;i++) {
4212 FIXME("arg %d: type %d\n",i,prgvt[i]);
4213 dump_Variant(prgpvarg[i]);
4214 argsize += _argsize(prgvt[i]);
4216 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4218 for (i=0;i<cActuals;i++) {
4220 VARIANT *arg = prgpvarg[i];
4222 arglen = _argsize(prgvt[i]);
4223 if (V_VT(arg) == prgvt[i]) {
4224 memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
4226 if (prgvt[i] == VT_VARIANT) {
4227 memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
4229 ERR("Set arg %d to disparg type %d vs %d\n",i,
4237 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4239 hres = _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize/4,args);
4240 HeapFree(GetProcessHeap(),0,args);
4244 static HRESULT WINAPI ITypeInfo_fnInvoke(
4249 DISPPARAMS *pDispParams,
4250 VARIANT *pVarResult,
4251 EXCEPINFO *pExcepInfo,
4254 ICOM_THIS( ITypeInfoImpl, iface);
4255 TLBFuncDesc * pFDesc;
4256 TLBVarDesc * pVDesc;
4259 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4260 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4262 dump_DispParms(pDispParams);
4264 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4265 if (pFDesc->funcdesc.memid == memid) {
4266 if (pFDesc->funcdesc.invkind & dwFlags)
4270 dump_TLBFuncDescOne(pFDesc);
4271 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4272 switch (pFDesc->funcdesc.funckind) {
4273 case FUNC_PUREVIRTUAL:
4274 case FUNC_VIRTUAL: {
4276 int numargs, numargs2, argspos, args2pos;
4277 DWORD *args , *args2;
4280 numargs = 1; numargs2 = 0;
4281 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4282 if (i<pDispParams->cArgs)
4283 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4285 numargs += 1; /* sizeof(lpvoid) */
4286 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4290 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4291 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4293 args[0] = (DWORD)pIUnk;
4294 argspos = 1; args2pos = 0;
4295 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4296 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4297 if (i<pDispParams->cArgs) {
4298 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4299 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4301 if (V_VT(arg) == tdesc->vt) {
4302 memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
4304 if (tdesc->vt == VT_VARIANT) {
4305 memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
4307 ERR("Set arg %d to disparg type %d vs %d\n",i,
4314 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4315 if (tdesc->vt != VT_PTR)
4316 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4317 /*FIXME: give pointers for the rest, so propertyget works*/
4318 args[argspos] = (DWORD)&args2[args2pos];
4320 /* If pointer to variant, pass reference it. */
4321 if ((tdesc->vt == VT_PTR) &&
4322 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4325 args[argspos]= (DWORD)pVarResult;
4330 if (pFDesc->funcdesc.cParamsOpt)
4331 FIXME("Does not support optional parameters (%d)\n",
4332 pFDesc->funcdesc.cParamsOpt
4335 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4336 pFDesc->funcdesc.callconv,
4340 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4342 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4343 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4344 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4345 /* If we are a pointer to a variant, we are done already */
4346 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4349 VariantInit(pVarResult);
4350 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4352 if (tdesc->vt == VT_PTR)
4353 tdesc = tdesc->u.lptdesc;
4354 V_VT(pVarResult) = tdesc->vt;
4356 /* HACK: VB5 likes this.
4357 * I do not know why. There is 1 example in MSDN which uses
4358 * this which appears broken (mixes int vals and
4361 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4362 V_VT(pVarResult) = VT_DISPATCH;
4363 TRACE("storing into variant:\n");
4364 dump_Variant(pVarResult);
4368 HeapFree(GetProcessHeap(),0,args2);
4369 HeapFree(GetProcessHeap(),0,args);
4372 case FUNC_DISPATCH: {
4376 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4378 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4381 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4382 hr = IDispatch_Invoke(
4383 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4384 pVarResult,pExcepInfo,pArgErr
4387 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4388 IDispatch_Release(disp);
4392 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4396 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4397 if (pVDesc->vardesc.memid == memid) {
4398 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4399 dump_TLBVarDesc(pVDesc);
4404 /* not found, look for it in inherited interfaces */
4405 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4406 /* recursive search */
4409 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4411 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4412 ITypeInfo_Release(pTInfo);
4415 WARN("Could not search inherited interface!\n");
4417 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4418 return DISP_E_MEMBERNOTFOUND;
4421 /* ITypeInfo::GetDocumentation
4423 * Retrieves the documentation string, the complete Help file name and path,
4424 * and the context ID for the Help topic for a specified type description.
4426 * (Can be tested by the Visual Basic Editor in Word for instance.)
4428 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4429 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4430 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4432 ICOM_THIS( ITypeInfoImpl, iface);
4433 TLBFuncDesc * pFDesc;
4434 TLBVarDesc * pVDesc;
4435 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4436 " HelpContext(%p) HelpFile(%p)\n",
4437 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4438 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4440 *pBstrName=SysAllocString(This->Name);
4442 *pBstrDocString=SysAllocString(This->DocString);
4444 *pdwHelpContext=This->dwHelpContext;
4446 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4448 }else {/* for a member */
4449 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4450 if(pFDesc->funcdesc.memid==memid){
4452 *pBstrName = SysAllocString(pFDesc->Name);
4454 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4456 *pdwHelpContext=pFDesc->helpcontext;
4459 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4460 if(pVDesc->vardesc.memid==memid){
4462 *pBstrName = SysAllocString(pVDesc->Name);
4464 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4466 *pdwHelpContext=pVDesc->HelpContext;
4470 return TYPE_E_ELEMENTNOTFOUND;
4473 /* ITypeInfo::GetDllEntry
4475 * Retrieves a description or specification of an entry point for a function
4478 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4479 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4482 ICOM_THIS( ITypeInfoImpl, iface);
4483 TLBFuncDesc *pFDesc;
4485 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4487 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4488 if(pFDesc->funcdesc.memid==memid){
4489 dump_TypeInfo(This);
4490 dump_TLBFuncDescOne(pFDesc);
4492 /* FIXME: This is wrong, but how do you find that out? */
4494 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4495 *pBstrDllName = SysAllocString(oleaut32W);
4498 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4500 *pBstrName = SysAllocString(pFDesc->Entry);
4508 *pwOrdinal = (DWORD)pFDesc->Entry;
4514 /* ITypeInfo::GetRefTypeInfo
4516 * If a type description references other type descriptions, it retrieves
4517 * the referenced type descriptions.
4519 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4522 ITypeInfo **ppTInfo)
4524 ICOM_THIS( ITypeInfoImpl, iface);
4525 HRESULT result = E_FAIL;
4528 if (hRefType == -1 &&
4529 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4530 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4532 /* when we meet a DUAL dispinterface, we must create the interface
4535 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4538 /* the interface version contains the same information as the dispinterface
4539 * copy the contents of the structs.
4541 *pTypeInfoImpl = *This;
4542 pTypeInfoImpl->ref = 1;
4544 /* change the type to interface */
4545 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4547 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4549 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4554 TLBRefType *pRefType;
4555 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4556 if(pRefType->reference == hRefType)
4560 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4561 if(pRefType && hRefType != -1) {
4562 ITypeLib *pTLib = NULL;
4564 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4566 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4568 if(pRefType->pImpTLInfo->pImpTypeLib) {
4569 TRACE("typeinfo in imported typelib that is already loaded\n");
4570 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4571 ITypeLib2_AddRef((ITypeLib*) pTLib);
4574 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4575 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4576 pRefType->pImpTLInfo->wVersionMajor,
4577 pRefType->pImpTLInfo->wVersionMinor,
4578 pRefType->pImpTLInfo->lcid,
4581 if(!SUCCEEDED(result)) {
4582 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4583 result=LoadTypeLib(libnam, &pTLib);
4584 SysFreeString(libnam);
4586 if(SUCCEEDED(result)) {
4587 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4588 ITypeLib2_AddRef(pTLib);
4592 if(SUCCEEDED(result)) {
4593 if(pRefType->index == TLB_REF_USE_GUID)
4594 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4598 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4602 ITypeLib2_Release(pTLib);
4606 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4607 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4611 /* ITypeInfo::AddressOfMember
4613 * Retrieves the addresses of static functions or variables, such as those
4616 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4617 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4619 ICOM_THIS( ITypeInfoImpl, iface);
4620 FIXME("(%p) stub!\n", This);
4624 /* ITypeInfo::CreateInstance
4626 * Creates a new instance of a type that describes a component object class
4629 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4630 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4632 ICOM_THIS( ITypeInfoImpl, iface);
4633 FIXME("(%p) stub!\n", This);
4637 /* ITypeInfo::GetMops
4639 * Retrieves marshaling information.
4641 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4644 ICOM_THIS( ITypeInfoImpl, iface);
4645 FIXME("(%p) stub!\n", This);
4649 /* ITypeInfo::GetContainingTypeLib
4651 * Retrieves the containing type library and the index of the type description
4652 * within that type library.
4654 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4655 ITypeLib * *ppTLib, UINT *pIndex)
4657 ICOM_THIS( ITypeInfoImpl, iface);
4659 return E_INVALIDARG;
4660 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4661 *pIndex=This->index;
4662 ITypeLib2_AddRef(*ppTLib);
4663 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4667 /* ITypeInfo::ReleaseTypeAttr
4669 * Releases a TYPEATTR previously returned by GetTypeAttr.
4672 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4673 TYPEATTR* pTypeAttr)
4675 ICOM_THIS( ITypeInfoImpl, iface);
4676 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4680 /* ITypeInfo::ReleaseFuncDesc
4682 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4684 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4686 FUNCDESC *pFuncDesc)
4688 ICOM_THIS( ITypeInfoImpl, iface);
4689 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4693 /* ITypeInfo::ReleaseVarDesc
4695 * Releases a VARDESC previously returned by GetVarDesc.
4697 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4700 ICOM_THIS( ITypeInfoImpl, iface);
4701 TRACE("(%p)->(%p)\n", This, pVarDesc);
4705 /* ITypeInfo2::GetTypeKind
4707 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4710 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4711 TYPEKIND *pTypeKind)
4713 ICOM_THIS( ITypeInfoImpl, iface);
4714 *pTypeKind=This->TypeAttr.typekind;
4715 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4719 /* ITypeInfo2::GetTypeFlags
4721 * Returns the type flags without any allocations. This returns a DWORD type
4722 * flag, which expands the type flags without growing the TYPEATTR (type
4726 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4729 ICOM_THIS( ITypeInfoImpl, iface);
4730 *pTypeFlags=This->TypeAttr.wTypeFlags;
4731 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4735 /* ITypeInfo2::GetFuncIndexOfMemId
4736 * Binds to a specific member based on a known DISPID, where the member name
4737 * is not known (for example, when binding to a default member).
4740 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4741 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4743 ICOM_THIS( ITypeInfoImpl, iface);
4744 TLBFuncDesc *pFuncInfo;
4747 /* FIXME: should check for invKind??? */
4748 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4749 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4755 result=E_INVALIDARG;
4757 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4758 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4762 /* TypeInfo2::GetVarIndexOfMemId
4764 * Binds to a specific member based on a known DISPID, where the member name
4765 * is not known (for example, when binding to a default member).
4768 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4769 MEMBERID memid, UINT *pVarIndex)
4771 ICOM_THIS( ITypeInfoImpl, iface);
4772 TLBVarDesc *pVarInfo;
4775 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4776 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4783 result=E_INVALIDARG;
4785 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4786 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4790 /* ITypeInfo2::GetCustData
4792 * Gets the custom data
4794 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4799 ICOM_THIS( ITypeInfoImpl, iface);
4800 TLBCustData *pCData;
4802 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4803 if( IsEqualIID(guid, &pCData->guid)) break;
4805 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4809 VariantInit( pVarVal);
4810 VariantCopy( pVarVal, &pCData->data);
4813 return E_INVALIDARG; /* FIXME: correct? */
4816 /* ITypeInfo2::GetFuncCustData
4818 * Gets the custom data
4820 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4826 ICOM_THIS( ITypeInfoImpl, iface);
4827 TLBCustData *pCData=NULL;
4828 TLBFuncDesc * pFDesc;
4830 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4831 pFDesc=pFDesc->next);
4834 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4835 if( IsEqualIID(guid, &pCData->guid)) break;
4837 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4840 VariantInit( pVarVal);
4841 VariantCopy( pVarVal, &pCData->data);
4844 return E_INVALIDARG; /* FIXME: correct? */
4847 /* ITypeInfo2::GetParamCustData
4849 * Gets the custom data
4851 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4858 ICOM_THIS( ITypeInfoImpl, iface);
4859 TLBCustData *pCData=NULL;
4860 TLBFuncDesc * pFDesc;
4863 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4865 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4866 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4867 pCData = pCData->next)
4868 if( IsEqualIID(guid, &pCData->guid)) break;
4870 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4874 VariantInit( pVarVal);
4875 VariantCopy( pVarVal, &pCData->data);
4878 return E_INVALIDARG; /* FIXME: correct? */
4881 /* ITypeInfo2::GetVarCustData
4883 * Gets the custom data
4885 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4891 ICOM_THIS( ITypeInfoImpl, iface);
4892 TLBCustData *pCData=NULL;
4893 TLBVarDesc * pVDesc;
4896 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4900 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4902 if( IsEqualIID(guid, &pCData->guid)) break;
4906 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4910 VariantInit( pVarVal);
4911 VariantCopy( pVarVal, &pCData->data);
4914 return E_INVALIDARG; /* FIXME: correct? */
4917 /* ITypeInfo2::GetImplCustData
4919 * Gets the custom data
4921 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4927 ICOM_THIS( ITypeInfoImpl, iface);
4928 TLBCustData *pCData=NULL;
4929 TLBImplType * pRDesc;
4932 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4936 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4938 if( IsEqualIID(guid, &pCData->guid)) break;
4942 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4946 VariantInit( pVarVal);
4947 VariantCopy( pVarVal, &pCData->data);
4950 return E_INVALIDARG; /* FIXME: correct? */
4953 /* ITypeInfo2::GetDocumentation2
4955 * Retrieves the documentation string, the complete Help file name and path,
4956 * the localization context to use, and the context ID for the library Help
4957 * topic in the Help file.
4960 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4964 BSTR *pbstrHelpString,
4965 DWORD *pdwHelpStringContext,
4966 BSTR *pbstrHelpStringDll)
4968 ICOM_THIS( ITypeInfoImpl, iface);
4969 TLBFuncDesc * pFDesc;
4970 TLBVarDesc * pVDesc;
4971 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4972 "HelpStringContext(%p) HelpStringDll(%p)\n",
4973 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4974 pbstrHelpStringDll );
4975 /* the help string should be obtained from the helpstringdll,
4976 * using the _DLLGetDocumentation function, based on the supplied
4977 * lcid. Nice to do sometime...
4979 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4981 *pbstrHelpString=SysAllocString(This->Name);
4982 if(pdwHelpStringContext)
4983 *pdwHelpStringContext=This->dwHelpStringContext;
4984 if(pbstrHelpStringDll)
4985 *pbstrHelpStringDll=
4986 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4988 }else {/* for a member */
4989 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4990 if(pFDesc->funcdesc.memid==memid){
4992 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4993 if(pdwHelpStringContext)
4994 *pdwHelpStringContext=pFDesc->HelpStringContext;
4995 if(pbstrHelpStringDll)
4996 *pbstrHelpStringDll=
4997 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5000 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5001 if(pVDesc->vardesc.memid==memid){
5003 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5004 if(pdwHelpStringContext)
5005 *pdwHelpStringContext=pVDesc->HelpStringContext;
5006 if(pbstrHelpStringDll)
5007 *pbstrHelpStringDll=
5008 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5012 return TYPE_E_ELEMENTNOTFOUND;
5015 /* ITypeInfo2::GetAllCustData
5017 * Gets all custom data items for the Type info.
5020 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5022 CUSTDATA *pCustData)
5024 ICOM_THIS( ITypeInfoImpl, iface);
5025 TLBCustData *pCData;
5028 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5030 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5031 if(pCustData->prgCustData ){
5032 pCustData->cCustData=This->ctCustData;
5033 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5034 pCustData->prgCustData[i].guid=pCData->guid;
5035 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5038 ERR(" OUT OF MEMORY! \n");
5039 return E_OUTOFMEMORY;
5044 /* ITypeInfo2::GetAllFuncCustData
5046 * Gets all custom data items for the specified Function
5049 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5052 CUSTDATA *pCustData)
5054 ICOM_THIS( ITypeInfoImpl, iface);
5055 TLBCustData *pCData;
5056 TLBFuncDesc * pFDesc;
5058 TRACE("(%p) index %d\n", This, index);
5059 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5060 pFDesc=pFDesc->next)
5063 pCustData->prgCustData =
5064 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5065 if(pCustData->prgCustData ){
5066 pCustData->cCustData=pFDesc->ctCustData;
5067 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5068 pCData = pCData->next){
5069 pCustData->prgCustData[i].guid=pCData->guid;
5070 VariantCopy(& pCustData->prgCustData[i].varValue,
5074 ERR(" OUT OF MEMORY! \n");
5075 return E_OUTOFMEMORY;
5079 return TYPE_E_ELEMENTNOTFOUND;
5082 /* ITypeInfo2::GetAllParamCustData
5084 * Gets all custom data items for the Functions
5087 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5088 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5090 ICOM_THIS( ITypeInfoImpl, iface);
5091 TLBCustData *pCData=NULL;
5092 TLBFuncDesc * pFDesc;
5094 TRACE("(%p) index %d\n", This, indexFunc);
5095 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5096 pFDesc=pFDesc->next)
5098 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5099 pCustData->prgCustData =
5100 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5101 sizeof(CUSTDATAITEM));
5102 if(pCustData->prgCustData ){
5103 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5104 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5105 pCData; i++, pCData = pCData->next){
5106 pCustData->prgCustData[i].guid=pCData->guid;
5107 VariantCopy(& pCustData->prgCustData[i].varValue,
5111 ERR(" OUT OF MEMORY! \n");
5112 return E_OUTOFMEMORY;
5116 return TYPE_E_ELEMENTNOTFOUND;
5119 /* ITypeInfo2::GetAllVarCustData
5121 * Gets all custom data items for the specified Variable
5124 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5125 UINT index, CUSTDATA *pCustData)
5127 ICOM_THIS( ITypeInfoImpl, iface);
5128 TLBCustData *pCData;
5129 TLBVarDesc * pVDesc;
5131 TRACE("(%p) index %d\n", This, index);
5132 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5133 pVDesc=pVDesc->next)
5136 pCustData->prgCustData =
5137 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5138 if(pCustData->prgCustData ){
5139 pCustData->cCustData=pVDesc->ctCustData;
5140 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5141 pCData = pCData->next){
5142 pCustData->prgCustData[i].guid=pCData->guid;
5143 VariantCopy(& pCustData->prgCustData[i].varValue,
5147 ERR(" OUT OF MEMORY! \n");
5148 return E_OUTOFMEMORY;
5152 return TYPE_E_ELEMENTNOTFOUND;
5155 /* ITypeInfo2::GetAllImplCustData
5157 * Gets all custom data items for the specified implementation type
5160 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5163 CUSTDATA *pCustData)
5165 ICOM_THIS( ITypeInfoImpl, iface);
5166 TLBCustData *pCData;
5167 TLBImplType * pRDesc;
5169 TRACE("(%p) index %d\n", This, index);
5170 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5171 pRDesc=pRDesc->next)
5174 pCustData->prgCustData =
5175 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5176 if(pCustData->prgCustData ){
5177 pCustData->cCustData=pRDesc->ctCustData;
5178 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5179 pCData = pCData->next){
5180 pCustData->prgCustData[i].guid=pCData->guid;
5181 VariantCopy(& pCustData->prgCustData[i].varValue,
5185 ERR(" OUT OF MEMORY! \n");
5186 return E_OUTOFMEMORY;
5190 return TYPE_E_ELEMENTNOTFOUND;
5193 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5195 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5197 ITypeInfo_fnQueryInterface,
5199 ITypeInfo_fnRelease,
5201 ITypeInfo_fnGetTypeAttr,
5202 ITypeInfo_fnGetTypeComp,
5203 ITypeInfo_fnGetFuncDesc,
5204 ITypeInfo_fnGetVarDesc,
5205 ITypeInfo_fnGetNames,
5206 ITypeInfo_fnGetRefTypeOfImplType,
5207 ITypeInfo_fnGetImplTypeFlags,
5208 ITypeInfo_fnGetIDsOfNames,
5210 ITypeInfo_fnGetDocumentation,
5211 ITypeInfo_fnGetDllEntry,
5212 ITypeInfo_fnGetRefTypeInfo,
5213 ITypeInfo_fnAddressOfMember,
5214 ITypeInfo_fnCreateInstance,
5215 ITypeInfo_fnGetMops,
5216 ITypeInfo_fnGetContainingTypeLib,
5217 ITypeInfo_fnReleaseTypeAttr,
5218 ITypeInfo_fnReleaseFuncDesc,
5219 ITypeInfo_fnReleaseVarDesc,
5221 ITypeInfo2_fnGetTypeKind,
5222 ITypeInfo2_fnGetTypeFlags,
5223 ITypeInfo2_fnGetFuncIndexOfMemId,
5224 ITypeInfo2_fnGetVarIndexOfMemId,
5225 ITypeInfo2_fnGetCustData,
5226 ITypeInfo2_fnGetFuncCustData,
5227 ITypeInfo2_fnGetParamCustData,
5228 ITypeInfo2_fnGetVarCustData,
5229 ITypeInfo2_fnGetImplTypeCustData,
5230 ITypeInfo2_fnGetDocumentation2,
5231 ITypeInfo2_fnGetAllCustData,
5232 ITypeInfo2_fnGetAllFuncCustData,
5233 ITypeInfo2_fnGetAllParamCustData,
5234 ITypeInfo2_fnGetAllVarCustData,
5235 ITypeInfo2_fnGetAllImplTypeCustData,