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"
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 [OLEAUT32.164]
150 QueryPathOfRegTypeLib(
151 REFGUID guid, /* [in] referenced guid */
152 WORD wMaj, /* [in] major version */
153 WORD wMin, /* [in] minor version */
154 LCID lcid, /* [in] locale id */
155 LPBSTR path ) /* [out] path of typelib */
157 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
158 string termination character on output strings */
165 char szTypeLibKey[100];
166 char szPath[MAX_PATH];
167 DWORD dwPathLen = sizeof(szPath);
175 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
181 sprintf(szTypeLibKey,
182 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
183 guid->Data1, guid->Data2, guid->Data3,
184 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
185 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
190 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
194 else if (myLCID == lcid)
196 /* try with sub-langid */
197 myLCID = SUBLANGID(lcid);
199 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
201 /* try with system langid */
211 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
212 BSTR bstrPath = SysAllocStringLen(NULL,len);
214 MultiByteToWideChar(CP_ACP,
226 TRACE_(typelib)("%s not found\n", szTypeLibKey);
231 /******************************************************************************
232 * CreateTypeLib [OLEAUT32.160] creates a typelib
238 HRESULT WINAPI CreateTypeLib(
239 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
241 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
244 /******************************************************************************
245 * LoadTypeLib [OLEAUT32.161]
246 * Loads and registers a type library
248 * Docs: OLECHAR FAR* szFile
249 * Docs: iTypeLib FAR* FAR* pptLib
255 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
257 HRESULT WINAPI LoadTypeLib(
258 const OLECHAR *szFile,/* [in] Name of file to load from */
259 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
262 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
265 /******************************************************************************
266 * LoadTypeLibEx [OLEAUT32.183]
267 * Loads and optionally registers a type library
273 HRESULT WINAPI LoadTypeLibEx(
274 LPCOLESTR szFile, /* [in] Name of file to load from */
275 REGKIND regkind, /* [in] Specify kind of registration */
276 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
278 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
282 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
284 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
287 /* Look for a trailing '\\' followed by an index */
288 pIndexStr = strrchrW(szFile, '\\');
289 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
290 index = atoiW(pIndexStr);
291 memcpy(szFileCopy, szFile,
292 (pIndexStr - szFile - 1) * sizeof(WCHAR));
293 szFileCopy[pIndexStr - szFile - 1] = '\0';
294 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
296 return TYPE_E_CANTLOADLIBRARY;
297 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
298 return TYPE_E_CANTLOADLIBRARY;
300 return TYPE_E_CANTLOADLIBRARY;
303 TRACE("File %s index %d\n", debugstr_w(szPath), index);
305 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
310 case REGKIND_DEFAULT:
311 /* FIXME: is this correct? */
312 if (!szFile || !szFile[0] ||
313 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
315 /* else fall-through */
316 case REGKIND_REGISTER:
317 /* FIXME: Help path? */
318 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
320 IUnknown_Release(*pptLib);
328 TRACE(" returns %08lx\n",res);
332 /******************************************************************************
333 * LoadRegTypeLib [OLEAUT32.162]
335 HRESULT WINAPI LoadRegTypeLib(
336 REFGUID rguid, /* [in] referenced guid */
337 WORD wVerMajor, /* [in] major version */
338 WORD wVerMinor, /* [in] minor version */
339 LCID lcid, /* [in] locale id */
340 ITypeLib **ppTLib) /* [out] path of typelib */
343 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
347 res= LoadTypeLib(bstr, ppTLib);
351 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
357 /******************************************************************************
358 * RegisterTypeLib [OLEAUT32.163]
359 * Adds information about a type library to the System Registry
361 * Docs: ITypeLib FAR * ptlib
362 * Docs: OLECHAR FAR* szFullPath
363 * Docs: OLECHAR FAR* szHelpDir
369 HRESULT WINAPI RegisterTypeLib(
370 ITypeLib * ptlib, /* [in] Pointer to the library*/
371 OLECHAR * szFullPath, /* [in] full Path of the library*/
372 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
383 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
385 if (ptlib == NULL || szFullPath == NULL)
388 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
391 StringFromGUID2(&attr->guid, guid, 80);
392 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
393 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
394 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
395 HeapFree(GetProcessHeap(), 0, guidA);
398 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
399 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
403 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
405 if (RegSetValueExW(key, NULL, 0, REG_SZ,
406 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
414 /* FIXME: This *seems* to be 0 always, not sure though */
415 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
416 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
418 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
419 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
427 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
428 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
431 /* FIXME: is %u correct? */
432 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
433 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
434 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
442 /* register OLE Automation-compatible interfaces for this typelib */
443 types = ITypeLib_GetTypeInfoCount(ptlib);
444 for (tidx=0; tidx<types; tidx++) {
445 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
446 LPOLESTR name = NULL;
447 ITypeInfo *tinfo = NULL;
449 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
451 case TKIND_INTERFACE:
452 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
453 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
456 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
457 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
460 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
461 /* coclasses should probably not be registered? */
464 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
468 TYPEATTR *tattr = NULL;
469 ITypeInfo_GetTypeAttr(tinfo, &tattr);
471 TRACE_(typelib)("guid=%s, flags=%04x (",
472 debugstr_guid(&tattr->guid),
474 if (TRACE_ON(typelib)) {
475 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
495 * FIXME: The 1 is just here until we implement rpcrt4
496 * stub/proxy handling. Until then it helps IShield
499 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
501 /* register interface<->typelib coupling */
502 StringFromGUID2(&tattr->guid, guid, 80);
503 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
504 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
505 HeapFree(GetProcessHeap(), 0, guidA);
507 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
508 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
510 RegSetValueExW(key, NULL, 0, REG_SZ,
511 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
513 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
514 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
515 RegSetValueExA(subKey, NULL, 0, REG_SZ,
519 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
520 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
521 RegSetValueExA(subKey, NULL, 0, REG_SZ,
526 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
527 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
529 StringFromGUID2(&attr->guid, guid, 80);
530 snprintf(ver, sizeof(ver), "%x.%x",
531 attr->wMajorVerNum, attr->wMinorVerNum);
532 RegSetValueExW(subKey, NULL, 0, REG_SZ,
533 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
534 RegSetValueExA(subKey, "Version", 0, REG_SZ,
541 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
543 ITypeInfo_Release(tinfo);
550 ITypeLib_ReleaseTLibAttr(ptlib, attr);
556 /******************************************************************************
557 * UnRegisterTypeLib [OLEAUT32.186]
558 * Removes information about a type library from the System Registry
565 HRESULT WINAPI UnRegisterTypeLib(
566 REFGUID libid, /* [in] Guid of the library */
567 WORD wVerMajor, /* [in] major version */
568 WORD wVerMinor, /* [in] minor version */
569 LCID lcid, /* [in] locale id */
572 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
573 return S_OK; /* FIXME: pretend everything is OK */
576 /* for better debugging info leave the static out for the time being */
579 /*======================= ITypeLib implementation =======================*/
581 typedef struct tagTLBCustData
585 struct tagTLBCustData* next;
588 /* data structure for import typelibs */
589 typedef struct tagTLBImpLib
591 int offset; /* offset in the file (MSFT)
592 offset in nametable (SLTG)
593 just used to identify library while reading
595 GUID guid; /* libid */
596 BSTR name; /* name */
598 LCID lcid; /* lcid of imported typelib */
600 WORD wVersionMajor; /* major version number */
601 WORD wVersionMinor; /* minor version number */
603 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
604 NULL if not yet loaded */
605 struct tagTLBImpLib * next;
608 /* internal ITypeLib data */
609 typedef struct tagITypeLibImpl
611 ICOM_VFIELD(ITypeLib2);
613 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
615 /* strings can be stored in tlb as multibyte strings BUT they are *always*
616 * exported to the application as a UNICODE string.
622 unsigned long dwHelpContext;
623 int TypeInfoCount; /* nr of typeinfo's in librarry */
624 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
625 int ctCustData; /* number of items in cust data list */
626 TLBCustData * pCustData; /* linked list to cust data */
627 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
628 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
629 libary. Only used while read MSFT
633 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
635 /* ITypeLib methods */
636 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
637 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
639 /*======================= ITypeInfo implementation =======================*/
641 /* data for refernced types */
642 typedef struct tagTLBRefType
644 INT index; /* Type index for internal ref or for external ref
645 it the format is SLTG. -2 indicates to
648 GUID guid; /* guid of the referenced type */
649 /* if index == TLB_REF_USE_GUID */
651 HREFTYPE reference; /* The href of this ref */
652 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
653 TLB_REF_INTERNAL for internal refs
654 TLB_REF_NOT_FOUND for broken refs */
656 struct tagTLBRefType * next;
659 #define TLB_REF_USE_GUID -2
661 #define TLB_REF_INTERNAL (void*)-2
662 #define TLB_REF_NOT_FOUND (void*)-1
664 /* internal Parameter data */
665 typedef struct tagTLBParDesc
669 TLBCustData * pCustData; /* linked list to cust data */
672 /* internal Function data */
673 typedef struct tagTLBFuncDesc
675 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
676 BSTR Name; /* the name of this function */
677 TLBParDesc *pParamDesc; /* array with param names and custom data */
679 int HelpStringContext;
681 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
683 TLBCustData * pCustData; /* linked list to cust data; */
684 struct tagTLBFuncDesc * next;
687 /* internal Variable data */
688 typedef struct tagTLBVarDesc
690 VARDESC vardesc; /* lots of info on the variable and its attributes. */
691 BSTR Name; /* the name of this variable */
693 int HelpStringContext; /* FIXME: where? */
696 TLBCustData * pCustData;/* linked list to cust data; */
697 struct tagTLBVarDesc * next;
700 /* internal implemented interface data */
701 typedef struct tagTLBImplType
703 HREFTYPE hRef; /* hRef of interface */
704 int implflags; /* IMPLFLAG_*s */
706 TLBCustData * pCustData;/* linked list to custom data; */
707 struct tagTLBImplType *next;
710 /* internal TypeInfo data */
711 typedef struct tagITypeInfoImpl
713 ICOM_VFIELD(ITypeInfo2);
715 TYPEATTR TypeAttr ; /* _lots_ of type information. */
716 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
717 int index; /* index in this typelib; */
718 /* type libs seem to store the doc strings in ascii
719 * so why should we do it in unicode?
723 unsigned long dwHelpContext;
724 unsigned long dwHelpStringContext;
727 TLBFuncDesc * funclist; /* linked list with function descriptions */
730 TLBVarDesc * varlist; /* linked list with variable descriptions */
732 /* Implemented Interfaces */
733 TLBImplType * impltypelist;
735 TLBRefType * reflist;
737 TLBCustData * pCustData; /* linked list to cust data; */
738 struct tagITypeInfoImpl * next;
741 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
743 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
745 typedef struct tagTLBContext
747 unsigned int oStart; /* start of TLB in file */
748 unsigned int pos; /* current pos */
749 unsigned int length; /* total length */
750 void *mapping; /* memory mapping */
751 MSFT_SegDir * pTblDir;
752 ITypeLibImpl* pLibInfo;
756 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
761 static void dump_VarType(VARTYPE vt,char *szVarType) {
762 /* FIXME : we could have better trace here, depending on the VARTYPE
765 if (vt & VT_RESERVED)
766 szVarType += strlen(strcpy(szVarType, "reserved | "));
768 szVarType += strlen(strcpy(szVarType, "ref to "));
770 szVarType += strlen(strcpy(szVarType, "array of "));
772 szVarType += strlen(strcpy(szVarType, "vector of "));
773 switch(vt & VT_TYPEMASK) {
774 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
775 case VT_I2: sprintf(szVarType, "VT_I2"); break;
776 case VT_I4: sprintf(szVarType, "VT_I4"); break;
777 case VT_R4: sprintf(szVarType, "VT_R4"); break;
778 case VT_R8: sprintf(szVarType, "VT_R8"); break;
779 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
780 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
781 case VT_CY: sprintf(szVarType, "VT_CY"); break;
782 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
783 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
784 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
785 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
786 case VT_I1: sprintf(szVarType, "VT_I1"); break;
787 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
788 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
789 case VT_INT: sprintf(szVarType, "VT_INT"); break;
790 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
791 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
792 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
793 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
794 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
798 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
799 if (pTD->vt & VT_RESERVED)
800 szVarType += strlen(strcpy(szVarType, "reserved | "));
801 if (pTD->vt & VT_BYREF)
802 szVarType += strlen(strcpy(szVarType, "ref to "));
803 if (pTD->vt & VT_ARRAY)
804 szVarType += strlen(strcpy(szVarType, "array of "));
805 if (pTD->vt & VT_VECTOR)
806 szVarType += strlen(strcpy(szVarType, "vector of "));
807 switch(pTD->vt & VT_TYPEMASK) {
808 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
809 case VT_I2: sprintf(szVarType, "VT_I2"); break;
810 case VT_I4: sprintf(szVarType, "VT_I4"); break;
811 case VT_R4: sprintf(szVarType, "VT_R4"); break;
812 case VT_R8: sprintf(szVarType, "VT_R8"); break;
813 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
814 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
815 case VT_CY: sprintf(szVarType, "VT_CY"); break;
816 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
817 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
818 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
819 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
820 case VT_I1: sprintf(szVarType, "VT_I1"); break;
821 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
822 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
823 case VT_INT: sprintf(szVarType, "VT_INT"); break;
824 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
825 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
826 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
827 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
828 pTD->u.hreftype); break;
829 case VT_PTR: sprintf(szVarType, "ptr to ");
830 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
832 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
833 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
835 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
836 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
837 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
840 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
844 void dump_ELEMDESC(ELEMDESC *edesc) {
846 dump_TypeDesc(&edesc->tdesc,buf);
847 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
848 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
849 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
851 void dump_FUNCDESC(FUNCDESC *funcdesc) {
853 MESSAGE("memid is %08lx\n",funcdesc->memid);
854 for (i=0;i<funcdesc->cParams;i++) {
855 MESSAGE("Param %d:\n",i);
856 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
858 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
859 switch (funcdesc->funckind) {
860 case FUNC_VIRTUAL: MESSAGE("virtual");break;
861 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
862 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
863 case FUNC_STATIC: MESSAGE("static");break;
864 case FUNC_DISPATCH: MESSAGE("dispatch");break;
865 default: MESSAGE("unknown");break;
867 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
868 switch (funcdesc->invkind) {
869 case INVOKE_FUNC: MESSAGE("func");break;
870 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
871 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
872 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
874 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
875 switch (funcdesc->callconv) {
876 case CC_CDECL: MESSAGE("cdecl");break;
877 case CC_PASCAL: MESSAGE("pascal");break;
878 case CC_STDCALL: MESSAGE("stdcall");break;
879 case CC_SYSCALL: MESSAGE("syscall");break;
882 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
883 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
884 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
887 void dump_IDLDESC(IDLDESC *idl) {
888 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
891 static char * typekind_desc[] =
904 void dump_TYPEATTR(TYPEATTR *tattr) {
906 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
907 MESSAGE("\tlcid: %ld\n",tattr->lcid);
908 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
909 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
910 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
911 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
912 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
913 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
914 MESSAGE("\tcVars: %d\n", tattr->cVars);
915 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
916 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
917 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
918 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
919 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
920 dump_TypeDesc(&tattr->tdescAlias,buf);
921 MESSAGE("\ttypedesc: %s\n", buf);
922 dump_IDLDESC(&tattr->idldescType);
925 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
928 if (!TRACE_ON(typelib))
930 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
931 for (i=0;i<pfd->funcdesc.cParams;i++)
932 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
935 dump_FUNCDESC(&(pfd->funcdesc));
937 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
938 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
940 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
944 dump_TLBFuncDescOne(pfd);
948 static void dump_TLBVarDesc(TLBVarDesc * pvd)
952 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
957 static void dump_TLBImpLib(TLBImpLib *import)
959 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
960 debugstr_w(import->name));
961 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
962 import->wVersionMinor, import->lcid, import->offset);
965 static void dump_TLBRefType(TLBRefType * prt)
969 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
971 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
973 TRACE_(typelib)("type no: %d\n", prt->index);
975 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
976 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
977 TRACE_(typelib)("in lib\n");
978 dump_TLBImpLib(prt->pImpTLInfo);
984 static void dump_TLBImplType(TLBImplType * impl)
988 "implementing/inheriting interface hRef = %lx implflags %x\n",
989 impl->hRef, impl->implflags);
994 void dump_Variant(VARIANT * pvar)
999 TRACE("(%p)\n", pvar);
1003 ZeroMemory(szVarType, sizeof(szVarType));
1005 /* FIXME : we could have better trace here, depending on the VARTYPE
1008 dump_VarType(V_VT(pvar),szVarType);
1010 TRACE("VARTYPE: %s\n", szVarType);
1012 if (V_VT(pvar) & VT_BYREF) {
1013 ref = V_UNION(pvar, byref);
1016 else ref = &V_UNION(pvar, cVal);
1018 if (V_VT(pvar) & VT_ARRAY) {
1022 if (V_VT(pvar) & VT_VECTOR) {
1027 switch (V_VT(pvar) & VT_TYPEMASK)
1030 TRACE("%d\n", *(short*)ref);
1034 TRACE("%d\n", *(INT*)ref);
1038 TRACE("%3.3e\n", *(float*)ref);
1042 TRACE("%3.3e\n", *(double*)ref);
1046 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1050 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1055 TRACE("%p\n", *(LPVOID*)ref);
1059 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1065 memset( &TM, 0, sizeof(TM) );
1067 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1068 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1070 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1071 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1072 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1078 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1083 TRACE("(?)%ld\n", *(long*)ref);
1088 static void dump_DispParms(DISPPARAMS * pdp)
1092 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1094 while (index < pdp->cArgs)
1096 dump_Variant( &pdp->rgvarg[index] );
1101 static void dump_TypeInfo(ITypeInfoImpl * pty)
1103 TRACE("%p ref=%u\n", pty, pty->ref);
1104 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1105 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1106 TRACE("fct:%u var:%u impl:%u\n",
1107 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1108 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1109 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1110 dump_TLBFuncDesc(pty->funclist);
1111 dump_TLBVarDesc(pty->varlist);
1112 dump_TLBImplType(pty->impltypelist);
1115 void dump_VARDESC(VARDESC *v)
1117 MESSAGE("memid %ld\n",v->memid);
1118 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1119 MESSAGE("oInst %ld\n",v->u.oInst);
1120 dump_ELEMDESC(&(v->elemdescVar));
1121 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1122 MESSAGE("varkind %d\n",v->varkind);
1125 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1127 /* VT_LPWSTR is largest type that */
1128 /* may appear in type description*/
1129 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1130 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1131 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1132 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1133 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1134 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1138 static void TLB_abort()
1142 static void * TLB_Alloc(unsigned size)
1145 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1147 ERR("cannot allocate memory\n");
1152 static void TLB_Free(void * ptr)
1154 HeapFree(GetProcessHeap(), 0, ptr);
1158 /**********************************************************************
1160 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1163 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1165 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1166 pcx->pos, count, pcx->oStart, pcx->length, where);
1168 if (where != DO_NOT_SEEK)
1170 where += pcx->oStart;
1171 if (where > pcx->length)
1174 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1179 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1180 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1185 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1190 ret = MSFT_Read(buffer, count, pcx, where);
1191 FromLEDWords(buffer, ret);
1196 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1201 ret = MSFT_Read(buffer, count, pcx, where);
1202 FromLEWords(buffer, ret);
1207 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1209 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1210 memset(pGuid,0, sizeof(GUID));
1213 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1214 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1215 pGuid->Data2 = FromLEWord(pGuid->Data2);
1216 pGuid->Data3 = FromLEWord(pGuid->Data3);
1217 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1220 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1223 MSFT_NameIntro niName;
1225 WCHAR* pwstring = NULL;
1226 BSTR bstrName = NULL;
1228 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1229 pcx->pTblDir->pNametab.offset+offset);
1230 niName.namelen &= 0xFF; /* FIXME: correct ? */
1231 name=TLB_Alloc((niName.namelen & 0xff) +1);
1232 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1233 name[niName.namelen & 0xff]='\0';
1235 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1238 /* no invalid characters in string */
1241 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1243 /* don't check for invalid character since this has been done previously */
1244 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1246 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1247 lengthInChars = SysStringLen(bstrName);
1248 HeapFree(GetProcessHeap(), 0, pwstring);
1251 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1255 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1262 if(offset<0) return NULL;
1263 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1264 if(length <= 0) return 0;
1265 string=TLB_Alloc(length +1);
1266 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1267 string[length]='\0';
1269 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1270 string, -1, NULL, 0);
1272 /* no invalid characters in string */
1275 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1277 /* don't check for invalid character since this has been done previously */
1278 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1280 bstr = SysAllocStringLen(pwstring, lengthInChars);
1281 lengthInChars = SysStringLen(bstr);
1282 HeapFree(GetProcessHeap(), 0, pwstring);
1285 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1289 * read a value and fill a VARIANT structure
1291 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1295 TRACE_(typelib)("\n");
1297 if(offset <0) { /* data are packed in here */
1298 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1299 V_UNION(pVar, iVal) = offset & 0xffff;
1302 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1303 pcx->pTblDir->pCustData.offset + offset );
1304 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1305 switch (V_VT(pVar)){
1306 case VT_EMPTY: /* FIXME: is this right? */
1307 case VT_NULL: /* FIXME: is this right? */
1308 case VT_I2 : /* this should not happen */
1319 case VT_VOID : /* FIXME: is this right? */
1327 case VT_DECIMAL : /* FIXME: is this right? */
1330 /* pointer types with known behaviour */
1333 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1335 FIXME("BSTR length = %d?\n", size);
1337 ptr=TLB_Alloc(size);/* allocate temp buffer */
1338 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1339 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1340 /* FIXME: do we need a AtoW conversion here? */
1341 V_UNION(pVar, bstrVal[size])=L'\0';
1342 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1347 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1354 case VT_USERDEFINED :
1360 case VT_STREAMED_OBJECT :
1361 case VT_STORED_OBJECT :
1362 case VT_BLOB_OBJECT :
1367 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1371 if(size>0) /* (big|small) endian correct? */
1372 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1376 * create a linked list with custom data
1378 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1384 TRACE_(typelib)("\n");
1388 pNew=TLB_Alloc(sizeof(TLBCustData));
1389 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1390 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1391 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1392 /* add new custom data at head of the list */
1393 pNew->next=*ppCustData;
1395 offset = entry.next;
1400 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1404 pTd->vt=type & VT_TYPEMASK;
1406 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1408 if(pTd->vt == VT_USERDEFINED)
1409 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1411 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1415 MSFT_DoFuncs(TLBContext* pcx,
1420 TLBFuncDesc** pptfd)
1423 * member information is stored in a data structure at offset
1424 * indicated by the memoffset field of the typeinfo structure
1425 * There are several distinctive parts.
1426 * the first part starts with a field that holds the total length
1427 * of this (first) part excluding this field. Then follow the records,
1428 * for each member there is one record.
1430 * First entry is always the length of the record (excluding this
1432 * Rest of the record depends on the type of the member. If there is
1433 * a field indicating the member type (function variable intereface etc)
1434 * I have not found it yet. At this time we depend on the information
1435 * in the type info and the usual order how things are stored.
1437 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1440 * Third is a equal sized array with file offsets to the name entry
1443 * Forth and last (?) part is an array with offsets to the records in the
1444 * first part of this file segment.
1447 int infolen, nameoffset, reclength, nrattributes, i;
1448 int recoffset = offset + sizeof(INT);
1451 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1453 TRACE_(typelib)("\n");
1455 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1457 for ( i = 0; i < cFuncs ; i++ )
1459 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1461 /* name, eventually add to a hash table */
1462 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1463 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1465 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1467 /* read the function information record */
1468 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1472 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1474 /* do the attributes */
1475 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1478 if ( nrattributes > 0 )
1480 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1482 if ( nrattributes > 1 )
1484 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1485 pFuncRec->OptAttr[1]) ;
1487 if ( nrattributes > 2 )
1489 if ( pFuncRec->FKCCIC & 0x2000 )
1491 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1495 (*pptfd)->Entry = MSFT_ReadString(pcx,
1496 pFuncRec->OptAttr[2]);
1498 if( nrattributes > 5 )
1500 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1502 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1505 pFuncRec->OptAttr[6],
1506 &(*pptfd)->pCustData);
1513 /* fill the FuncDesc Structure */
1514 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1515 offset + infolen + ( i + 1) * sizeof(INT));
1517 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1518 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1519 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1520 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1521 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1522 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1523 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1527 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1530 /* do the parameters/arguments */
1531 if(pFuncRec->nrargs)
1534 MSFT_ParameterInfo paraminfo;
1536 (*pptfd)->funcdesc.lprgelemdescParam =
1537 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1539 (*pptfd)->pParamDesc =
1540 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1542 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1543 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1545 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1547 TYPEDESC* lpArgTypeDesc = 0;
1551 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1554 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1556 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1558 /* SEEK value = jump to offset,
1559 * from there jump to the end of record,
1560 * go back by (j-1) arguments
1562 MSFT_ReadLEDWords( ¶minfo ,
1563 sizeof(MSFT_ParameterInfo), pcx,
1564 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1565 * sizeof(MSFT_ParameterInfo)));
1567 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1569 while ( lpArgTypeDesc != NULL )
1571 switch ( lpArgTypeDesc->vt )
1574 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1578 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1581 case VT_USERDEFINED:
1582 MSFT_DoRefType(pcx, pTI,
1583 lpArgTypeDesc->u.hreftype);
1585 lpArgTypeDesc = NULL;
1589 lpArgTypeDesc = NULL;
1595 /* parameter is the return value! */
1596 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1598 TYPEDESC* lpArgTypeDesc;
1600 (*pptfd)->funcdesc.elemdescFunc =
1601 (*pptfd)->funcdesc.lprgelemdescParam[j];
1603 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1605 while ( lpArgTypeDesc != NULL )
1607 switch ( lpArgTypeDesc->vt )
1610 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1614 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1618 case VT_USERDEFINED:
1621 lpArgTypeDesc->u.hreftype);
1623 lpArgTypeDesc = NULL;
1627 lpArgTypeDesc = NULL;
1632 /* second time around */
1633 for(j=0;j<pFuncRec->nrargs;j++)
1636 (*pptfd)->pParamDesc[j].Name =
1637 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1640 if ( (PARAMFLAG_FHASDEFAULT &
1641 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1642 ((pFuncRec->FKCCIC) & 0x1000) )
1644 INT* pInt = (INT *)((char *)pFuncRec +
1646 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1648 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1650 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1651 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1653 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1657 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1660 pFuncRec->OptAttr[7+j],
1661 &(*pptfd)->pParamDesc[j].pCustData);
1666 /* scode is not used: archaic win16 stuff FIXME: right? */
1667 (*pptfd)->funcdesc.cScodes = 0 ;
1668 (*pptfd)->funcdesc.lprgscode = NULL ;
1670 pptfd = & ((*pptfd)->next);
1671 recoffset += reclength;
1674 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1675 int cVars, int offset, TLBVarDesc ** pptvd)
1677 int infolen, nameoffset, reclength;
1679 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1683 TRACE_(typelib)("\n");
1685 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1686 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1687 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1688 recoffset += offset+sizeof(INT);
1689 for(i=0;i<cVars;i++){
1690 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1691 /* name, eventually add to a hash table */
1692 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1693 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1694 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1695 /* read the variable information record */
1696 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1698 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1700 if(reclength >(6*sizeof(INT)) )
1701 (*pptvd)->HelpContext=pVarRec->HelpContext;
1702 if(reclength >(7*sizeof(INT)) )
1703 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1704 if(reclength >(8*sizeof(INT)) )
1705 if(reclength >(9*sizeof(INT)) )
1706 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1707 /* fill the VarDesc Structure */
1708 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1709 offset + infolen + ( i + 1) * sizeof(INT));
1710 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1711 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1712 MSFT_GetTdesc(pcx, pVarRec->DataType,
1713 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1714 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1715 if(pVarRec->VarKind == VAR_CONST ){
1716 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1717 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1718 pVarRec->OffsValue, pcx);
1720 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1721 pptvd=&((*pptvd)->next);
1722 recoffset += reclength;
1725 /* fill in data for a hreftype (offset). When the refernced type is contained
1726 * in the typelib, it's just an (file) offset in the type info base dir.
1727 * If comes from import, it's an offset+1 in the ImpInfo table
1729 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1733 TLBRefType **ppRefType = &pTI->reflist;
1735 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1738 if((*ppRefType)->reference == offset)
1740 ppRefType = &(*ppRefType)->next;
1743 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1744 sizeof(**ppRefType));
1746 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1747 /* external typelib */
1748 MSFT_ImpInfo impinfo;
1749 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1751 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1753 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1754 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1755 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1756 if(pImpLib->offset==impinfo.oImpFile) break;
1757 pImpLib=pImpLib->next;
1760 (*ppRefType)->reference=offset;
1761 (*ppRefType)->pImpTLInfo = pImpLib;
1762 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1763 (*ppRefType)->index = TLB_REF_USE_GUID;
1765 ERR("Cannot find a reference\n");
1766 (*ppRefType)->reference=-1;
1767 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1770 /* in this typelib */
1771 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1772 (*ppRefType)->reference=offset;
1773 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1777 /* process Implemented Interfaces of a com class */
1778 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1782 MSFT_RefRecord refrec;
1783 TLBImplType **ppImpl = &pTI->impltypelist;
1785 TRACE_(typelib)("\n");
1787 for(i=0;i<count;i++){
1788 if(offset<0) break; /* paranoia */
1789 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1790 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1791 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1792 (*ppImpl)->hRef = refrec.reftype;
1793 (*ppImpl)->implflags=refrec.flags;
1794 (*ppImpl)->ctCustData=
1795 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1796 offset=refrec.onext;
1797 ppImpl=&((*ppImpl)->next);
1801 * process a typeinfo record
1803 ITypeInfoImpl * MSFT_DoTypeInfo(
1806 ITypeLibImpl * pLibInfo)
1808 MSFT_TypeInfoBase tiBase;
1809 ITypeInfoImpl *ptiRet;
1811 TRACE_(typelib)("count=%u\n", count);
1813 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1814 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1815 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1816 /* this is where we are coming from */
1817 ptiRet->pTypeLib = pLibInfo;
1818 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1819 ptiRet->index=count;
1820 /* fill in the typeattr fields */
1821 FIXME("Assign constructor/destructor memid\n");
1823 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1824 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1825 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1826 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1827 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1828 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1829 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1830 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1831 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1832 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1833 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1834 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1835 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1836 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1837 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1838 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1839 MSFT_GetTdesc(pcx, tiBase.datatype1,
1840 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1843 /* IDLDESC idldescType; *//* never saw this one != zero */
1845 /* name, eventually add to a hash table */
1846 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1847 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1849 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1850 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1851 ptiRet->dwHelpContext=tiBase.helpcontext;
1852 /* note: InfoType's Help file and HelpStringDll come from the containing
1853 * library. Further HelpString and Docstring appear to be the same thing :(
1856 if(ptiRet->TypeAttr.cFuncs >0 )
1857 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1858 ptiRet->TypeAttr.cVars,
1859 tiBase.memoffset, & ptiRet->funclist);
1861 if(ptiRet->TypeAttr.cVars >0 )
1862 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1863 ptiRet->TypeAttr.cVars,
1864 tiBase.memoffset, & ptiRet->varlist);
1865 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1866 switch(ptiRet->TypeAttr.typekind)
1869 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1872 case TKIND_DISPATCH:
1873 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1875 if (tiBase.datatype1 != -1)
1877 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1878 ptiRet->impltypelist->hRef = tiBase.datatype1;
1881 { /* FIXME: This is a really bad hack to add IDispatch */
1882 char* szStdOle = "stdole2.tlb\0";
1883 int nStdOleLen = strlen(szStdOle);
1884 TLBRefType **ppRef = &ptiRet->reflist;
1887 if((*ppRef)->reference == -1)
1889 ppRef = &(*ppRef)->next;
1892 *ppRef = TLB_Alloc(sizeof(**ppRef));
1893 (*ppRef)->guid = IID_IDispatch;
1894 (*ppRef)->reference = -1;
1895 (*ppRef)->index = TLB_REF_USE_GUID;
1896 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1897 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1898 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1901 MultiByteToWideChar(CP_ACP,
1905 (*ppRef)->pImpTLInfo->name,
1906 SysStringLen((*ppRef)->pImpTLInfo->name));
1908 (*ppRef)->pImpTLInfo->lcid = 0;
1909 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1910 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1915 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1916 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1917 ptiRet->impltypelist->hRef = tiBase.datatype1;
1922 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1924 TRACE_(typelib)("%s guid: %s kind:%s\n",
1925 debugstr_w(ptiRet->Name),
1926 debugstr_guid(&ptiRet->TypeAttr.guid),
1927 typekind_desc[ptiRet->TypeAttr.typekind]);
1932 /****************************************************************************
1935 * find the type of the typelib file and map the typelib resource into
1938 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1939 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1940 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1942 int ret = TYPE_E_CANTLOADLIBRARY;
1943 DWORD dwSignature = 0;
1946 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1950 /* check the signature of the file */
1951 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1952 if (INVALID_HANDLE_VALUE != hFile)
1954 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1957 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1960 /* retrieve file size */
1961 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1963 /* first try to load as *.tlb */
1964 dwSignature = FromLEDWord(*((DWORD*) pBase));
1965 if ( dwSignature == MSFT_SIGNATURE)
1967 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1969 else if ( dwSignature == SLTG_SIGNATURE)
1971 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1973 UnmapViewOfFile(pBase);
1975 CloseHandle(hMapping);
1980 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1982 /* find the typelibrary resource*/
1983 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1984 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1987 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1991 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1994 LPVOID pBase = LockResource(hGlobal);
1995 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1999 /* try to load as incore resource */
2000 dwSignature = FromLEDWord(*((DWORD*) pBase));
2001 if ( dwSignature == MSFT_SIGNATURE)
2003 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2005 else if ( dwSignature == SLTG_SIGNATURE)
2007 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2011 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2014 FreeResource( hGlobal );
2017 FreeLibrary(hinstDLL);
2024 ERR("Loading of typelib %s failed with error %ld\n",
2025 debugstr_w(pszFileName), GetLastError());
2030 /*================== ITypeLib(2) Methods ===================================*/
2032 /****************************************************************************
2033 * ITypeLib2_Constructor_MSFT
2035 * loading an MSFT typelib from an in-memory image
2037 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2041 MSFT_Header tlbHeader;
2042 MSFT_SegDir tlbSegDir;
2043 ITypeLibImpl * pTypeLibImpl;
2045 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2047 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2048 if (!pTypeLibImpl) return NULL;
2050 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2051 pTypeLibImpl->ref = 1;
2053 /* get pointer to beginning of typelib data */
2057 cx.pLibInfo = pTypeLibImpl;
2058 cx.length = dwTLBLength;
2061 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2063 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2064 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2065 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2068 /* there is a small amount of information here until the next important
2070 * the segment directory . Try to calculate the amount of data */
2071 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2073 /* now read the segment directory */
2074 TRACE("read segment directory (at %ld)\n",lPSegDir);
2075 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2076 cx.pTblDir = &tlbSegDir;
2078 /* just check two entries */
2079 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2081 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2082 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2086 /* now fill our internal data */
2087 /* TLIBATTR fields */
2088 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2090 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2091 /* Windows seems to have zero here, is this correct? */
2092 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2093 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2095 pTypeLibImpl->LibAttr.lcid = 0;
2097 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2098 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2099 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2100 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2102 /* name, eventually add to a hash table */
2103 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2106 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2107 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2109 if( tlbHeader.varflags & HELPDLLFLAG)
2112 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2113 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2116 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2119 if(tlbHeader.CustomDataOffset >= 0)
2121 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2124 /* fill in typedescriptions */
2125 if(tlbSegDir.pTypdescTab.length > 0)
2127 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2129 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2130 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2133 /* FIXME: add several sanity checks here */
2134 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2135 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2137 /* FIXME: check safearray */
2139 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2141 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2143 else if(td[0] == VT_CARRAY)
2145 /* array descr table here */
2146 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2148 else if(td[0] == VT_USERDEFINED)
2150 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2152 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2155 /* second time around to fill the array subscript info */
2158 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2159 if(tlbSegDir.pArrayDescriptions.offset>0)
2161 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2162 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2165 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2167 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2169 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2171 for(j = 0; j<td[2]; j++)
2173 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2174 sizeof(INT), &cx, DO_NOT_SEEK);
2175 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2176 sizeof(INT), &cx, DO_NOT_SEEK);
2181 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2182 ERR("didn't find array description data\n");
2187 /* imported type libs */
2188 if(tlbSegDir.pImpFiles.offset>0)
2190 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2191 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2194 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2196 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2197 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2198 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2200 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2201 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2202 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2203 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2206 (*ppImpLib)->name = TLB_Alloc(size+1);
2207 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2208 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2209 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2211 ppImpLib = &(*ppImpLib)->next;
2216 if(tlbHeader.nrtypeinfos >= 0 )
2218 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2219 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2222 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2224 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2226 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2227 ppTI = &((*ppTI)->next);
2228 (pTypeLibImpl->TypeInfoCount)++;
2232 TRACE("(%p)\n", pTypeLibImpl);
2233 return (ITypeLib2*) pTypeLibImpl;
2237 static BSTR TLB_MultiByteToBSTR(char *ptr)
2243 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2244 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2245 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2246 ret = SysAllocString(nameW);
2247 HeapFree(GetProcessHeap(), 0, nameW);
2251 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2257 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2258 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2262 guid->Data4[0] = s >> 8;
2263 guid->Data4[1] = s & 0xff;
2266 for(i = 0; i < 6; i++) {
2267 memcpy(b, str + 24 + 2 * i, 2);
2268 guid->Data4[i + 2] = strtol(b, NULL, 16);
2273 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2280 bytelen = *(WORD*)ptr;
2281 if(bytelen == 0xffff) return 2;
2282 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2283 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2284 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2285 *pBstr = SysAllocStringLen(nameW, len);
2286 HeapFree(GetProcessHeap(), 0, nameW);
2290 static WORD SLTG_ReadStringA(char *ptr, char **str)
2295 bytelen = *(WORD*)ptr;
2296 if(bytelen == 0xffff) return 2;
2297 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2298 memcpy(*str, ptr + 2, bytelen);
2299 (*str)[bytelen] = '\0';
2303 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2305 char *ptr = pLibBlk;
2308 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2309 FIXME("libblk magic = %04x\n", w);
2314 if((w = *(WORD*)ptr) != 0xffff) {
2315 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2320 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2322 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2324 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2327 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2330 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2333 ptr += 4; /* skip res12 */
2335 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2338 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2341 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2344 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2345 ptr += sizeof(GUID);
2347 return ptr - (char*)pLibBlk;
2350 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2353 TYPEDESC *pTD = &pElem->tdesc;
2355 /* Handle [in/out] first */
2356 if((*pType & 0xc000) == 0xc000)
2357 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2358 else if(*pType & 0x8000)
2359 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2360 else if(*pType & 0x4000)
2361 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2363 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2366 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2369 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2372 if((*pType & 0xe00) == 0xe00) {
2374 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2376 pTD = pTD->u.lptdesc;
2378 switch(*pType & 0x7f) {
2381 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2383 pTD = pTD->u.lptdesc;
2386 case VT_USERDEFINED:
2387 pTD->vt = VT_USERDEFINED;
2388 pTD->u.hreftype = *(++pType) / 4;
2394 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2397 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2399 pTD->vt = VT_CARRAY;
2400 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2402 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2403 pTD->u.lpadesc->cDims = pSA->cDims;
2404 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2405 pSA->cDims * sizeof(SAFEARRAYBOUND));
2407 pTD = &pTD->u.lpadesc->tdescElem;
2413 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2417 pTD->vt = VT_SAFEARRAY;
2418 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2420 pTD = pTD->u.lptdesc;
2424 pTD->vt = *pType & 0x7f;
2434 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2439 TLBRefType **ppRefType;
2441 if(pRef->magic != SLTG_REF_MAGIC) {
2442 FIXME("Ref magic = %x\n", pRef->magic);
2445 name = ( (char*)(&pRef->names) + pRef->number);
2447 ppRefType = &pTI->reflist;
2448 for(ref = 0; ref < pRef->number >> 3; ref++) {
2450 unsigned int lib_offs, type_num;
2452 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2453 sizeof(**ppRefType));
2455 name += SLTG_ReadStringA(name, &refname);
2456 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2457 FIXME("Can't sscanf ref\n");
2458 if(lib_offs != 0xffff) {
2459 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2462 if((*import)->offset == lib_offs)
2464 import = &(*import)->next;
2467 char fname[MAX_PATH+1];
2470 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2472 (*import)->offset = lib_offs;
2473 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2475 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2476 &(*import)->wVersionMajor,
2477 &(*import)->wVersionMinor,
2478 &(*import)->lcid, fname) != 4) {
2479 FIXME("can't sscanf ref %s\n",
2480 pNameTable + lib_offs + 40);
2482 len = strlen(fname);
2483 if(fname[len-1] != '#')
2484 FIXME("fname = %s\n", fname);
2485 fname[len-1] = '\0';
2486 (*import)->name = TLB_MultiByteToBSTR(fname);
2488 (*ppRefType)->pImpTLInfo = *import;
2489 } else { /* internal ref */
2490 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2492 (*ppRefType)->reference = ref;
2493 (*ppRefType)->index = type_num;
2495 HeapFree(GetProcessHeap(), 0, refname);
2496 ppRefType = &(*ppRefType)->next;
2498 if((BYTE)*name != SLTG_REF_MAGIC)
2499 FIXME("End of ref block magic = %x\n", *name);
2500 dump_TLBRefType(pTI->reflist);
2503 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2506 SLTG_ImplInfo *info;
2507 TLBImplType **ppImplType = &pTI->impltypelist;
2508 /* I don't really get this structure, usually it's 0x16 bytes
2509 long, but iuser.tlb contains some that are 0x18 bytes long.
2510 That's ok because we can use the next ptr to jump to the next
2511 one. But how do we know the length of the last one? The WORD
2512 at offs 0x8 might be the clue. For now I'm just assuming that
2513 the last one is the regular 0x16 bytes. */
2515 info = (SLTG_ImplInfo*)pBlk;
2517 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2518 sizeof(**ppImplType));
2519 (*ppImplType)->hRef = info->ref;
2520 (*ppImplType)->implflags = info->impltypeflags;
2521 pTI->TypeAttr.cImplTypes++;
2522 ppImplType = &(*ppImplType)->next;
2524 if(info->next == 0xffff)
2527 FIXME("Interface inheriting more than one interface\n");
2528 info = (SLTG_ImplInfo*)(pBlk + info->next);
2530 info++; /* see comment at top of function */
2534 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2537 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2538 SLTG_MemberHeader *pMemHeader;
2539 char *pFirstItem, *pNextItem;
2541 if(pTIHeader->href_table != 0xffffffff) {
2542 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2547 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2549 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2551 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2552 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2555 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2559 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2562 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2563 SLTG_MemberHeader *pMemHeader;
2564 SLTG_Function *pFunc;
2565 char *pFirstItem, *pNextItem;
2566 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2569 if(pTIHeader->href_table != 0xffffffff) {
2570 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2574 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2576 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2578 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2579 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2582 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2583 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2588 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2589 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2590 FIXME("func magic = %02x\n", pFunc->magic);
2593 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2594 sizeof(**ppFuncDesc));
2595 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2597 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2598 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2599 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2600 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2601 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2602 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2604 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2605 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2607 if(pFunc->retnextopt & 0x80)
2608 pType = &pFunc->rettype;
2610 pType = (WORD*)(pFirstItem + pFunc->rettype);
2613 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2615 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2616 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2617 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2618 (*ppFuncDesc)->pParamDesc =
2619 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2620 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2622 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2624 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2625 char *paramName = pNameTable + *pArg;
2627 /* If arg type follows then paramName points to the 2nd
2628 letter of the name, else the next WORD is an offset to
2629 the arg type and paramName points to the first letter.
2630 So let's take one char off paramName and see if we're
2631 pointing at an alpha-numeric char. However if *pArg is
2632 0xffff or 0xfffe then the param has no name, the former
2633 meaning that the next WORD is the type, the latter
2634 meaning the the next WORD is an offset to the type. */
2639 else if(*pArg == 0xfffe) {
2643 else if(!isalnum(*(paramName-1)))
2648 if(HaveOffs) { /* the next word is an offset to type */
2649 pType = (WORD*)(pFirstItem + *pArg);
2650 SLTG_DoType(pType, pFirstItem,
2651 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2656 pArg = SLTG_DoType(pArg, pFirstItem,
2657 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2660 /* Are we an optional param ? */
2661 if((*ppFuncDesc)->funcdesc.cParams - param <=
2662 (*ppFuncDesc)->funcdesc.cParamsOpt)
2663 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2666 (*ppFuncDesc)->pParamDesc[param].Name =
2667 TLB_MultiByteToBSTR(paramName);
2671 ppFuncDesc = &((*ppFuncDesc)->next);
2672 if(pFunc->next == 0xffff) break;
2674 pTI->TypeAttr.cFuncs = num;
2675 dump_TLBFuncDesc(pTI->funclist);
2676 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2679 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2682 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2683 SLTG_MemberHeader *pMemHeader;
2684 SLTG_RecordItem *pItem;
2686 TLBVarDesc **ppVarDesc = &pTI->varlist;
2691 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2693 pFirstItem = (char*)(pMemHeader + 1);
2694 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2695 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2696 if(pItem->magic != SLTG_RECORD_MAGIC) {
2697 FIXME("record magic = %02x\n", pItem->magic);
2700 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2701 sizeof(**ppVarDesc));
2702 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2703 (*ppVarDesc)->vardesc.memid = pItem->memid;
2704 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2705 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2707 if(pItem->typepos == 0x02)
2708 pType = &pItem->type;
2709 else if(pItem->typepos == 0x00)
2710 pType = (WORD*)(pFirstItem + pItem->type);
2712 FIXME("typepos = %02x\n", pItem->typepos);
2716 SLTG_DoType(pType, pFirstItem,
2717 &(*ppVarDesc)->vardesc.elemdescVar);
2719 /* FIXME("helpcontext, helpstring\n"); */
2721 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2723 ppVarDesc = &((*ppVarDesc)->next);
2724 if(pItem->next == 0xffff) break;
2726 pTI->TypeAttr.cVars = num;
2727 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2730 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2733 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2734 SLTG_MemberHeader *pMemHeader;
2735 SLTG_EnumItem *pItem;
2737 TLBVarDesc **ppVarDesc = &pTI->varlist;
2740 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2742 pFirstItem = (char*)(pMemHeader + 1);
2743 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2744 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2745 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2746 FIXME("enumitem magic = %04x\n", pItem->magic);
2749 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2750 sizeof(**ppVarDesc));
2751 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2752 (*ppVarDesc)->vardesc.memid = pItem->memid;
2753 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2755 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2756 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2757 *(INT*)(pItem->value + pFirstItem);
2758 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2759 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2760 /* FIXME("helpcontext, helpstring\n"); */
2762 ppVarDesc = &((*ppVarDesc)->next);
2763 if(pItem->next == 0xffff) break;
2765 pTI->TypeAttr.cVars = num;
2766 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2769 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2770 managable copy of it into this */
2783 } SLTG_InternalOtherTypeInfo;
2785 /****************************************************************************
2786 * ITypeLib2_Constructor_SLTG
2788 * loading a SLTG typelib from an in-memory image
2790 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2792 ITypeLibImpl *pTypeLibImpl;
2793 SLTG_Header *pHeader;
2794 SLTG_BlkEntry *pBlkEntry;
2798 LPVOID pBlk, pFirstBlk;
2799 SLTG_LibBlk *pLibBlk;
2800 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2801 char *pAfterOTIBlks = NULL;
2802 char *pNameTable, *ptr;
2805 ITypeInfoImpl **ppTypeInfoImpl;
2807 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2809 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2810 if (!pTypeLibImpl) return NULL;
2812 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2813 pTypeLibImpl->ref = 1;
2818 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2819 pHeader->nrOfFileBlks );
2820 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2821 FIXME("Header type magic 0x%08lx not supported.\n",
2822 pHeader->SLTG_magic);
2826 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2827 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2829 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2830 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2832 /* Next we have a magic block */
2833 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2835 /* Let's see if we're still in sync */
2836 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2837 sizeof(SLTG_COMPOBJ_MAGIC))) {
2838 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2841 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2842 sizeof(SLTG_DIR_MAGIC))) {
2843 FIXME("dir magic = %s\n", pMagic->dir_magic);
2847 pIndex = (SLTG_Index*)(pMagic+1);
2849 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2851 pFirstBlk = (LPVOID)(pPad9 + 1);
2853 /* We'll set up a ptr to the main library block, which is the last one. */
2855 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2856 pBlkEntry[order].next != 0;
2857 order = pBlkEntry[order].next - 1, i++) {
2858 pBlk = (char*)pBlk + pBlkEntry[order].len;
2862 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2864 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2869 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2871 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2872 sizeof(*pOtherTypeInfoBlks) *
2873 pTypeLibImpl->TypeInfoCount);
2876 ptr = (char*)pLibBlk + len;
2878 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2882 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2884 w = *(WORD*)(ptr + 2);
2887 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2889 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2890 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2892 w = *(WORD*)(ptr + 4 + len);
2894 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2896 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2898 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2899 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2901 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2902 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2903 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2905 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2907 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2910 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2911 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2912 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2913 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2914 len += sizeof(SLTG_OtherTypeInfo);
2918 pAfterOTIBlks = ptr;
2920 /* Skip this WORD and get the next DWORD */
2921 len = *(DWORD*)(pAfterOTIBlks + 2);
2923 /* Now add this to pLibBLk look at what we're pointing at and
2924 possibly add 0x20, then add 0x216, sprinkle a bit a magic
2925 dust and we should be pointing at the beginning of the name
2928 pNameTable = (char*)pLibBlk + len;
2930 switch(*(WORD*)pNameTable) {
2937 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
2941 pNameTable += 0x216;
2945 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2947 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2950 /* Hopefully we now have enough ptrs set up to actually read in
2951 some TypeInfos. It's not clear which order to do them in, so
2952 I'll just follow the links along the BlkEntry chain and read
2953 them in in the order in which they're in the file */
2955 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2957 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2958 pBlkEntry[order].next != 0;
2959 order = pBlkEntry[order].next - 1, i++) {
2961 SLTG_TypeInfoHeader *pTIHeader;
2962 SLTG_TypeInfoTail *pTITail;
2964 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2965 pOtherTypeInfoBlks[i].index_name)) {
2966 FIXME("Index strings don't match\n");
2971 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2972 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2975 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2976 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2977 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
2978 (*ppTypeInfoImpl)->index = i;
2979 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2980 pOtherTypeInfoBlks[i].name_offs +
2982 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2983 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2985 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2986 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2987 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2988 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2989 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2991 if((pTIHeader->typeflags1 & 7) != 2)
2992 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2993 if(pTIHeader->typeflags3 != 2)
2994 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2996 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2997 debugstr_w((*ppTypeInfoImpl)->Name),
2998 typekind_desc[pTIHeader->typekind],
2999 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3000 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3002 switch(pTIHeader->typekind) {
3004 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3008 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3011 case TKIND_INTERFACE:
3012 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3016 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3020 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3026 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3027 but we've already set those */
3028 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3029 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3030 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3032 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3033 pBlk = (char*)pBlk + pBlkEntry[order].len;
3036 if(i != pTypeLibImpl->TypeInfoCount) {
3037 FIXME("Somehow processed %d TypeInfos\n", i);
3041 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3042 return (ITypeLib2*)pTypeLibImpl;
3045 /* ITypeLib::QueryInterface
3047 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3052 ICOM_THIS( ITypeLibImpl, iface);
3054 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3057 if(IsEqualIID(riid, &IID_IUnknown) ||
3058 IsEqualIID(riid,&IID_ITypeLib)||
3059 IsEqualIID(riid,&IID_ITypeLib2))
3066 ITypeLib2_AddRef(iface);
3067 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3070 TRACE("-- Interface: E_NOINTERFACE\n");
3071 return E_NOINTERFACE;
3076 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3078 ICOM_THIS( ITypeLibImpl, iface);
3080 TRACE("(%p)->ref is %u\n",This, This->ref);
3082 return ++(This->ref);
3085 /* ITypeLib::Release
3087 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3089 ICOM_THIS( ITypeLibImpl, iface);
3093 TRACE("(%p)->(%u)\n",This, This->ref);
3097 /* FIXME destroy child objects */
3099 TRACE(" destroying ITypeLib(%p)\n",This);
3103 SysFreeString(This->Name);
3107 if (This->DocString)
3109 SysFreeString(This->DocString);
3110 This->DocString = NULL;
3115 SysFreeString(This->HelpFile);
3116 This->HelpFile = NULL;
3119 if (This->HelpStringDll)
3121 SysFreeString(This->HelpStringDll);
3122 This->HelpStringDll = NULL;
3125 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3126 HeapFree(GetProcessHeap(),0,This);
3133 /* ITypeLib::GetTypeInfoCount
3135 * Returns the number of type descriptions in the type library
3137 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3139 ICOM_THIS( ITypeLibImpl, iface);
3140 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3141 return This->TypeInfoCount;
3144 /* ITypeLib::GetTypeInfo
3146 * retrieves the specified type description in the library.
3148 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3151 ITypeInfo **ppTInfo)
3155 ICOM_THIS( ITypeLibImpl, iface);
3156 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3158 TRACE("(%p)->(index=%d) \n", This, index);
3160 if (!ppTInfo) return E_INVALIDARG;
3162 /* search element n in list */
3163 for(i=0; i < index; i++)
3165 pTypeInfo = pTypeInfo->next;
3168 TRACE("-- element not found\n");
3169 return TYPE_E_ELEMENTNOTFOUND;
3173 *ppTInfo = (ITypeInfo *) pTypeInfo;
3175 ITypeInfo_AddRef(*ppTInfo);
3176 TRACE("-- found (%p)\n",*ppTInfo);
3181 /* ITypeLibs::GetTypeInfoType
3183 * Retrieves the type of a type description.
3185 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3190 ICOM_THIS( ITypeLibImpl, iface);
3192 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3194 TRACE("(%p) index %d \n",This, index);
3196 if(!pTKind) return E_INVALIDARG;
3198 /* search element n in list */
3199 for(i=0; i < index; i++)
3203 TRACE("-- element not found\n");
3204 return TYPE_E_ELEMENTNOTFOUND;
3206 pTInfo = pTInfo->next;
3209 *pTKind = pTInfo->TypeAttr.typekind;
3210 TRACE("-- found Type (%d)\n", *pTKind);
3214 /* ITypeLib::GetTypeInfoOfGuid
3216 * Retrieves the type description that corresponds to the specified GUID.
3219 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3222 ITypeInfo **ppTInfo)
3224 ICOM_THIS( ITypeLibImpl, iface);
3225 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3227 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3229 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3231 /* search linked list for guid */
3232 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3234 pTypeInfo = pTypeInfo->next;
3238 /* end of list reached */
3239 TRACE("-- element not found\n");
3240 return TYPE_E_ELEMENTNOTFOUND;
3244 TRACE("-- found (%p, %s)\n",
3246 debugstr_w(pTypeInfo->Name));
3248 *ppTInfo = (ITypeInfo*)pTypeInfo;
3249 ITypeInfo_AddRef(*ppTInfo);
3253 /* ITypeLib::GetLibAttr
3255 * Retrieves the structure that contains the library's attributes.
3258 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3260 LPTLIBATTR *ppTLibAttr)
3262 ICOM_THIS( ITypeLibImpl, iface);
3263 TRACE("(%p)\n",This);
3264 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3265 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3269 /* ITypeLib::GetTypeComp
3271 * Enables a client compiler to bind to a library's types, variables,
3272 * constants, and global functions.
3275 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3277 ITypeComp **ppTComp)
3279 ICOM_THIS( ITypeLibImpl, iface);
3280 FIXME("(%p): stub!\n",This);
3284 /* ITypeLib::GetDocumentation
3286 * Retrieves the library's documentation string, the complete Help file name
3287 * and path, and the context identifier for the library Help topic in the Help
3290 * On a successful return all non-null BSTR pointers will have been set,
3293 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3297 BSTR *pBstrDocString,
3298 DWORD *pdwHelpContext,
3299 BSTR *pBstrHelpFile)
3301 ICOM_THIS( ITypeLibImpl, iface);
3303 HRESULT result = E_INVALIDARG;
3308 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3310 pBstrName, pBstrDocString,
3311 pdwHelpContext, pBstrHelpFile);
3315 /* documentation for the typelib */
3319 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3325 if (This->DocString)
3326 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3327 else if (This->Name)
3328 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3330 *pBstrDocString = NULL;
3334 *pdwHelpContext = This->dwHelpContext;
3339 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3341 *pBstrHelpFile = NULL;
3348 /* for a typeinfo */
3349 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3351 if(SUCCEEDED(result))
3353 result = ITypeInfo_GetDocumentation(pTInfo,
3357 pdwHelpContext, pBstrHelpFile);
3359 ITypeInfo_Release(pTInfo);
3364 if (pBstrDocString) SysFreeString (*pBstrDocString);
3366 if (pBstrName) SysFreeString (*pBstrName);
3368 return STG_E_INSUFFICIENTMEMORY;
3373 * Indicates whether a passed-in string contains the name of a type or member
3374 * described in the library.
3377 static HRESULT WINAPI ITypeLib2_fnIsName(
3383 ICOM_THIS( ITypeLibImpl, iface);
3384 ITypeInfoImpl *pTInfo;
3385 TLBFuncDesc *pFInfo;
3388 UINT nNameBufLen = SysStringLen(szNameBuf);
3390 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3394 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3395 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3396 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3397 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3398 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3399 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3400 goto ITypeLib2_fnIsName_exit;
3402 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3403 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3408 ITypeLib2_fnIsName_exit:
3409 TRACE("(%p)slow! search for %s: %s found!\n", This,
3410 debugstr_w(szNameBuf), *pfName?"NOT":"");
3415 /* ITypeLib::FindName
3417 * Finds occurrences of a type description in a type library. This may be used
3418 * to quickly verify that a name exists in a type library.
3421 static HRESULT WINAPI ITypeLib2_fnFindName(
3425 ITypeInfo **ppTInfo,
3429 ICOM_THIS( ITypeLibImpl, iface);
3430 ITypeInfoImpl *pTInfo;
3431 TLBFuncDesc *pFInfo;
3435 UINT nNameBufLen = SysStringLen(szNameBuf);
3437 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3438 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3439 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3440 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3441 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3442 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3443 goto ITypeLib2_fnFindName_exit;
3445 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3446 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3448 ITypeLib2_fnFindName_exit:
3449 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3450 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3453 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3454 This, *pcFound, debugstr_w(szNameBuf), j);
3461 /* ITypeLib::ReleaseTLibAttr
3463 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3466 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3468 TLIBATTR *pTLibAttr)
3470 ICOM_THIS( ITypeLibImpl, iface);
3471 TRACE("freeing (%p)\n",This);
3472 HeapFree(GetProcessHeap(),0,pTLibAttr);
3476 /* ITypeLib2::GetCustData
3478 * gets the custom data
3480 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3485 ICOM_THIS( ITypeLibImpl, iface);
3486 TLBCustData *pCData;
3488 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3490 if( IsEqualIID(guid, &pCData->guid)) break;
3493 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3497 VariantInit( pVarVal);
3498 VariantCopy( pVarVal, &pCData->data);
3501 return E_INVALIDARG; /* FIXME: correct? */
3504 /* ITypeLib2::GetLibStatistics
3506 * Returns statistics about a type library that are required for efficient
3507 * sizing of hash tables.
3510 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3512 ULONG *pcUniqueNames,
3513 ULONG *pcchUniqueNames)
3515 ICOM_THIS( ITypeLibImpl, iface);
3517 FIXME("(%p): stub!\n", This);
3519 if(pcUniqueNames) *pcUniqueNames=1;
3520 if(pcchUniqueNames) *pcchUniqueNames=1;
3524 /* ITypeLib2::GetDocumentation2
3526 * Retrieves the library's documentation string, the complete Help file name
3527 * and path, the localization context to use, and the context ID for the
3528 * library Help topic in the Help file.
3531 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3535 BSTR *pbstrHelpString,
3536 DWORD *pdwHelpStringContext,
3537 BSTR *pbstrHelpStringDll)
3539 ICOM_THIS( ITypeLibImpl, iface);
3543 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3545 /* the help string should be obtained from the helpstringdll,
3546 * using the _DLLGetDocumentation function, based on the supplied
3547 * lcid. Nice to do sometime...
3551 /* documentation for the typelib */
3553 *pbstrHelpString=SysAllocString(This->DocString);
3554 if(pdwHelpStringContext)
3555 *pdwHelpStringContext=This->dwHelpContext;
3556 if(pbstrHelpStringDll)
3557 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3563 /* for a typeinfo */
3564 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3566 if(SUCCEEDED(result))
3568 ITypeInfo2 * pTInfo2;
3569 result = ITypeInfo_QueryInterface(pTInfo,
3571 (LPVOID*) &pTInfo2);
3573 if(SUCCEEDED(result))
3575 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3579 pdwHelpStringContext,
3580 pbstrHelpStringDll);
3582 ITypeInfo2_Release(pTInfo2);
3585 ITypeInfo_Release(pTInfo);
3591 /* ITypeLib2::GetAllCustData
3593 * Gets all custom data items for the library.
3596 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3598 CUSTDATA *pCustData)
3600 ICOM_THIS( ITypeLibImpl, iface);
3601 TLBCustData *pCData;
3603 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3604 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3605 if(pCustData->prgCustData ){
3606 pCustData->cCustData=This->ctCustData;
3607 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3608 pCustData->prgCustData[i].guid=pCData->guid;
3609 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3612 ERR(" OUT OF MEMORY! \n");
3613 return E_OUTOFMEMORY;
3618 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3619 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3620 ITypeLib2_fnQueryInterface,
3622 ITypeLib2_fnRelease,
3623 ITypeLib2_fnGetTypeInfoCount,
3624 ITypeLib2_fnGetTypeInfo,
3625 ITypeLib2_fnGetTypeInfoType,
3626 ITypeLib2_fnGetTypeInfoOfGuid,
3627 ITypeLib2_fnGetLibAttr,
3628 ITypeLib2_fnGetTypeComp,
3629 ITypeLib2_fnGetDocumentation,
3631 ITypeLib2_fnFindName,
3632 ITypeLib2_fnReleaseTLibAttr,
3634 ITypeLib2_fnGetCustData,
3635 ITypeLib2_fnGetLibStatistics,
3636 ITypeLib2_fnGetDocumentation2,
3637 ITypeLib2_fnGetAllCustData
3640 /*================== ITypeInfo(2) Methods ===================================*/
3641 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3643 ITypeInfoImpl * pTypeInfoImpl;
3645 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3648 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3649 pTypeInfoImpl->ref=1;
3651 TRACE("(%p)\n", pTypeInfoImpl);
3652 return (ITypeInfo2*) pTypeInfoImpl;
3655 /* ITypeInfo::QueryInterface
3657 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3662 ICOM_THIS( ITypeLibImpl, iface);
3664 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3667 if(IsEqualIID(riid, &IID_IUnknown) ||
3668 IsEqualIID(riid,&IID_ITypeInfo)||
3669 IsEqualIID(riid,&IID_ITypeInfo2))
3673 ITypeInfo_AddRef(iface);
3674 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3677 TRACE("-- Interface: E_NOINTERFACE\n");
3678 return E_NOINTERFACE;
3681 /* ITypeInfo::AddRef
3683 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3685 ICOM_THIS( ITypeInfoImpl, iface);
3689 TRACE("(%p)->ref is %u\n",This, This->ref);
3693 /* ITypeInfo::Release
3695 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3697 ICOM_THIS( ITypeInfoImpl, iface);
3701 TRACE("(%p)->(%u)\n",This, This->ref);
3705 FIXME("destroy child objects\n");
3707 TRACE("destroying ITypeInfo(%p)\n",This);
3710 SysFreeString(This->Name);
3714 if (This->DocString)
3716 SysFreeString(This->DocString);
3717 This->DocString = 0;
3722 ITypeInfo_Release((ITypeInfo*)This->next);
3725 HeapFree(GetProcessHeap(),0,This);
3731 /* ITypeInfo::GetTypeAttr
3733 * Retrieves a TYPEATTR structure that contains the attributes of the type
3737 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3738 LPTYPEATTR *ppTypeAttr)
3740 ICOM_THIS( ITypeInfoImpl, iface);
3741 TRACE("(%p)\n",This);
3742 /* FIXME: must do a copy here */
3743 *ppTypeAttr=&This->TypeAttr;
3747 /* ITypeInfo::GetTypeComp
3749 * Retrieves the ITypeComp interface for the type description, which enables a
3750 * client compiler to bind to the type description's members.
3753 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3754 ITypeComp * *ppTComp)
3756 ICOM_THIS( ITypeInfoImpl, iface);
3757 FIXME("(%p) stub!\n", This);
3761 /* ITypeInfo::GetFuncDesc
3763 * Retrieves the FUNCDESC structure that contains information about a
3764 * specified function.
3767 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3768 LPFUNCDESC *ppFuncDesc)
3770 ICOM_THIS( ITypeInfoImpl, iface);
3772 TLBFuncDesc * pFDesc;
3773 TRACE("(%p) index %d\n", This, index);
3774 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3777 /* FIXME: must do a copy here */
3778 *ppFuncDesc=&pFDesc->funcdesc;
3781 return E_INVALIDARG;
3784 /* ITypeInfo::GetVarDesc
3786 * Retrieves a VARDESC structure that describes the specified variable.
3789 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3790 LPVARDESC *ppVarDesc)
3792 ICOM_THIS( ITypeInfoImpl, iface);
3794 TLBVarDesc * pVDesc;
3795 TRACE("(%p) index %d\n", This, index);
3796 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3799 /* FIXME: must do a copy here */
3800 *ppVarDesc=&pVDesc->vardesc;
3803 return E_INVALIDARG;
3806 /* ITypeInfo_GetNames
3808 * Retrieves the variable with the specified member ID (or the name of the
3809 * property or method and its parameters) that correspond to the specified
3812 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3813 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3815 ICOM_THIS( ITypeInfoImpl, iface);
3816 TLBFuncDesc * pFDesc;
3817 TLBVarDesc * pVDesc;
3819 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3820 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3823 /* function found, now return function and parameter names */
3824 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3827 *rgBstrNames=SysAllocString(pFDesc->Name);
3829 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3835 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3838 *rgBstrNames=SysAllocString(pVDesc->Name);
3843 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3845 /* recursive search */
3848 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3850 if(SUCCEEDED(result))
3852 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3853 ITypeInfo_Release(pTInfo);
3856 WARN("Could not search inherited interface!\n");
3860 WARN("no names found\n");
3863 return TYPE_E_ELEMENTNOTFOUND;
3870 /* ITypeInfo::GetRefTypeOfImplType
3872 * If a type description describes a COM class, it retrieves the type
3873 * description of the implemented interface types. For an interface,
3874 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3878 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3883 ICOM_THIS( ITypeInfoImpl, iface);
3885 TLBImplType *pImpl = This->impltypelist;
3887 TRACE("(%p) index %d\n", This, index);
3888 dump_TypeInfo(This);
3892 /* only valid on dual interfaces;
3893 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3895 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3897 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3898 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3904 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3905 *pRefType = pImpl->hRef;
3910 /* get element n from linked list */
3911 for(i=0; pImpl && i<index; i++)
3913 pImpl = pImpl->next;
3916 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3918 *pRefType = pImpl->hRef;
3920 TRACE("-- 0x%08lx\n", pImpl->hRef );
3927 /* ITypeInfo::GetImplTypeFlags
3929 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3930 * or base interface in a type description.
3932 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3933 UINT index, INT *pImplTypeFlags)
3935 ICOM_THIS( ITypeInfoImpl, iface);
3939 TRACE("(%p) index %d\n", This, index);
3940 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3941 i++, pImpl=pImpl->next)
3943 if(i==index && pImpl){
3944 *pImplTypeFlags=pImpl->implflags;
3948 return TYPE_E_ELEMENTNOTFOUND;
3952 * Maps between member names and member IDs, and parameter names and
3955 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3956 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3958 ICOM_THIS( ITypeInfoImpl, iface);
3959 TLBFuncDesc * pFDesc;
3960 TLBVarDesc * pVDesc;
3963 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3965 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3967 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3968 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3969 for(i=1; i < cNames; i++){
3970 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3971 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3973 if( j<pFDesc->funcdesc.cParams)
3976 ret=DISP_E_UNKNOWNNAME;
3981 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3982 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3983 if(cNames) *pMemId=pVDesc->vardesc.memid;
3987 /* not found, see if this is and interface with an inheritance */
3988 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3989 This->TypeAttr.cImplTypes ){
3990 /* recursive search */
3992 ret=ITypeInfo_GetRefTypeInfo(iface,
3993 This->impltypelist->hRef, &pTInfo);
3995 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3996 ITypeInfo_Release(pTInfo);
3999 WARN("Could not search inherited interface!\n");
4001 WARN("no names found\n");
4002 return DISP_E_UNKNOWNNAME;
4005 /* ITypeInfo::Invoke
4007 * Invokes a method, or accesses a property of an object, that implements the
4008 * interface described by the type description.
4011 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
4014 if (TRACE_ON(ole)) {
4016 MESSAGE("Calling %p(",func);
4017 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
4026 DWORD (WINAPI *xfunc)() = func;
4031 DWORD (WINAPI *xfunc)(DWORD) = func;
4032 res = xfunc(args[0]);
4036 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
4037 res = xfunc(args[0],args[1]);
4041 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
4042 res = xfunc(args[0],args[1],args[2]);
4046 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
4047 res = xfunc(args[0],args[1],args[2],args[3]);
4051 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4052 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4056 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4057 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4061 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4062 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4066 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4067 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4071 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4072 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4076 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4082 FIXME("unsupported calling convention %d\n",callconv);
4086 TRACE("returns %08lx\n",res);
4090 extern int const _argsize(DWORD vt);
4092 /***********************************************************************
4093 * DispCallFunc (OLEAUT32.@)
4097 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4098 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4100 int i, argsize, argspos;
4104 FIXME("(%p, %ld, %d, %d, %d, %p, %p, %p)\n",
4105 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult
4108 for (i=0;i<cActuals;i++) {
4109 FIXME("arg %d: type %d\n",i,prgvt[i]);
4110 dump_Variant(prgpvarg[i]);
4111 argsize += _argsize(prgvt[i]);
4113 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4115 for (i=0;i<cActuals;i++) {
4117 VARIANT *arg = prgpvarg[i];
4119 arglen = _argsize(prgvt[i]);
4120 if (V_VT(arg) == prgvt[i]) {
4121 memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
4123 if (prgvt[i] == VT_VARIANT) {
4124 memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
4126 ERR("Set arg %d to disparg type %d vs %d\n",i,
4134 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4136 hres = _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize/4,args);
4137 HeapFree(GetProcessHeap(),0,args);
4141 static HRESULT WINAPI ITypeInfo_fnInvoke(
4146 DISPPARAMS *pDispParams,
4147 VARIANT *pVarResult,
4148 EXCEPINFO *pExcepInfo,
4151 ICOM_THIS( ITypeInfoImpl, iface);
4152 TLBFuncDesc * pFDesc;
4153 TLBVarDesc * pVDesc;
4156 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4157 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4159 dump_DispParms(pDispParams);
4161 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4162 if (pFDesc->funcdesc.memid == memid) {
4163 if (pFDesc->funcdesc.invkind & dwFlags)
4167 dump_TLBFuncDescOne(pFDesc);
4168 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4169 switch (pFDesc->funcdesc.funckind) {
4170 case FUNC_PUREVIRTUAL:
4171 case FUNC_VIRTUAL: {
4173 int numargs, numargs2, argspos, args2pos;
4174 DWORD *args , *args2;
4177 numargs = 1; numargs2 = 0;
4178 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4179 if (i<pDispParams->cArgs)
4180 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4182 numargs += 1; /* sizeof(lpvoid) */
4183 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4187 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4188 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4190 args[0] = (DWORD)pIUnk;
4191 argspos = 1; args2pos = 0;
4192 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4193 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4194 if (i<pDispParams->cArgs) {
4195 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4196 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4198 if (V_VT(arg) == tdesc->vt) {
4199 memcpy(&args[argspos],&V_UNION(arg,lVal), arglen*sizeof(DWORD));
4200 } else if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==tdesc->vt)) {
4201 memcpy(&args[argspos],(void*)V_UNION(arg,lVal), arglen*sizeof(DWORD));
4202 } else if (tdesc->vt == VT_VARIANT) {
4203 memcpy(&args[argspos],arg, arglen*sizeof(DWORD));
4205 ERR("Set arg %d to disparg type %d vs %d\n",i,
4211 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4212 if (tdesc->vt != VT_PTR)
4213 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4214 /*FIXME: give pointers for the rest, so propertyget works*/
4215 args[argspos] = (DWORD)&args2[args2pos];
4217 /* If pointer to variant, pass reference it. */
4218 if ((tdesc->vt == VT_PTR) &&
4219 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4222 args[argspos]= (DWORD)pVarResult;
4227 if (pFDesc->funcdesc.cParamsOpt)
4228 FIXME("Does not support optional parameters (%d)\n",
4229 pFDesc->funcdesc.cParamsOpt
4232 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4233 pFDesc->funcdesc.callconv,
4237 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4239 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4240 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4241 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4242 /* If we are a pointer to a variant, we are done already */
4243 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4246 VariantInit(pVarResult);
4247 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4249 if (tdesc->vt == VT_PTR)
4250 tdesc = tdesc->u.lptdesc;
4251 V_VT(pVarResult) = tdesc->vt;
4253 /* HACK: VB5 likes this.
4254 * I do not know why. There is 1 example in MSDN which uses
4255 * this which appears broken (mixes int vals and
4258 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4259 V_VT(pVarResult) = VT_DISPATCH;
4260 TRACE("storing into variant:\n");
4261 dump_Variant(pVarResult);
4265 HeapFree(GetProcessHeap(),0,args2);
4266 HeapFree(GetProcessHeap(),0,args);
4269 case FUNC_DISPATCH: {
4273 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4275 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4278 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4279 hr = IDispatch_Invoke(
4280 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4281 pVarResult,pExcepInfo,pArgErr
4284 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4285 IDispatch_Release(disp);
4289 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4293 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4294 if (pVDesc->vardesc.memid == memid) {
4295 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4296 dump_TLBVarDesc(pVDesc);
4301 /* not found, look for it in inherited interfaces */
4302 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4303 /* recursive search */
4306 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4308 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4309 ITypeInfo_Release(pTInfo);
4312 WARN("Could not search inherited interface!\n");
4314 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4315 return DISP_E_MEMBERNOTFOUND;
4318 /* ITypeInfo::GetDocumentation
4320 * Retrieves the documentation string, the complete Help file name and path,
4321 * and the context ID for the Help topic for a specified type description.
4323 * (Can be tested by the Visual Basic Editor in Word for instance.)
4325 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4326 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4327 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4329 ICOM_THIS( ITypeInfoImpl, iface);
4330 TLBFuncDesc * pFDesc;
4331 TLBVarDesc * pVDesc;
4332 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4333 " HelpContext(%p) HelpFile(%p)\n",
4334 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4335 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4337 *pBstrName=SysAllocString(This->Name);
4339 *pBstrDocString=SysAllocString(This->DocString);
4341 *pdwHelpContext=This->dwHelpContext;
4343 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4345 }else {/* for a member */
4346 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4347 if(pFDesc->funcdesc.memid==memid){
4349 *pBstrName = SysAllocString(pFDesc->Name);
4351 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4353 *pdwHelpContext=pFDesc->helpcontext;
4356 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4357 if(pVDesc->vardesc.memid==memid){
4359 *pBstrName = SysAllocString(pVDesc->Name);
4361 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4363 *pdwHelpContext=pVDesc->HelpContext;
4367 return TYPE_E_ELEMENTNOTFOUND;
4370 /* ITypeInfo::GetDllEntry
4372 * Retrieves a description or specification of an entry point for a function
4375 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4376 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4379 ICOM_THIS( ITypeInfoImpl, iface);
4380 TLBFuncDesc *pFDesc;
4382 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4384 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4385 if(pFDesc->funcdesc.memid==memid){
4386 dump_TypeInfo(This);
4387 dump_TLBFuncDescOne(pFDesc);
4389 /* FIXME: This is wrong, but how do you find that out? */
4391 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4392 *pBstrDllName = SysAllocString(oleaut32W);
4395 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4397 *pBstrName = SysAllocString(pFDesc->Entry);
4405 *pwOrdinal = (DWORD)pFDesc->Entry;
4411 /* ITypeInfo::GetRefTypeInfo
4413 * If a type description references other type descriptions, it retrieves
4414 * the referenced type descriptions.
4416 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4419 ITypeInfo **ppTInfo)
4421 ICOM_THIS( ITypeInfoImpl, iface);
4422 HRESULT result = E_FAIL;
4425 if (hRefType == -1 &&
4426 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4427 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4429 /* when we meet a DUAL dispinterface, we must create the interface
4432 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4435 /* the interface version contains the same information as the dispinterface
4436 * copy the contents of the structs.
4438 *pTypeInfoImpl = *This;
4439 pTypeInfoImpl->ref = 1;
4441 /* change the type to interface */
4442 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4444 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4446 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4451 TLBRefType *pRefType;
4452 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4453 if(pRefType->reference == hRefType)
4457 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4458 if(pRefType && hRefType != -1) {
4459 ITypeLib *pTLib = NULL;
4461 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4463 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4465 if(pRefType->pImpTLInfo->pImpTypeLib) {
4466 TRACE("typeinfo in imported typelib that is already loaded\n");
4467 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4468 ITypeLib2_AddRef((ITypeLib*) pTLib);
4471 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4472 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4473 pRefType->pImpTLInfo->wVersionMajor,
4474 pRefType->pImpTLInfo->wVersionMinor,
4475 pRefType->pImpTLInfo->lcid,
4478 if(!SUCCEEDED(result)) {
4479 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4480 result=LoadTypeLib(libnam, &pTLib);
4481 SysFreeString(libnam);
4483 if(SUCCEEDED(result)) {
4484 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4485 ITypeLib2_AddRef(pTLib);
4489 if(SUCCEEDED(result)) {
4490 if(pRefType->index == TLB_REF_USE_GUID)
4491 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4495 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4499 ITypeLib2_Release(pTLib);
4503 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4504 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4508 /* ITypeInfo::AddressOfMember
4510 * Retrieves the addresses of static functions or variables, such as those
4513 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4514 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4516 ICOM_THIS( ITypeInfoImpl, iface);
4517 FIXME("(%p) stub!\n", This);
4521 /* ITypeInfo::CreateInstance
4523 * Creates a new instance of a type that describes a component object class
4526 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4527 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4529 ICOM_THIS( ITypeInfoImpl, iface);
4530 FIXME("(%p) stub!\n", This);
4534 /* ITypeInfo::GetMops
4536 * Retrieves marshaling information.
4538 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4541 ICOM_THIS( ITypeInfoImpl, iface);
4542 FIXME("(%p) stub!\n", This);
4546 /* ITypeInfo::GetContainingTypeLib
4548 * Retrieves the containing type library and the index of the type description
4549 * within that type library.
4551 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4552 ITypeLib * *ppTLib, UINT *pIndex)
4554 ICOM_THIS( ITypeInfoImpl, iface);
4556 return E_INVALIDARG;
4557 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4558 *pIndex=This->index;
4559 ITypeLib2_AddRef(*ppTLib);
4560 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4564 /* ITypeInfo::ReleaseTypeAttr
4566 * Releases a TYPEATTR previously returned by GetTypeAttr.
4569 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4570 TYPEATTR* pTypeAttr)
4572 ICOM_THIS( ITypeInfoImpl, iface);
4573 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4577 /* ITypeInfo::ReleaseFuncDesc
4579 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4581 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4583 FUNCDESC *pFuncDesc)
4585 ICOM_THIS( ITypeInfoImpl, iface);
4586 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4590 /* ITypeInfo::ReleaseVarDesc
4592 * Releases a VARDESC previously returned by GetVarDesc.
4594 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4597 ICOM_THIS( ITypeInfoImpl, iface);
4598 TRACE("(%p)->(%p)\n", This, pVarDesc);
4602 /* ITypeInfo2::GetTypeKind
4604 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4607 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4608 TYPEKIND *pTypeKind)
4610 ICOM_THIS( ITypeInfoImpl, iface);
4611 *pTypeKind=This->TypeAttr.typekind;
4612 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4616 /* ITypeInfo2::GetTypeFlags
4618 * Returns the type flags without any allocations. This returns a DWORD type
4619 * flag, which expands the type flags without growing the TYPEATTR (type
4623 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4626 ICOM_THIS( ITypeInfoImpl, iface);
4627 *pTypeFlags=This->TypeAttr.wTypeFlags;
4628 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4632 /* ITypeInfo2::GetFuncIndexOfMemId
4633 * Binds to a specific member based on a known DISPID, where the member name
4634 * is not known (for example, when binding to a default member).
4637 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4638 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4640 ICOM_THIS( ITypeInfoImpl, iface);
4641 TLBFuncDesc *pFuncInfo;
4644 /* FIXME: should check for invKind??? */
4645 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4646 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4652 result=E_INVALIDARG;
4654 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4655 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4659 /* TypeInfo2::GetVarIndexOfMemId
4661 * Binds to a specific member based on a known DISPID, where the member name
4662 * is not known (for example, when binding to a default member).
4665 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4666 MEMBERID memid, UINT *pVarIndex)
4668 ICOM_THIS( ITypeInfoImpl, iface);
4669 TLBVarDesc *pVarInfo;
4672 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4673 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4680 result=E_INVALIDARG;
4682 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4683 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4687 /* ITypeInfo2::GetCustData
4689 * Gets the custom data
4691 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4696 ICOM_THIS( ITypeInfoImpl, iface);
4697 TLBCustData *pCData;
4699 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4700 if( IsEqualIID(guid, &pCData->guid)) break;
4702 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4706 VariantInit( pVarVal);
4707 VariantCopy( pVarVal, &pCData->data);
4710 return E_INVALIDARG; /* FIXME: correct? */
4713 /* ITypeInfo2::GetFuncCustData
4715 * Gets the custom data
4717 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4723 ICOM_THIS( ITypeInfoImpl, iface);
4724 TLBCustData *pCData=NULL;
4725 TLBFuncDesc * pFDesc;
4727 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4728 pFDesc=pFDesc->next);
4731 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4732 if( IsEqualIID(guid, &pCData->guid)) break;
4734 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4737 VariantInit( pVarVal);
4738 VariantCopy( pVarVal, &pCData->data);
4741 return E_INVALIDARG; /* FIXME: correct? */
4744 /* ITypeInfo2::GetParamCustData
4746 * Gets the custom data
4748 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4755 ICOM_THIS( ITypeInfoImpl, iface);
4756 TLBCustData *pCData=NULL;
4757 TLBFuncDesc * pFDesc;
4760 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4762 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4763 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4764 pCData = pCData->next)
4765 if( IsEqualIID(guid, &pCData->guid)) break;
4767 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4771 VariantInit( pVarVal);
4772 VariantCopy( pVarVal, &pCData->data);
4775 return E_INVALIDARG; /* FIXME: correct? */
4778 /* ITypeInfo2::GetVarCustData
4780 * Gets the custom data
4782 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4788 ICOM_THIS( ITypeInfoImpl, iface);
4789 TLBCustData *pCData=NULL;
4790 TLBVarDesc * pVDesc;
4793 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4797 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4799 if( IsEqualIID(guid, &pCData->guid)) break;
4803 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4807 VariantInit( pVarVal);
4808 VariantCopy( pVarVal, &pCData->data);
4811 return E_INVALIDARG; /* FIXME: correct? */
4814 /* ITypeInfo2::GetImplCustData
4816 * Gets the custom data
4818 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4824 ICOM_THIS( ITypeInfoImpl, iface);
4825 TLBCustData *pCData=NULL;
4826 TLBImplType * pRDesc;
4829 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4833 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4835 if( IsEqualIID(guid, &pCData->guid)) break;
4839 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4843 VariantInit( pVarVal);
4844 VariantCopy( pVarVal, &pCData->data);
4847 return E_INVALIDARG; /* FIXME: correct? */
4850 /* ITypeInfo2::GetDocumentation2
4852 * Retrieves the documentation string, the complete Help file name and path,
4853 * the localization context to use, and the context ID for the library Help
4854 * topic in the Help file.
4857 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4861 BSTR *pbstrHelpString,
4862 DWORD *pdwHelpStringContext,
4863 BSTR *pbstrHelpStringDll)
4865 ICOM_THIS( ITypeInfoImpl, iface);
4866 TLBFuncDesc * pFDesc;
4867 TLBVarDesc * pVDesc;
4868 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4869 "HelpStringContext(%p) HelpStringDll(%p)\n",
4870 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4871 pbstrHelpStringDll );
4872 /* the help string should be obtained from the helpstringdll,
4873 * using the _DLLGetDocumentation function, based on the supplied
4874 * lcid. Nice to do sometime...
4876 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4878 *pbstrHelpString=SysAllocString(This->Name);
4879 if(pdwHelpStringContext)
4880 *pdwHelpStringContext=This->dwHelpStringContext;
4881 if(pbstrHelpStringDll)
4882 *pbstrHelpStringDll=
4883 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4885 }else {/* for a member */
4886 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4887 if(pFDesc->funcdesc.memid==memid){
4889 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4890 if(pdwHelpStringContext)
4891 *pdwHelpStringContext=pFDesc->HelpStringContext;
4892 if(pbstrHelpStringDll)
4893 *pbstrHelpStringDll=
4894 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4897 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4898 if(pVDesc->vardesc.memid==memid){
4900 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4901 if(pdwHelpStringContext)
4902 *pdwHelpStringContext=pVDesc->HelpStringContext;
4903 if(pbstrHelpStringDll)
4904 *pbstrHelpStringDll=
4905 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4909 return TYPE_E_ELEMENTNOTFOUND;
4912 /* ITypeInfo2::GetAllCustData
4914 * Gets all custom data items for the Type info.
4917 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4919 CUSTDATA *pCustData)
4921 ICOM_THIS( ITypeInfoImpl, iface);
4922 TLBCustData *pCData;
4925 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4927 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4928 if(pCustData->prgCustData ){
4929 pCustData->cCustData=This->ctCustData;
4930 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4931 pCustData->prgCustData[i].guid=pCData->guid;
4932 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4935 ERR(" OUT OF MEMORY! \n");
4936 return E_OUTOFMEMORY;
4941 /* ITypeInfo2::GetAllFuncCustData
4943 * Gets all custom data items for the specified Function
4946 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4949 CUSTDATA *pCustData)
4951 ICOM_THIS( ITypeInfoImpl, iface);
4952 TLBCustData *pCData;
4953 TLBFuncDesc * pFDesc;
4955 TRACE("(%p) index %d\n", This, index);
4956 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4957 pFDesc=pFDesc->next)
4960 pCustData->prgCustData =
4961 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4962 if(pCustData->prgCustData ){
4963 pCustData->cCustData=pFDesc->ctCustData;
4964 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4965 pCData = pCData->next){
4966 pCustData->prgCustData[i].guid=pCData->guid;
4967 VariantCopy(& pCustData->prgCustData[i].varValue,
4971 ERR(" OUT OF MEMORY! \n");
4972 return E_OUTOFMEMORY;
4976 return TYPE_E_ELEMENTNOTFOUND;
4979 /* ITypeInfo2::GetAllParamCustData
4981 * Gets all custom data items for the Functions
4984 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4985 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4987 ICOM_THIS( ITypeInfoImpl, iface);
4988 TLBCustData *pCData=NULL;
4989 TLBFuncDesc * pFDesc;
4991 TRACE("(%p) index %d\n", This, indexFunc);
4992 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4993 pFDesc=pFDesc->next)
4995 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4996 pCustData->prgCustData =
4997 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4998 sizeof(CUSTDATAITEM));
4999 if(pCustData->prgCustData ){
5000 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5001 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5002 pCData; i++, pCData = pCData->next){
5003 pCustData->prgCustData[i].guid=pCData->guid;
5004 VariantCopy(& pCustData->prgCustData[i].varValue,
5008 ERR(" OUT OF MEMORY! \n");
5009 return E_OUTOFMEMORY;
5013 return TYPE_E_ELEMENTNOTFOUND;
5016 /* ITypeInfo2::GetAllVarCustData
5018 * Gets all custom data items for the specified Variable
5021 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5022 UINT index, CUSTDATA *pCustData)
5024 ICOM_THIS( ITypeInfoImpl, iface);
5025 TLBCustData *pCData;
5026 TLBVarDesc * pVDesc;
5028 TRACE("(%p) index %d\n", This, index);
5029 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5030 pVDesc=pVDesc->next)
5033 pCustData->prgCustData =
5034 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5035 if(pCustData->prgCustData ){
5036 pCustData->cCustData=pVDesc->ctCustData;
5037 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5038 pCData = pCData->next){
5039 pCustData->prgCustData[i].guid=pCData->guid;
5040 VariantCopy(& pCustData->prgCustData[i].varValue,
5044 ERR(" OUT OF MEMORY! \n");
5045 return E_OUTOFMEMORY;
5049 return TYPE_E_ELEMENTNOTFOUND;
5052 /* ITypeInfo2::GetAllImplCustData
5054 * Gets all custom data items for the specified implementation type
5057 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5060 CUSTDATA *pCustData)
5062 ICOM_THIS( ITypeInfoImpl, iface);
5063 TLBCustData *pCData;
5064 TLBImplType * pRDesc;
5066 TRACE("(%p) index %d\n", This, index);
5067 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5068 pRDesc=pRDesc->next)
5071 pCustData->prgCustData =
5072 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5073 if(pCustData->prgCustData ){
5074 pCustData->cCustData=pRDesc->ctCustData;
5075 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5076 pCData = pCData->next){
5077 pCustData->prgCustData[i].guid=pCData->guid;
5078 VariantCopy(& pCustData->prgCustData[i].varValue,
5082 ERR(" OUT OF MEMORY! \n");
5083 return E_OUTOFMEMORY;
5087 return TYPE_E_ELEMENTNOTFOUND;
5090 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5092 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5094 ITypeInfo_fnQueryInterface,
5096 ITypeInfo_fnRelease,
5098 ITypeInfo_fnGetTypeAttr,
5099 ITypeInfo_fnGetTypeComp,
5100 ITypeInfo_fnGetFuncDesc,
5101 ITypeInfo_fnGetVarDesc,
5102 ITypeInfo_fnGetNames,
5103 ITypeInfo_fnGetRefTypeOfImplType,
5104 ITypeInfo_fnGetImplTypeFlags,
5105 ITypeInfo_fnGetIDsOfNames,
5107 ITypeInfo_fnGetDocumentation,
5108 ITypeInfo_fnGetDllEntry,
5109 ITypeInfo_fnGetRefTypeInfo,
5110 ITypeInfo_fnAddressOfMember,
5111 ITypeInfo_fnCreateInstance,
5112 ITypeInfo_fnGetMops,
5113 ITypeInfo_fnGetContainingTypeLib,
5114 ITypeInfo_fnReleaseTypeAttr,
5115 ITypeInfo_fnReleaseFuncDesc,
5116 ITypeInfo_fnReleaseVarDesc,
5118 ITypeInfo2_fnGetTypeKind,
5119 ITypeInfo2_fnGetTypeFlags,
5120 ITypeInfo2_fnGetFuncIndexOfMemId,
5121 ITypeInfo2_fnGetVarIndexOfMemId,
5122 ITypeInfo2_fnGetCustData,
5123 ITypeInfo2_fnGetFuncCustData,
5124 ITypeInfo2_fnGetParamCustData,
5125 ITypeInfo2_fnGetVarCustData,
5126 ITypeInfo2_fnGetImplTypeCustData,
5127 ITypeInfo2_fnGetDocumentation2,
5128 ITypeInfo2_fnGetAllCustData,
5129 ITypeInfo2_fnGetAllFuncCustData,
5130 ITypeInfo2_fnGetAllParamCustData,
5131 ITypeInfo2_fnGetAllVarCustData,
5132 ITypeInfo2_fnGetAllImplTypeCustData,