4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
63 #define NONAMELESSUNION
64 #define NONAMELESSSTRUCT
66 #include "winnls.h" /* for PRIMARYLANGID */
67 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
70 #include "wine/unicode.h"
75 #include "wine/debug.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib);
81 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
82 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
84 /****************************************************************************
87 * Takes p_iVal (which is in little endian) and returns it
88 * in the host machine's byte order.
90 #ifdef WORDS_BIGENDIAN
91 static WORD FromLEWord(WORD p_iVal)
93 return (((p_iVal & 0x00FF) << 8) |
94 ((p_iVal & 0xFF00) >> 8));
98 static DWORD FromLEDWord(DWORD p_iVal)
100 return (((p_iVal & 0x000000FF) << 24) |
101 ((p_iVal & 0x0000FF00) << 8) |
102 ((p_iVal & 0x00FF0000) >> 8) |
103 ((p_iVal & 0xFF000000) >> 24));
106 #define FromLEWord(X) (X)
107 #define FromLEDWord(X) (X)
111 /****************************************************************************
114 * Fix byte order in any structure if necessary
116 #ifdef WORDS_BIGENDIAN
117 static void FromLEWords(void *p_Val, int p_iSize)
121 p_iSize /= sizeof(WORD);
124 *Val = FromLEWord(*Val);
131 static void FromLEDWords(void *p_Val, int p_iSize)
135 p_iSize /= sizeof(DWORD);
138 *Val = FromLEDWord(*Val);
144 #define FromLEWords(X,Y) /*nothing*/
145 #define FromLEDWords(X,Y) /*nothing*/
149 /****************************************************************************
150 * QueryPathOfRegTypeLib [OLEAUT32.164]
155 QueryPathOfRegTypeLib(
156 REFGUID guid, /* [in] referenced guid */
157 WORD wMaj, /* [in] major version */
158 WORD wMin, /* [in] minor version */
159 LCID lcid, /* [in] locale id */
160 LPBSTR path ) /* [out] path of typelib */
162 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
163 string termination character on output strings */
170 char szTypeLibKey[100];
171 char szPath[MAX_PATH];
172 DWORD dwPathLen = sizeof(szPath);
180 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
186 sprintf(szTypeLibKey,
187 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
188 guid->Data1, guid->Data2, guid->Data3,
189 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
190 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
195 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
199 else if (myLCID == lcid)
201 /* try with sub-langid */
202 myLCID = SUBLANGID(lcid);
204 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
206 /* try with system langid */
216 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
217 BSTR bstrPath = SysAllocStringLen(NULL,len);
219 MultiByteToWideChar(CP_ACP,
231 TRACE_(typelib)("%s not found\n", szTypeLibKey);
236 /******************************************************************************
237 * CreateTypeLib [OLEAUT32.160] creates a typelib
243 HRESULT WINAPI CreateTypeLib(
244 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
246 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
249 /******************************************************************************
250 * LoadTypeLib [OLEAUT32.161]
251 * Loads and registers a type library
253 * Docs: OLECHAR FAR* szFile
254 * Docs: iTypeLib FAR* FAR* pptLib
260 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
262 HRESULT WINAPI LoadTypeLib(
263 const OLECHAR *szFile,/* [in] Name of file to load from */
264 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
267 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
270 /******************************************************************************
271 * LoadTypeLibEx [OLEAUT32.183]
272 * Loads and optionally registers a type library
278 HRESULT WINAPI LoadTypeLibEx(
279 LPCOLESTR szFile, /* [in] Name of file to load from */
280 REGKIND regkind, /* [in] Specify kind of registration */
281 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
283 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
288 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
289 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
292 /* Look for a trailing '\\' followed by an index */
293 pIndexStr = strrchrW(szFile, '\\');
294 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
295 index = atoiW(pIndexStr);
296 memcpy(szFileCopy, szFile,
297 (pIndexStr - szFile - 1) * sizeof(WCHAR));
298 szFileCopy[pIndexStr - szFile - 1] = '\0';
299 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
301 return TYPE_E_CANTLOADLIBRARY;
302 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
303 return TYPE_E_CANTLOADLIBRARY;
306 WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
309 lstrcpyW(tstpath,szFile);
311 for (i=0;i<strlenW(tstpath);i++) {
312 if (tstpath[i] == 's') {
313 if (!strcmpW(tstpath+i,stdole32tlb)) {
315 MESSAGE("**************************************************************************\n");
316 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
317 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
318 MESSAGE("on the Microsoft Download Pages.\n");
319 MESSAGE("**************************************************************************\n");
324 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
325 return TYPE_E_CANTLOADLIBRARY;
329 TRACE("File %s index %d\n", debugstr_w(szPath), index);
331 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
336 case REGKIND_DEFAULT:
337 /* FIXME: is this correct? */
338 if (!szFile || !szFile[0] ||
339 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
341 /* else fall-through */
342 case REGKIND_REGISTER:
343 /* FIXME: Help path? */
344 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
346 IUnknown_Release(*pptLib);
354 TRACE(" returns %08lx\n",res);
358 /******************************************************************************
359 * LoadRegTypeLib [OLEAUT32.162]
361 HRESULT WINAPI LoadRegTypeLib(
362 REFGUID rguid, /* [in] referenced guid */
363 WORD wVerMajor, /* [in] major version */
364 WORD wVerMinor, /* [in] minor version */
365 LCID lcid, /* [in] locale id */
366 ITypeLib **ppTLib) /* [out] path of typelib */
369 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
373 res= LoadTypeLib(bstr, ppTLib);
377 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
383 /******************************************************************************
384 * RegisterTypeLib [OLEAUT32.163]
385 * Adds information about a type library to the System Registry
387 * Docs: ITypeLib FAR * ptlib
388 * Docs: OLECHAR FAR* szFullPath
389 * Docs: OLECHAR FAR* szHelpDir
395 HRESULT WINAPI RegisterTypeLib(
396 ITypeLib * ptlib, /* [in] Pointer to the library*/
397 OLECHAR * szFullPath, /* [in] full Path of the library*/
398 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
409 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
411 if (ptlib == NULL || szFullPath == NULL)
414 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
417 StringFromGUID2(&attr->guid, guid, 80);
418 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
419 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
420 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
421 HeapFree(GetProcessHeap(), 0, guidA);
424 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
425 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
429 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
431 if (RegSetValueExW(key, NULL, 0, REG_SZ,
432 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
440 /* FIXME: This *seems* to be 0 always, not sure though */
441 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
442 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
444 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
445 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
453 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
454 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
457 /* FIXME: is %u correct? */
458 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
459 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
460 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
468 /* register OLE Automation-compatible interfaces for this typelib */
469 types = ITypeLib_GetTypeInfoCount(ptlib);
470 for (tidx=0; tidx<types; tidx++) {
471 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
472 LPOLESTR name = NULL;
473 ITypeInfo *tinfo = NULL;
475 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
477 case TKIND_INTERFACE:
478 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
479 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
482 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
483 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
486 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
487 /* coclasses should probably not be registered? */
490 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
494 TYPEATTR *tattr = NULL;
495 ITypeInfo_GetTypeAttr(tinfo, &tattr);
497 TRACE_(typelib)("guid=%s, flags=%04x (",
498 debugstr_guid(&tattr->guid),
500 if (TRACE_ON(typelib)) {
501 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
521 * FIXME: The 1 is just here until we implement rpcrt4
522 * stub/proxy handling. Until then it helps IShield
525 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
527 /* register interface<->typelib coupling */
528 StringFromGUID2(&tattr->guid, guid, 80);
529 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
530 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
531 HeapFree(GetProcessHeap(), 0, guidA);
533 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
534 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
536 RegSetValueExW(key, NULL, 0, REG_SZ,
537 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
539 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
540 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
541 RegSetValueExA(subKey, NULL, 0, REG_SZ,
545 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
546 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
547 RegSetValueExA(subKey, NULL, 0, REG_SZ,
552 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
553 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
555 StringFromGUID2(&attr->guid, guid, 80);
556 snprintf(ver, sizeof(ver), "%x.%x",
557 attr->wMajorVerNum, attr->wMinorVerNum);
558 RegSetValueExW(subKey, NULL, 0, REG_SZ,
559 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
560 RegSetValueExA(subKey, "Version", 0, REG_SZ,
567 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
569 ITypeInfo_Release(tinfo);
576 ITypeLib_ReleaseTLibAttr(ptlib, attr);
582 /******************************************************************************
583 * UnRegisterTypeLib [OLEAUT32.186]
584 * Removes information about a type library from the System Registry
591 HRESULT WINAPI UnRegisterTypeLib(
592 REFGUID libid, /* [in] Guid of the library */
593 WORD wVerMajor, /* [in] major version */
594 WORD wVerMinor, /* [in] minor version */
595 LCID lcid, /* [in] locale id */
598 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
599 return S_OK; /* FIXME: pretend everything is OK */
602 /*======================= ITypeLib implementation =======================*/
604 typedef struct tagTLBCustData
608 struct tagTLBCustData* next;
611 /* data structure for import typelibs */
612 typedef struct tagTLBImpLib
614 int offset; /* offset in the file (MSFT)
615 offset in nametable (SLTG)
616 just used to identify library while reading
618 GUID guid; /* libid */
619 BSTR name; /* name */
621 LCID lcid; /* lcid of imported typelib */
623 WORD wVersionMajor; /* major version number */
624 WORD wVersionMinor; /* minor version number */
626 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
627 NULL if not yet loaded */
628 struct tagTLBImpLib * next;
631 /* internal ITypeLib data */
632 typedef struct tagITypeLibImpl
634 ICOM_VFIELD(ITypeLib2);
636 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
638 /* strings can be stored in tlb as multibyte strings BUT they are *always*
639 * exported to the application as a UNICODE string.
645 unsigned long dwHelpContext;
646 int TypeInfoCount; /* nr of typeinfo's in librarry */
647 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
648 int ctCustData; /* number of items in cust data list */
649 TLBCustData * pCustData; /* linked list to cust data */
650 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
651 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
652 libary. Only used while read MSFT
656 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
658 /* ITypeLib methods */
659 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
660 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
662 /*======================= ITypeInfo implementation =======================*/
664 /* data for refernced types */
665 typedef struct tagTLBRefType
667 INT index; /* Type index for internal ref or for external ref
668 it the format is SLTG. -2 indicates to
671 GUID guid; /* guid of the referenced type */
672 /* if index == TLB_REF_USE_GUID */
674 HREFTYPE reference; /* The href of this ref */
675 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
676 TLB_REF_INTERNAL for internal refs
677 TLB_REF_NOT_FOUND for broken refs */
679 struct tagTLBRefType * next;
682 #define TLB_REF_USE_GUID -2
684 #define TLB_REF_INTERNAL (void*)-2
685 #define TLB_REF_NOT_FOUND (void*)-1
687 /* internal Parameter data */
688 typedef struct tagTLBParDesc
692 TLBCustData * pCustData; /* linked list to cust data */
695 /* internal Function data */
696 typedef struct tagTLBFuncDesc
698 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
699 BSTR Name; /* the name of this function */
700 TLBParDesc *pParamDesc; /* array with param names and custom data */
702 int HelpStringContext;
704 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
706 TLBCustData * pCustData; /* linked list to cust data; */
707 struct tagTLBFuncDesc * next;
710 /* internal Variable data */
711 typedef struct tagTLBVarDesc
713 VARDESC vardesc; /* lots of info on the variable and its attributes. */
714 BSTR Name; /* the name of this variable */
716 int HelpStringContext; /* FIXME: where? */
719 TLBCustData * pCustData;/* linked list to cust data; */
720 struct tagTLBVarDesc * next;
723 /* internal implemented interface data */
724 typedef struct tagTLBImplType
726 HREFTYPE hRef; /* hRef of interface */
727 int implflags; /* IMPLFLAG_*s */
729 TLBCustData * pCustData;/* linked list to custom data; */
730 struct tagTLBImplType *next;
733 /* internal TypeInfo data */
734 typedef struct tagITypeInfoImpl
736 ICOM_VFIELD(ITypeInfo2);
738 TYPEATTR TypeAttr ; /* _lots_ of type information. */
739 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
740 int index; /* index in this typelib; */
741 /* type libs seem to store the doc strings in ascii
742 * so why should we do it in unicode?
746 unsigned long dwHelpContext;
747 unsigned long dwHelpStringContext;
750 TLBFuncDesc * funclist; /* linked list with function descriptions */
753 TLBVarDesc * varlist; /* linked list with variable descriptions */
755 /* Implemented Interfaces */
756 TLBImplType * impltypelist;
758 TLBRefType * reflist;
760 TLBCustData * pCustData; /* linked list to cust data; */
761 struct tagITypeInfoImpl * next;
764 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
766 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
768 typedef struct tagTLBContext
770 unsigned int oStart; /* start of TLB in file */
771 unsigned int pos; /* current pos */
772 unsigned int length; /* total length */
773 void *mapping; /* memory mapping */
774 MSFT_SegDir * pTblDir;
775 ITypeLibImpl* pLibInfo;
779 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
784 static void dump_VarType(VARTYPE vt,char *szVarType) {
785 /* FIXME : we could have better trace here, depending on the VARTYPE
788 if (vt & VT_RESERVED)
789 szVarType += strlen(strcpy(szVarType, "reserved | "));
791 szVarType += strlen(strcpy(szVarType, "ref to "));
793 szVarType += strlen(strcpy(szVarType, "array of "));
795 szVarType += strlen(strcpy(szVarType, "vector of "));
796 switch(vt & VT_TYPEMASK) {
797 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
798 case VT_I2: sprintf(szVarType, "VT_I2"); break;
799 case VT_I4: sprintf(szVarType, "VT_I4"); break;
800 case VT_R4: sprintf(szVarType, "VT_R4"); break;
801 case VT_R8: sprintf(szVarType, "VT_R8"); break;
802 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
803 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
804 case VT_CY: sprintf(szVarType, "VT_CY"); break;
805 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
806 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
807 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
808 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
809 case VT_I1: sprintf(szVarType, "VT_I1"); break;
810 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
811 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
812 case VT_INT: sprintf(szVarType, "VT_INT"); break;
813 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
814 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
815 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
816 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
817 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
821 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
822 if (pTD->vt & VT_RESERVED)
823 szVarType += strlen(strcpy(szVarType, "reserved | "));
824 if (pTD->vt & VT_BYREF)
825 szVarType += strlen(strcpy(szVarType, "ref to "));
826 if (pTD->vt & VT_ARRAY)
827 szVarType += strlen(strcpy(szVarType, "array of "));
828 if (pTD->vt & VT_VECTOR)
829 szVarType += strlen(strcpy(szVarType, "vector of "));
830 switch(pTD->vt & VT_TYPEMASK) {
831 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
832 case VT_I2: sprintf(szVarType, "VT_I2"); break;
833 case VT_I4: sprintf(szVarType, "VT_I4"); break;
834 case VT_R4: sprintf(szVarType, "VT_R4"); break;
835 case VT_R8: sprintf(szVarType, "VT_R8"); break;
836 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
837 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
838 case VT_CY: sprintf(szVarType, "VT_CY"); break;
839 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
840 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
841 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
842 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
843 case VT_I1: sprintf(szVarType, "VT_I1"); break;
844 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
845 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
846 case VT_INT: sprintf(szVarType, "VT_INT"); break;
847 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
848 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
849 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
850 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
851 pTD->u.hreftype); break;
852 case VT_PTR: sprintf(szVarType, "ptr to ");
853 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
855 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
856 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
858 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
859 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
860 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
863 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
867 void dump_ELEMDESC(ELEMDESC *edesc) {
869 dump_TypeDesc(&edesc->tdesc,buf);
870 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
871 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
872 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
874 void dump_FUNCDESC(FUNCDESC *funcdesc) {
876 MESSAGE("memid is %08lx\n",funcdesc->memid);
877 for (i=0;i<funcdesc->cParams;i++) {
878 MESSAGE("Param %d:\n",i);
879 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
881 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
882 switch (funcdesc->funckind) {
883 case FUNC_VIRTUAL: MESSAGE("virtual");break;
884 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
885 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
886 case FUNC_STATIC: MESSAGE("static");break;
887 case FUNC_DISPATCH: MESSAGE("dispatch");break;
888 default: MESSAGE("unknown");break;
890 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
891 switch (funcdesc->invkind) {
892 case INVOKE_FUNC: MESSAGE("func");break;
893 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
894 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
895 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
897 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
898 switch (funcdesc->callconv) {
899 case CC_CDECL: MESSAGE("cdecl");break;
900 case CC_PASCAL: MESSAGE("pascal");break;
901 case CC_STDCALL: MESSAGE("stdcall");break;
902 case CC_SYSCALL: MESSAGE("syscall");break;
905 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
906 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
907 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
910 void dump_IDLDESC(IDLDESC *idl) {
911 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
914 static char * typekind_desc[] =
927 void dump_TYPEATTR(TYPEATTR *tattr) {
929 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
930 MESSAGE("\tlcid: %ld\n",tattr->lcid);
931 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
932 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
933 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
934 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
935 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
936 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
937 MESSAGE("\tcVars: %d\n", tattr->cVars);
938 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
939 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
940 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
941 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
942 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
943 dump_TypeDesc(&tattr->tdescAlias,buf);
944 MESSAGE("\ttypedesc: %s\n", buf);
945 dump_IDLDESC(&tattr->idldescType);
948 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
951 if (!TRACE_ON(typelib))
953 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
954 for (i=0;i<pfd->funcdesc.cParams;i++)
955 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
958 dump_FUNCDESC(&(pfd->funcdesc));
960 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
961 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
963 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
967 dump_TLBFuncDescOne(pfd);
971 static void dump_TLBVarDesc(TLBVarDesc * pvd)
975 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
980 static void dump_TLBImpLib(TLBImpLib *import)
982 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
983 debugstr_w(import->name));
984 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
985 import->wVersionMinor, import->lcid, import->offset);
988 static void dump_TLBRefType(TLBRefType * prt)
992 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
994 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
996 TRACE_(typelib)("type no: %d\n", prt->index);
998 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
999 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1000 TRACE_(typelib)("in lib\n");
1001 dump_TLBImpLib(prt->pImpTLInfo);
1007 static void dump_TLBImplType(TLBImplType * impl)
1011 "implementing/inheriting interface hRef = %lx implflags %x\n",
1012 impl->hRef, impl->implflags);
1017 void dump_Variant(VARIANT * pvar)
1022 TRACE("(%p)\n", pvar);
1026 ZeroMemory(szVarType, sizeof(szVarType));
1028 /* FIXME : we could have better trace here, depending on the VARTYPE
1031 dump_VarType(V_VT(pvar),szVarType);
1033 TRACE("VARTYPE: %s\n", szVarType);
1035 if (V_VT(pvar) & VT_BYREF) {
1036 ref = V_UNION(pvar, byref);
1039 else ref = &V_UNION(pvar, cVal);
1041 if (V_VT(pvar) & VT_ARRAY) {
1045 if (V_VT(pvar) & VT_VECTOR) {
1050 switch (V_VT(pvar) & VT_TYPEMASK)
1053 TRACE("%d\n", *(short*)ref);
1058 TRACE("%u\n", *(UINT*)ref);
1063 TRACE("%d\n", *(INT*)ref);
1067 TRACE("%3.3e\n", *(float*)ref);
1071 TRACE("%3.3e\n", *(double*)ref);
1075 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1079 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1084 TRACE("%p\n", *(LPVOID*)ref);
1088 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1094 memset( &TM, 0, sizeof(TM) );
1096 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1097 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1099 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1100 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1101 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1107 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1112 TRACE("(?)%ld\n", *(long*)ref);
1117 static void dump_DispParms(DISPPARAMS * pdp)
1121 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1123 while (index < pdp->cArgs)
1125 dump_Variant( &pdp->rgvarg[index] );
1130 static void dump_TypeInfo(ITypeInfoImpl * pty)
1132 TRACE("%p ref=%u\n", pty, pty->ref);
1133 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1134 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1135 TRACE("fct:%u var:%u impl:%u\n",
1136 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1137 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1138 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1139 dump_TLBFuncDesc(pty->funclist);
1140 dump_TLBVarDesc(pty->varlist);
1141 dump_TLBImplType(pty->impltypelist);
1144 void dump_VARDESC(VARDESC *v)
1146 MESSAGE("memid %ld\n",v->memid);
1147 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1148 MESSAGE("oInst %ld\n",v->u.oInst);
1149 dump_ELEMDESC(&(v->elemdescVar));
1150 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1151 MESSAGE("varkind %d\n",v->varkind);
1154 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1156 /* VT_LPWSTR is largest type that */
1157 /* may appear in type description*/
1158 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1159 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1160 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1161 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1162 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1163 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1167 static void TLB_abort()
1171 static void * TLB_Alloc(unsigned size)
1174 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1176 ERR("cannot allocate memory\n");
1181 static void TLB_Free(void * ptr)
1183 HeapFree(GetProcessHeap(), 0, ptr);
1187 /**********************************************************************
1189 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1192 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1194 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1195 pcx->pos, count, pcx->oStart, pcx->length, where);
1197 if (where != DO_NOT_SEEK)
1199 where += pcx->oStart;
1200 if (where > pcx->length)
1203 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1208 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1209 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1214 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1219 ret = MSFT_Read(buffer, count, pcx, where);
1220 FromLEDWords(buffer, ret);
1225 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1230 ret = MSFT_Read(buffer, count, pcx, where);
1231 FromLEWords(buffer, ret);
1236 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1238 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1239 memset(pGuid,0, sizeof(GUID));
1242 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1243 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1244 pGuid->Data2 = FromLEWord(pGuid->Data2);
1245 pGuid->Data3 = FromLEWord(pGuid->Data3);
1246 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1249 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1252 MSFT_NameIntro niName;
1254 WCHAR* pwstring = NULL;
1255 BSTR bstrName = NULL;
1257 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1258 pcx->pTblDir->pNametab.offset+offset);
1259 niName.namelen &= 0xFF; /* FIXME: correct ? */
1260 name=TLB_Alloc((niName.namelen & 0xff) +1);
1261 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1262 name[niName.namelen & 0xff]='\0';
1264 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1267 /* no invalid characters in string */
1270 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1272 /* don't check for invalid character since this has been done previously */
1273 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1275 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1276 lengthInChars = SysStringLen(bstrName);
1277 HeapFree(GetProcessHeap(), 0, pwstring);
1280 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1284 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1291 if(offset<0) return NULL;
1292 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1293 if(length <= 0) return 0;
1294 string=TLB_Alloc(length +1);
1295 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1296 string[length]='\0';
1298 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1299 string, -1, NULL, 0);
1301 /* no invalid characters in string */
1304 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1306 /* don't check for invalid character since this has been done previously */
1307 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1309 bstr = SysAllocStringLen(pwstring, lengthInChars);
1310 lengthInChars = SysStringLen(bstr);
1311 HeapFree(GetProcessHeap(), 0, pwstring);
1314 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1318 * read a value and fill a VARIANT structure
1320 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1324 TRACE_(typelib)("\n");
1326 if(offset <0) { /* data are packed in here */
1327 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1328 V_UNION(pVar, iVal) = offset & 0xffff;
1331 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1332 pcx->pTblDir->pCustData.offset + offset );
1333 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1334 switch (V_VT(pVar)){
1335 case VT_EMPTY: /* FIXME: is this right? */
1336 case VT_NULL: /* FIXME: is this right? */
1337 case VT_I2 : /* this should not happen */
1348 case VT_VOID : /* FIXME: is this right? */
1356 case VT_DECIMAL : /* FIXME: is this right? */
1359 /* pointer types with known behaviour */
1362 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1364 FIXME("BSTR length = %d?\n", size);
1366 ptr=TLB_Alloc(size);/* allocate temp buffer */
1367 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1368 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1369 /* FIXME: do we need a AtoW conversion here? */
1370 V_UNION(pVar, bstrVal[size])=L'\0';
1371 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1376 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1383 case VT_USERDEFINED :
1389 case VT_STREAMED_OBJECT :
1390 case VT_STORED_OBJECT :
1391 case VT_BLOB_OBJECT :
1396 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1400 if(size>0) /* (big|small) endian correct? */
1401 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1405 * create a linked list with custom data
1407 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1413 TRACE_(typelib)("\n");
1417 pNew=TLB_Alloc(sizeof(TLBCustData));
1418 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1419 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1420 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1421 /* add new custom data at head of the list */
1422 pNew->next=*ppCustData;
1424 offset = entry.next;
1429 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1433 pTd->vt=type & VT_TYPEMASK;
1435 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1437 if(pTd->vt == VT_USERDEFINED)
1438 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1440 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1444 MSFT_DoFuncs(TLBContext* pcx,
1449 TLBFuncDesc** pptfd)
1452 * member information is stored in a data structure at offset
1453 * indicated by the memoffset field of the typeinfo structure
1454 * There are several distinctive parts.
1455 * the first part starts with a field that holds the total length
1456 * of this (first) part excluding this field. Then follow the records,
1457 * for each member there is one record.
1459 * First entry is always the length of the record (excluding this
1461 * Rest of the record depends on the type of the member. If there is
1462 * a field indicating the member type (function variable intereface etc)
1463 * I have not found it yet. At this time we depend on the information
1464 * in the type info and the usual order how things are stored.
1466 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1469 * Third is a equal sized array with file offsets to the name entry
1472 * Forth and last (?) part is an array with offsets to the records in the
1473 * first part of this file segment.
1476 int infolen, nameoffset, reclength, nrattributes, i;
1477 int recoffset = offset + sizeof(INT);
1480 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1482 TRACE_(typelib)("\n");
1484 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1486 for ( i = 0; i < cFuncs ; i++ )
1488 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1490 /* name, eventually add to a hash table */
1491 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1492 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1494 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1496 /* read the function information record */
1497 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1501 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1503 /* do the attributes */
1504 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1507 if ( nrattributes > 0 )
1509 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1511 if ( nrattributes > 1 )
1513 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1514 pFuncRec->OptAttr[1]) ;
1516 if ( nrattributes > 2 )
1518 if ( pFuncRec->FKCCIC & 0x2000 )
1520 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1524 (*pptfd)->Entry = MSFT_ReadString(pcx,
1525 pFuncRec->OptAttr[2]);
1527 if( nrattributes > 5 )
1529 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1531 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1534 pFuncRec->OptAttr[6],
1535 &(*pptfd)->pCustData);
1542 /* fill the FuncDesc Structure */
1543 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1544 offset + infolen + ( i + 1) * sizeof(INT));
1546 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1547 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1548 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1549 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1550 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1551 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1552 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1556 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1559 /* do the parameters/arguments */
1560 if(pFuncRec->nrargs)
1563 MSFT_ParameterInfo paraminfo;
1565 (*pptfd)->funcdesc.lprgelemdescParam =
1566 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1568 (*pptfd)->pParamDesc =
1569 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1571 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1572 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1574 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1576 TYPEDESC* lpArgTypeDesc = 0;
1580 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1583 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1585 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1587 /* SEEK value = jump to offset,
1588 * from there jump to the end of record,
1589 * go back by (j-1) arguments
1591 MSFT_ReadLEDWords( ¶minfo ,
1592 sizeof(MSFT_ParameterInfo), pcx,
1593 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1594 * sizeof(MSFT_ParameterInfo)));
1596 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1598 while ( lpArgTypeDesc != NULL )
1600 switch ( lpArgTypeDesc->vt )
1603 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1607 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1610 case VT_USERDEFINED:
1611 MSFT_DoRefType(pcx, pTI,
1612 lpArgTypeDesc->u.hreftype);
1614 lpArgTypeDesc = NULL;
1618 lpArgTypeDesc = NULL;
1624 /* parameter is the return value! */
1625 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1627 TYPEDESC* lpArgTypeDesc;
1629 (*pptfd)->funcdesc.elemdescFunc =
1630 (*pptfd)->funcdesc.lprgelemdescParam[j];
1632 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1634 while ( lpArgTypeDesc != NULL )
1636 switch ( lpArgTypeDesc->vt )
1639 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1643 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1647 case VT_USERDEFINED:
1650 lpArgTypeDesc->u.hreftype);
1652 lpArgTypeDesc = NULL;
1656 lpArgTypeDesc = NULL;
1661 /* second time around */
1662 for(j=0;j<pFuncRec->nrargs;j++)
1665 (*pptfd)->pParamDesc[j].Name =
1666 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1669 if ( (PARAMFLAG_FHASDEFAULT &
1670 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1671 ((pFuncRec->FKCCIC) & 0x1000) )
1673 INT* pInt = (INT *)((char *)pFuncRec +
1675 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1677 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1679 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1680 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1682 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1686 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1689 pFuncRec->OptAttr[7+j],
1690 &(*pptfd)->pParamDesc[j].pCustData);
1695 /* scode is not used: archaic win16 stuff FIXME: right? */
1696 (*pptfd)->funcdesc.cScodes = 0 ;
1697 (*pptfd)->funcdesc.lprgscode = NULL ;
1699 pptfd = & ((*pptfd)->next);
1700 recoffset += reclength;
1703 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1704 int cVars, int offset, TLBVarDesc ** pptvd)
1706 int infolen, nameoffset, reclength;
1708 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1712 TRACE_(typelib)("\n");
1714 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1715 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1716 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1717 recoffset += offset+sizeof(INT);
1718 for(i=0;i<cVars;i++){
1719 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1720 /* name, eventually add to a hash table */
1721 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1722 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1723 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1724 /* read the variable information record */
1725 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1727 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1729 if(reclength >(6*sizeof(INT)) )
1730 (*pptvd)->HelpContext=pVarRec->HelpContext;
1731 if(reclength >(7*sizeof(INT)) )
1732 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1733 if(reclength >(8*sizeof(INT)) )
1734 if(reclength >(9*sizeof(INT)) )
1735 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1736 /* fill the VarDesc Structure */
1737 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1738 offset + infolen + ( i + 1) * sizeof(INT));
1739 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1740 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1741 MSFT_GetTdesc(pcx, pVarRec->DataType,
1742 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1743 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1744 if(pVarRec->VarKind == VAR_CONST ){
1745 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1746 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1747 pVarRec->OffsValue, pcx);
1749 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1750 pptvd=&((*pptvd)->next);
1751 recoffset += reclength;
1754 /* fill in data for a hreftype (offset). When the refernced type is contained
1755 * in the typelib, it's just an (file) offset in the type info base dir.
1756 * If comes from import, it's an offset+1 in the ImpInfo table
1758 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1762 TLBRefType **ppRefType = &pTI->reflist;
1764 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1767 if((*ppRefType)->reference == offset)
1769 ppRefType = &(*ppRefType)->next;
1772 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1773 sizeof(**ppRefType));
1775 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1776 /* external typelib */
1777 MSFT_ImpInfo impinfo;
1778 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1780 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1782 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1783 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1784 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1785 if(pImpLib->offset==impinfo.oImpFile) break;
1786 pImpLib=pImpLib->next;
1789 (*ppRefType)->reference=offset;
1790 (*ppRefType)->pImpTLInfo = pImpLib;
1791 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1792 (*ppRefType)->index = TLB_REF_USE_GUID;
1794 ERR("Cannot find a reference\n");
1795 (*ppRefType)->reference=-1;
1796 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1799 /* in this typelib */
1800 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1801 (*ppRefType)->reference=offset;
1802 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1806 /* process Implemented Interfaces of a com class */
1807 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1811 MSFT_RefRecord refrec;
1812 TLBImplType **ppImpl = &pTI->impltypelist;
1814 TRACE_(typelib)("\n");
1816 for(i=0;i<count;i++){
1817 if(offset<0) break; /* paranoia */
1818 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1819 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1820 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1821 (*ppImpl)->hRef = refrec.reftype;
1822 (*ppImpl)->implflags=refrec.flags;
1823 (*ppImpl)->ctCustData=
1824 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1825 offset=refrec.onext;
1826 ppImpl=&((*ppImpl)->next);
1830 * process a typeinfo record
1832 ITypeInfoImpl * MSFT_DoTypeInfo(
1835 ITypeLibImpl * pLibInfo)
1837 MSFT_TypeInfoBase tiBase;
1838 ITypeInfoImpl *ptiRet;
1840 TRACE_(typelib)("count=%u\n", count);
1842 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1843 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1844 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1845 /* this is where we are coming from */
1846 ptiRet->pTypeLib = pLibInfo;
1847 ptiRet->index=count;
1848 /* fill in the typeattr fields */
1849 FIXME("Assign constructor/destructor memid\n");
1851 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1852 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1853 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1854 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1855 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1856 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1857 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1858 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1859 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1860 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1861 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1862 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1863 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1864 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1865 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1866 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1867 MSFT_GetTdesc(pcx, tiBase.datatype1,
1868 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1871 /* IDLDESC idldescType; *//* never saw this one != zero */
1873 /* name, eventually add to a hash table */
1874 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1875 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1877 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1878 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1879 ptiRet->dwHelpContext=tiBase.helpcontext;
1880 /* note: InfoType's Help file and HelpStringDll come from the containing
1881 * library. Further HelpString and Docstring appear to be the same thing :(
1884 if(ptiRet->TypeAttr.cFuncs >0 )
1885 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1886 ptiRet->TypeAttr.cVars,
1887 tiBase.memoffset, & ptiRet->funclist);
1889 if(ptiRet->TypeAttr.cVars >0 )
1890 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1891 ptiRet->TypeAttr.cVars,
1892 tiBase.memoffset, & ptiRet->varlist);
1893 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1894 switch(ptiRet->TypeAttr.typekind)
1897 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1900 case TKIND_DISPATCH:
1901 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1903 if (tiBase.datatype1 != -1)
1905 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1906 ptiRet->impltypelist->hRef = tiBase.datatype1;
1909 { /* FIXME: This is a really bad hack to add IDispatch */
1910 char* szStdOle = "stdole2.tlb\0";
1911 int nStdOleLen = strlen(szStdOle);
1912 TLBRefType **ppRef = &ptiRet->reflist;
1915 if((*ppRef)->reference == -1)
1917 ppRef = &(*ppRef)->next;
1920 *ppRef = TLB_Alloc(sizeof(**ppRef));
1921 (*ppRef)->guid = IID_IDispatch;
1922 (*ppRef)->reference = -1;
1923 (*ppRef)->index = TLB_REF_USE_GUID;
1924 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1925 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1926 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1929 MultiByteToWideChar(CP_ACP,
1933 (*ppRef)->pImpTLInfo->name,
1934 SysStringLen((*ppRef)->pImpTLInfo->name));
1936 (*ppRef)->pImpTLInfo->lcid = 0;
1937 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1938 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1943 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1944 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1945 ptiRet->impltypelist->hRef = tiBase.datatype1;
1950 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1952 TRACE_(typelib)("%s guid: %s kind:%s\n",
1953 debugstr_w(ptiRet->Name),
1954 debugstr_guid(&ptiRet->TypeAttr.guid),
1955 typekind_desc[ptiRet->TypeAttr.typekind]);
1960 /****************************************************************************
1963 * find the type of the typelib file and map the typelib resource into
1966 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1967 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1968 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1970 int ret = TYPE_E_CANTLOADLIBRARY;
1971 DWORD dwSignature = 0;
1974 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1978 /* check the signature of the file */
1979 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1980 if (INVALID_HANDLE_VALUE != hFile)
1982 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1985 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1988 /* retrieve file size */
1989 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1991 /* first try to load as *.tlb */
1992 dwSignature = FromLEDWord(*((DWORD*) pBase));
1993 if ( dwSignature == MSFT_SIGNATURE)
1995 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1997 else if ( dwSignature == SLTG_SIGNATURE)
1999 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2001 UnmapViewOfFile(pBase);
2003 CloseHandle(hMapping);
2008 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2010 /* find the typelibrary resource*/
2011 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2012 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2015 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2019 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2022 LPVOID pBase = LockResource(hGlobal);
2023 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2027 /* try to load as incore resource */
2028 dwSignature = FromLEDWord(*((DWORD*) pBase));
2029 if ( dwSignature == MSFT_SIGNATURE)
2031 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2033 else if ( dwSignature == SLTG_SIGNATURE)
2035 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2039 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2042 FreeResource( hGlobal );
2045 FreeLibrary(hinstDLL);
2052 ERR("Loading of typelib %s failed with error %ld\n",
2053 debugstr_w(pszFileName), GetLastError());
2058 /*================== ITypeLib(2) Methods ===================================*/
2060 /****************************************************************************
2061 * ITypeLib2_Constructor_MSFT
2063 * loading an MSFT typelib from an in-memory image
2065 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2069 MSFT_Header tlbHeader;
2070 MSFT_SegDir tlbSegDir;
2071 ITypeLibImpl * pTypeLibImpl;
2073 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2075 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2076 if (!pTypeLibImpl) return NULL;
2078 pTypeLibImpl->lpVtbl = &tlbvt;
2079 pTypeLibImpl->ref = 1;
2081 /* get pointer to beginning of typelib data */
2085 cx.pLibInfo = pTypeLibImpl;
2086 cx.length = dwTLBLength;
2089 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2091 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2092 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2093 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2096 /* there is a small amount of information here until the next important
2098 * the segment directory . Try to calculate the amount of data */
2099 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2101 /* now read the segment directory */
2102 TRACE("read segment directory (at %ld)\n",lPSegDir);
2103 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2104 cx.pTblDir = &tlbSegDir;
2106 /* just check two entries */
2107 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2109 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2110 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2114 /* now fill our internal data */
2115 /* TLIBATTR fields */
2116 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2118 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2119 /* Windows seems to have zero here, is this correct? */
2120 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2121 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2123 pTypeLibImpl->LibAttr.lcid = 0;
2125 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2126 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2127 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2128 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2130 /* name, eventually add to a hash table */
2131 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2134 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2135 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2137 if( tlbHeader.varflags & HELPDLLFLAG)
2140 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2141 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2144 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2147 if(tlbHeader.CustomDataOffset >= 0)
2149 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2152 /* fill in typedescriptions */
2153 if(tlbSegDir.pTypdescTab.length > 0)
2155 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2157 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2158 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2161 /* FIXME: add several sanity checks here */
2162 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2163 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2165 /* FIXME: check safearray */
2167 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2169 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2171 else if(td[0] == VT_CARRAY)
2173 /* array descr table here */
2174 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2176 else if(td[0] == VT_USERDEFINED)
2178 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2180 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2183 /* second time around to fill the array subscript info */
2186 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2187 if(tlbSegDir.pArrayDescriptions.offset>0)
2189 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2190 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2193 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2195 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2197 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2199 for(j = 0; j<td[2]; j++)
2201 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2202 sizeof(INT), &cx, DO_NOT_SEEK);
2203 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2204 sizeof(INT), &cx, DO_NOT_SEEK);
2209 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2210 ERR("didn't find array description data\n");
2215 /* imported type libs */
2216 if(tlbSegDir.pImpFiles.offset>0)
2218 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2219 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2222 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2224 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2225 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2226 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2228 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2229 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2230 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2231 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2234 (*ppImpLib)->name = TLB_Alloc(size+1);
2235 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2236 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2237 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2239 ppImpLib = &(*ppImpLib)->next;
2244 if(tlbHeader.nrtypeinfos >= 0 )
2246 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2247 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2250 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2252 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2254 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2255 ppTI = &((*ppTI)->next);
2256 (pTypeLibImpl->TypeInfoCount)++;
2260 TRACE("(%p)\n", pTypeLibImpl);
2261 return (ITypeLib2*) pTypeLibImpl;
2265 static BSTR TLB_MultiByteToBSTR(char *ptr)
2271 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2272 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2273 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2274 ret = SysAllocString(nameW);
2275 HeapFree(GetProcessHeap(), 0, nameW);
2279 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2285 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2286 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2290 guid->Data4[0] = s >> 8;
2291 guid->Data4[1] = s & 0xff;
2294 for(i = 0; i < 6; i++) {
2295 memcpy(b, str + 24 + 2 * i, 2);
2296 guid->Data4[i + 2] = strtol(b, NULL, 16);
2301 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2308 bytelen = *(WORD*)ptr;
2309 if(bytelen == 0xffff) return 2;
2310 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2311 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2312 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2313 *pBstr = SysAllocStringLen(nameW, len);
2314 HeapFree(GetProcessHeap(), 0, nameW);
2318 static WORD SLTG_ReadStringA(char *ptr, char **str)
2323 bytelen = *(WORD*)ptr;
2324 if(bytelen == 0xffff) return 2;
2325 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2326 memcpy(*str, ptr + 2, bytelen);
2327 (*str)[bytelen] = '\0';
2331 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2333 char *ptr = pLibBlk;
2336 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2337 FIXME("libblk magic = %04x\n", w);
2342 if((w = *(WORD*)ptr) != 0xffff) {
2343 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2348 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2350 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2352 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2355 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2358 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2361 ptr += 4; /* skip res12 */
2363 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2366 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2369 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2372 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2373 ptr += sizeof(GUID);
2375 return ptr - (char*)pLibBlk;
2378 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2381 TYPEDESC *pTD = &pElem->tdesc;
2383 /* Handle [in/out] first */
2384 if((*pType & 0xc000) == 0xc000)
2385 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2386 else if(*pType & 0x8000)
2387 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2388 else if(*pType & 0x4000)
2389 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2391 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2394 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2397 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2400 if((*pType & 0xe00) == 0xe00) {
2402 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2404 pTD = pTD->u.lptdesc;
2406 switch(*pType & 0x7f) {
2409 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2411 pTD = pTD->u.lptdesc;
2414 case VT_USERDEFINED:
2415 pTD->vt = VT_USERDEFINED;
2416 pTD->u.hreftype = *(++pType) / 4;
2422 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2425 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2427 pTD->vt = VT_CARRAY;
2428 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2430 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2431 pTD->u.lpadesc->cDims = pSA->cDims;
2432 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2433 pSA->cDims * sizeof(SAFEARRAYBOUND));
2435 pTD = &pTD->u.lpadesc->tdescElem;
2441 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2445 pTD->vt = VT_SAFEARRAY;
2446 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2448 pTD = pTD->u.lptdesc;
2452 pTD->vt = *pType & 0x7f;
2462 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2467 TLBRefType **ppRefType;
2469 if(pRef->magic != SLTG_REF_MAGIC) {
2470 FIXME("Ref magic = %x\n", pRef->magic);
2473 name = ( (char*)(&pRef->names) + pRef->number);
2475 ppRefType = &pTI->reflist;
2476 for(ref = 0; ref < pRef->number >> 3; ref++) {
2478 unsigned int lib_offs, type_num;
2480 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2481 sizeof(**ppRefType));
2483 name += SLTG_ReadStringA(name, &refname);
2484 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2485 FIXME("Can't sscanf ref\n");
2486 if(lib_offs != 0xffff) {
2487 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2490 if((*import)->offset == lib_offs)
2492 import = &(*import)->next;
2495 char fname[MAX_PATH+1];
2498 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2500 (*import)->offset = lib_offs;
2501 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2503 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2504 &(*import)->wVersionMajor,
2505 &(*import)->wVersionMinor,
2506 &(*import)->lcid, fname) != 4) {
2507 FIXME("can't sscanf ref %s\n",
2508 pNameTable + lib_offs + 40);
2510 len = strlen(fname);
2511 if(fname[len-1] != '#')
2512 FIXME("fname = %s\n", fname);
2513 fname[len-1] = '\0';
2514 (*import)->name = TLB_MultiByteToBSTR(fname);
2516 (*ppRefType)->pImpTLInfo = *import;
2517 } else { /* internal ref */
2518 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2520 (*ppRefType)->reference = ref;
2521 (*ppRefType)->index = type_num;
2523 HeapFree(GetProcessHeap(), 0, refname);
2524 ppRefType = &(*ppRefType)->next;
2526 if((BYTE)*name != SLTG_REF_MAGIC)
2527 FIXME("End of ref block magic = %x\n", *name);
2528 dump_TLBRefType(pTI->reflist);
2531 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2534 SLTG_ImplInfo *info;
2535 TLBImplType **ppImplType = &pTI->impltypelist;
2536 /* I don't really get this structure, usually it's 0x16 bytes
2537 long, but iuser.tlb contains some that are 0x18 bytes long.
2538 That's ok because we can use the next ptr to jump to the next
2539 one. But how do we know the length of the last one? The WORD
2540 at offs 0x8 might be the clue. For now I'm just assuming that
2541 the last one is the regular 0x16 bytes. */
2543 info = (SLTG_ImplInfo*)pBlk;
2545 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2546 sizeof(**ppImplType));
2547 (*ppImplType)->hRef = info->ref;
2548 (*ppImplType)->implflags = info->impltypeflags;
2549 pTI->TypeAttr.cImplTypes++;
2550 ppImplType = &(*ppImplType)->next;
2552 if(info->next == 0xffff)
2555 FIXME("Interface inheriting more than one interface\n");
2556 info = (SLTG_ImplInfo*)(pBlk + info->next);
2558 info++; /* see comment at top of function */
2562 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2565 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2566 SLTG_MemberHeader *pMemHeader;
2567 char *pFirstItem, *pNextItem;
2569 if(pTIHeader->href_table != 0xffffffff) {
2570 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2575 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2577 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2579 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2580 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2583 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2587 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2590 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2591 SLTG_MemberHeader *pMemHeader;
2592 SLTG_Function *pFunc;
2593 char *pFirstItem, *pNextItem;
2594 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2597 if(pTIHeader->href_table != 0xffffffff) {
2598 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2602 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2604 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2606 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2607 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2610 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2611 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2616 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2617 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2618 FIXME("func magic = %02x\n", pFunc->magic);
2621 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2622 sizeof(**ppFuncDesc));
2623 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2625 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2626 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2627 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2628 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2629 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2630 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2632 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2633 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2635 if(pFunc->retnextopt & 0x80)
2636 pType = &pFunc->rettype;
2638 pType = (WORD*)(pFirstItem + pFunc->rettype);
2641 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2643 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2644 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2645 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2646 (*ppFuncDesc)->pParamDesc =
2647 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2648 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2650 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2652 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2653 char *paramName = pNameTable + *pArg;
2655 /* If arg type follows then paramName points to the 2nd
2656 letter of the name, else the next WORD is an offset to
2657 the arg type and paramName points to the first letter.
2658 So let's take one char off paramName and see if we're
2659 pointing at an alpha-numeric char. However if *pArg is
2660 0xffff or 0xfffe then the param has no name, the former
2661 meaning that the next WORD is the type, the latter
2662 meaning the the next WORD is an offset to the type. */
2667 else if(*pArg == 0xfffe) {
2671 else if(!isalnum(*(paramName-1)))
2676 if(HaveOffs) { /* the next word is an offset to type */
2677 pType = (WORD*)(pFirstItem + *pArg);
2678 SLTG_DoType(pType, pFirstItem,
2679 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2684 pArg = SLTG_DoType(pArg, pFirstItem,
2685 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2688 /* Are we an optional param ? */
2689 if((*ppFuncDesc)->funcdesc.cParams - param <=
2690 (*ppFuncDesc)->funcdesc.cParamsOpt)
2691 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2694 (*ppFuncDesc)->pParamDesc[param].Name =
2695 TLB_MultiByteToBSTR(paramName);
2699 ppFuncDesc = &((*ppFuncDesc)->next);
2700 if(pFunc->next == 0xffff) break;
2702 pTI->TypeAttr.cFuncs = num;
2703 dump_TLBFuncDesc(pTI->funclist);
2704 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2707 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2710 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2711 SLTG_MemberHeader *pMemHeader;
2712 SLTG_RecordItem *pItem;
2714 TLBVarDesc **ppVarDesc = &pTI->varlist;
2719 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2721 pFirstItem = (char*)(pMemHeader + 1);
2722 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2723 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2724 if(pItem->magic != SLTG_RECORD_MAGIC) {
2725 FIXME("record magic = %02x\n", pItem->magic);
2728 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2729 sizeof(**ppVarDesc));
2730 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2731 (*ppVarDesc)->vardesc.memid = pItem->memid;
2732 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2733 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2735 if(pItem->typepos == 0x02)
2736 pType = &pItem->type;
2737 else if(pItem->typepos == 0x00)
2738 pType = (WORD*)(pFirstItem + pItem->type);
2740 FIXME("typepos = %02x\n", pItem->typepos);
2744 SLTG_DoType(pType, pFirstItem,
2745 &(*ppVarDesc)->vardesc.elemdescVar);
2747 /* FIXME("helpcontext, helpstring\n"); */
2749 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2751 ppVarDesc = &((*ppVarDesc)->next);
2752 if(pItem->next == 0xffff) break;
2754 pTI->TypeAttr.cVars = num;
2755 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2758 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2761 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2762 SLTG_MemberHeader *pMemHeader;
2763 SLTG_AliasItem *pItem;
2766 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2767 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2770 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2771 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2772 if (pItem->vt == 0xffff) {
2773 if (i<(pMemHeader->cbExtra/4-1))
2774 FIXME("Endmarker too early in process alias data!\n");
2778 FIXME("Chain extends over last entry?\n");
2781 if (pItem->vt == VT_USERDEFINED) {
2782 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2783 /* guessing here ... */
2784 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2785 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2788 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2789 FIXME("alias %d: 0x%x\n",i,pItem->res02);
2793 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2796 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
2799 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2800 SLTG_MemberHeader *pMemHeader;
2801 SLTG_AliasItem *pItem;
2803 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2804 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2805 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
2806 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
2807 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2810 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2813 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2814 SLTG_MemberHeader *pMemHeader;
2815 SLTG_EnumItem *pItem;
2817 TLBVarDesc **ppVarDesc = &pTI->varlist;
2820 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2822 pFirstItem = (char*)(pMemHeader + 1);
2823 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2824 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2825 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2826 FIXME("enumitem magic = %04x\n", pItem->magic);
2829 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2830 sizeof(**ppVarDesc));
2831 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2832 (*ppVarDesc)->vardesc.memid = pItem->memid;
2833 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2835 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2836 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2837 *(INT*)(pItem->value + pFirstItem);
2838 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2839 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2840 /* FIXME("helpcontext, helpstring\n"); */
2842 ppVarDesc = &((*ppVarDesc)->next);
2843 if(pItem->next == 0xffff) break;
2845 pTI->TypeAttr.cVars = num;
2846 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2849 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2850 managable copy of it into this */
2863 } SLTG_InternalOtherTypeInfo;
2865 /****************************************************************************
2866 * ITypeLib2_Constructor_SLTG
2868 * loading a SLTG typelib from an in-memory image
2870 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2872 ITypeLibImpl *pTypeLibImpl;
2873 SLTG_Header *pHeader;
2874 SLTG_BlkEntry *pBlkEntry;
2878 LPVOID pBlk, pFirstBlk;
2879 SLTG_LibBlk *pLibBlk;
2880 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2881 char *pAfterOTIBlks = NULL;
2882 char *pNameTable, *ptr;
2885 ITypeInfoImpl **ppTypeInfoImpl;
2887 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2889 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2890 if (!pTypeLibImpl) return NULL;
2892 pTypeLibImpl->lpVtbl = &tlbvt;
2893 pTypeLibImpl->ref = 1;
2898 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2899 pHeader->nrOfFileBlks );
2900 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2901 FIXME("Header type magic 0x%08lx not supported.\n",
2902 pHeader->SLTG_magic);
2906 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2907 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2909 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2910 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2912 /* Next we have a magic block */
2913 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2915 /* Let's see if we're still in sync */
2916 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2917 sizeof(SLTG_COMPOBJ_MAGIC))) {
2918 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2921 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2922 sizeof(SLTG_DIR_MAGIC))) {
2923 FIXME("dir magic = %s\n", pMagic->dir_magic);
2927 pIndex = (SLTG_Index*)(pMagic+1);
2929 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2931 pFirstBlk = (LPVOID)(pPad9 + 1);
2933 /* We'll set up a ptr to the main library block, which is the last one. */
2935 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2936 pBlkEntry[order].next != 0;
2937 order = pBlkEntry[order].next - 1, i++) {
2938 pBlk = (char*)pBlk + pBlkEntry[order].len;
2942 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2944 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2949 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2951 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2952 sizeof(*pOtherTypeInfoBlks) *
2953 pTypeLibImpl->TypeInfoCount);
2956 ptr = (char*)pLibBlk + len;
2958 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2962 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2964 w = *(WORD*)(ptr + 2);
2967 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2969 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2970 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2972 w = *(WORD*)(ptr + 4 + len);
2974 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2976 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2978 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2979 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2981 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2982 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2983 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2985 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2987 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2990 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2991 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2992 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2993 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2994 len += sizeof(SLTG_OtherTypeInfo);
2998 pAfterOTIBlks = ptr;
3000 /* Skip this WORD and get the next DWORD */
3001 len = *(DWORD*)(pAfterOTIBlks + 2);
3003 /* Now add this to pLibBLk look at what we're pointing at and
3004 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3005 dust and we should be pointing at the beginning of the name
3008 pNameTable = (char*)pLibBlk + len;
3010 switch(*(WORD*)pNameTable) {
3017 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3021 pNameTable += 0x216;
3025 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3027 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3030 /* Hopefully we now have enough ptrs set up to actually read in
3031 some TypeInfos. It's not clear which order to do them in, so
3032 I'll just follow the links along the BlkEntry chain and read
3033 them in in the order in which they're in the file */
3035 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3037 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3038 pBlkEntry[order].next != 0;
3039 order = pBlkEntry[order].next - 1, i++) {
3041 SLTG_TypeInfoHeader *pTIHeader;
3042 SLTG_TypeInfoTail *pTITail;
3044 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3045 pOtherTypeInfoBlks[i].index_name)) {
3046 FIXME("Index strings don't match\n");
3051 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3052 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3055 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3056 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3057 (*ppTypeInfoImpl)->index = i;
3058 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3059 pOtherTypeInfoBlks[i].name_offs +
3061 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3062 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3064 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3065 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3066 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3067 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3068 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3070 if((pTIHeader->typeflags1 & 7) != 2)
3071 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3072 if(pTIHeader->typeflags3 != 2)
3073 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3075 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3076 debugstr_w((*ppTypeInfoImpl)->Name),
3077 typekind_desc[pTIHeader->typekind],
3078 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3079 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3081 switch(pTIHeader->typekind) {
3083 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3087 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3090 case TKIND_INTERFACE:
3091 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3095 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3099 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3100 if (pTITail->tdescalias_vt)
3101 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3104 case TKIND_DISPATCH:
3105 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3109 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3115 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3116 but we've already set those */
3117 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3118 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3119 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3121 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3143 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3144 pBlk = (char*)pBlk + pBlkEntry[order].len;
3147 if(i != pTypeLibImpl->TypeInfoCount) {
3148 FIXME("Somehow processed %d TypeInfos\n", i);
3152 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3153 return (ITypeLib2*)pTypeLibImpl;
3156 /* ITypeLib::QueryInterface
3158 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3163 ICOM_THIS( ITypeLibImpl, iface);
3165 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3168 if(IsEqualIID(riid, &IID_IUnknown) ||
3169 IsEqualIID(riid,&IID_ITypeLib)||
3170 IsEqualIID(riid,&IID_ITypeLib2))
3177 ITypeLib2_AddRef(iface);
3178 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3181 TRACE("-- Interface: E_NOINTERFACE\n");
3182 return E_NOINTERFACE;
3187 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3189 ICOM_THIS( ITypeLibImpl, iface);
3191 TRACE("(%p)->ref is %u\n",This, This->ref);
3193 return ++(This->ref);
3196 /* ITypeLib::Release
3198 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3200 ICOM_THIS( ITypeLibImpl, iface);
3204 TRACE("(%p)->(%u)\n",This, This->ref);
3208 /* FIXME destroy child objects */
3210 TRACE(" destroying ITypeLib(%p)\n",This);
3214 SysFreeString(This->Name);
3218 if (This->DocString)
3220 SysFreeString(This->DocString);
3221 This->DocString = NULL;
3226 SysFreeString(This->HelpFile);
3227 This->HelpFile = NULL;
3230 if (This->HelpStringDll)
3232 SysFreeString(This->HelpStringDll);
3233 This->HelpStringDll = NULL;
3236 if (This->pTypeInfo) /* can be NULL */
3237 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3238 HeapFree(GetProcessHeap(),0,This);
3245 /* ITypeLib::GetTypeInfoCount
3247 * Returns the number of type descriptions in the type library
3249 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3251 ICOM_THIS( ITypeLibImpl, iface);
3252 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3253 return This->TypeInfoCount;
3256 /* ITypeLib::GetTypeInfo
3258 * retrieves the specified type description in the library.
3260 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3263 ITypeInfo **ppTInfo)
3267 ICOM_THIS( ITypeLibImpl, iface);
3268 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3270 TRACE("(%p)->(index=%d) \n", This, index);
3272 if (!ppTInfo) return E_INVALIDARG;
3274 /* search element n in list */
3275 for(i=0; i < index; i++)
3277 pTypeInfo = pTypeInfo->next;
3280 TRACE("-- element not found\n");
3281 return TYPE_E_ELEMENTNOTFOUND;
3285 *ppTInfo = (ITypeInfo *) pTypeInfo;
3287 ITypeInfo_AddRef(*ppTInfo);
3288 TRACE("-- found (%p)\n",*ppTInfo);
3293 /* ITypeLibs::GetTypeInfoType
3295 * Retrieves the type of a type description.
3297 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3302 ICOM_THIS( ITypeLibImpl, iface);
3304 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3306 TRACE("(%p) index %d \n",This, index);
3308 if(!pTKind) return E_INVALIDARG;
3310 /* search element n in list */
3311 for(i=0; i < index; i++)
3315 TRACE("-- element not found\n");
3316 return TYPE_E_ELEMENTNOTFOUND;
3318 pTInfo = pTInfo->next;
3321 *pTKind = pTInfo->TypeAttr.typekind;
3322 TRACE("-- found Type (%d)\n", *pTKind);
3326 /* ITypeLib::GetTypeInfoOfGuid
3328 * Retrieves the type description that corresponds to the specified GUID.
3331 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3334 ITypeInfo **ppTInfo)
3336 ICOM_THIS( ITypeLibImpl, iface);
3337 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3339 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3341 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3343 /* search linked list for guid */
3344 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3346 pTypeInfo = pTypeInfo->next;
3350 /* end of list reached */
3351 TRACE("-- element not found\n");
3352 return TYPE_E_ELEMENTNOTFOUND;
3356 TRACE("-- found (%p, %s)\n",
3358 debugstr_w(pTypeInfo->Name));
3360 *ppTInfo = (ITypeInfo*)pTypeInfo;
3361 ITypeInfo_AddRef(*ppTInfo);
3365 /* ITypeLib::GetLibAttr
3367 * Retrieves the structure that contains the library's attributes.
3370 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3372 LPTLIBATTR *ppTLibAttr)
3374 ICOM_THIS( ITypeLibImpl, iface);
3375 TRACE("(%p)\n",This);
3376 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3377 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3381 /* ITypeLib::GetTypeComp
3383 * Enables a client compiler to bind to a library's types, variables,
3384 * constants, and global functions.
3387 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3389 ITypeComp **ppTComp)
3391 ICOM_THIS( ITypeLibImpl, iface);
3392 FIXME("(%p): stub!\n",This);
3396 /* ITypeLib::GetDocumentation
3398 * Retrieves the library's documentation string, the complete Help file name
3399 * and path, and the context identifier for the library Help topic in the Help
3402 * On a successful return all non-null BSTR pointers will have been set,
3405 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3409 BSTR *pBstrDocString,
3410 DWORD *pdwHelpContext,
3411 BSTR *pBstrHelpFile)
3413 ICOM_THIS( ITypeLibImpl, iface);
3415 HRESULT result = E_INVALIDARG;
3420 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3422 pBstrName, pBstrDocString,
3423 pdwHelpContext, pBstrHelpFile);
3427 /* documentation for the typelib */
3431 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3437 if (This->DocString)
3438 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3439 else if (This->Name)
3440 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3442 *pBstrDocString = NULL;
3446 *pdwHelpContext = This->dwHelpContext;
3451 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3453 *pBstrHelpFile = NULL;
3460 /* for a typeinfo */
3461 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3463 if(SUCCEEDED(result))
3465 result = ITypeInfo_GetDocumentation(pTInfo,
3469 pdwHelpContext, pBstrHelpFile);
3471 ITypeInfo_Release(pTInfo);
3476 if (pBstrDocString) SysFreeString (*pBstrDocString);
3478 if (pBstrName) SysFreeString (*pBstrName);
3480 return STG_E_INSUFFICIENTMEMORY;
3485 * Indicates whether a passed-in string contains the name of a type or member
3486 * described in the library.
3489 static HRESULT WINAPI ITypeLib2_fnIsName(
3495 ICOM_THIS( ITypeLibImpl, iface);
3496 ITypeInfoImpl *pTInfo;
3497 TLBFuncDesc *pFInfo;
3500 UINT nNameBufLen = SysStringLen(szNameBuf);
3502 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3506 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3507 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3508 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3509 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3510 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3511 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3512 goto ITypeLib2_fnIsName_exit;
3514 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3515 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3520 ITypeLib2_fnIsName_exit:
3521 TRACE("(%p)slow! search for %s: %s found!\n", This,
3522 debugstr_w(szNameBuf), *pfName?"NOT":"");
3527 /* ITypeLib::FindName
3529 * Finds occurrences of a type description in a type library. This may be used
3530 * to quickly verify that a name exists in a type library.
3533 static HRESULT WINAPI ITypeLib2_fnFindName(
3537 ITypeInfo **ppTInfo,
3541 ICOM_THIS( ITypeLibImpl, iface);
3542 ITypeInfoImpl *pTInfo;
3543 TLBFuncDesc *pFInfo;
3547 UINT nNameBufLen = SysStringLen(szNameBuf);
3549 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3550 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3551 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3552 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3553 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3554 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3555 goto ITypeLib2_fnFindName_exit;
3557 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3558 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3560 ITypeLib2_fnFindName_exit:
3561 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3562 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3565 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3566 This, *pcFound, debugstr_w(szNameBuf), j);
3573 /* ITypeLib::ReleaseTLibAttr
3575 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3578 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3580 TLIBATTR *pTLibAttr)
3582 ICOM_THIS( ITypeLibImpl, iface);
3583 TRACE("freeing (%p)\n",This);
3584 HeapFree(GetProcessHeap(),0,pTLibAttr);
3588 /* ITypeLib2::GetCustData
3590 * gets the custom data
3592 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3597 ICOM_THIS( ITypeLibImpl, iface);
3598 TLBCustData *pCData;
3600 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3602 if( IsEqualIID(guid, &pCData->guid)) break;
3605 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3609 VariantInit( pVarVal);
3610 VariantCopy( pVarVal, &pCData->data);
3613 return E_INVALIDARG; /* FIXME: correct? */
3616 /* ITypeLib2::GetLibStatistics
3618 * Returns statistics about a type library that are required for efficient
3619 * sizing of hash tables.
3622 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3624 ULONG *pcUniqueNames,
3625 ULONG *pcchUniqueNames)
3627 ICOM_THIS( ITypeLibImpl, iface);
3629 FIXME("(%p): stub!\n", This);
3631 if(pcUniqueNames) *pcUniqueNames=1;
3632 if(pcchUniqueNames) *pcchUniqueNames=1;
3636 /* ITypeLib2::GetDocumentation2
3638 * Retrieves the library's documentation string, the complete Help file name
3639 * and path, the localization context to use, and the context ID for the
3640 * library Help topic in the Help file.
3643 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3647 BSTR *pbstrHelpString,
3648 DWORD *pdwHelpStringContext,
3649 BSTR *pbstrHelpStringDll)
3651 ICOM_THIS( ITypeLibImpl, iface);
3655 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3657 /* the help string should be obtained from the helpstringdll,
3658 * using the _DLLGetDocumentation function, based on the supplied
3659 * lcid. Nice to do sometime...
3663 /* documentation for the typelib */
3665 *pbstrHelpString=SysAllocString(This->DocString);
3666 if(pdwHelpStringContext)
3667 *pdwHelpStringContext=This->dwHelpContext;
3668 if(pbstrHelpStringDll)
3669 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3675 /* for a typeinfo */
3676 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3678 if(SUCCEEDED(result))
3680 ITypeInfo2 * pTInfo2;
3681 result = ITypeInfo_QueryInterface(pTInfo,
3683 (LPVOID*) &pTInfo2);
3685 if(SUCCEEDED(result))
3687 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3691 pdwHelpStringContext,
3692 pbstrHelpStringDll);
3694 ITypeInfo2_Release(pTInfo2);
3697 ITypeInfo_Release(pTInfo);
3703 /* ITypeLib2::GetAllCustData
3705 * Gets all custom data items for the library.
3708 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3710 CUSTDATA *pCustData)
3712 ICOM_THIS( ITypeLibImpl, iface);
3713 TLBCustData *pCData;
3715 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3716 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3717 if(pCustData->prgCustData ){
3718 pCustData->cCustData=This->ctCustData;
3719 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3720 pCustData->prgCustData[i].guid=pCData->guid;
3721 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3724 ERR(" OUT OF MEMORY! \n");
3725 return E_OUTOFMEMORY;
3730 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3731 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3732 ITypeLib2_fnQueryInterface,
3734 ITypeLib2_fnRelease,
3735 ITypeLib2_fnGetTypeInfoCount,
3736 ITypeLib2_fnGetTypeInfo,
3737 ITypeLib2_fnGetTypeInfoType,
3738 ITypeLib2_fnGetTypeInfoOfGuid,
3739 ITypeLib2_fnGetLibAttr,
3740 ITypeLib2_fnGetTypeComp,
3741 ITypeLib2_fnGetDocumentation,
3743 ITypeLib2_fnFindName,
3744 ITypeLib2_fnReleaseTLibAttr,
3746 ITypeLib2_fnGetCustData,
3747 ITypeLib2_fnGetLibStatistics,
3748 ITypeLib2_fnGetDocumentation2,
3749 ITypeLib2_fnGetAllCustData
3752 /*================== ITypeInfo(2) Methods ===================================*/
3753 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3755 ITypeInfoImpl * pTypeInfoImpl;
3757 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3760 pTypeInfoImpl->lpVtbl = &tinfvt;
3761 pTypeInfoImpl->ref=1;
3763 TRACE("(%p)\n", pTypeInfoImpl);
3764 return (ITypeInfo2*) pTypeInfoImpl;
3767 /* ITypeInfo::QueryInterface
3769 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3774 ICOM_THIS( ITypeLibImpl, iface);
3776 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3779 if(IsEqualIID(riid, &IID_IUnknown) ||
3780 IsEqualIID(riid,&IID_ITypeInfo)||
3781 IsEqualIID(riid,&IID_ITypeInfo2))
3785 ITypeInfo_AddRef(iface);
3786 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3789 TRACE("-- Interface: E_NOINTERFACE\n");
3790 return E_NOINTERFACE;
3793 /* ITypeInfo::AddRef
3795 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3797 ICOM_THIS( ITypeInfoImpl, iface);
3801 TRACE("(%p)->ref is %u\n",This, This->ref);
3805 /* ITypeInfo::Release
3807 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3809 ICOM_THIS( ITypeInfoImpl, iface);
3813 TRACE("(%p)->(%u)\n",This, This->ref);
3817 FIXME("destroy child objects\n");
3819 TRACE("destroying ITypeInfo(%p)\n",This);
3822 SysFreeString(This->Name);
3826 if (This->DocString)
3828 SysFreeString(This->DocString);
3829 This->DocString = 0;
3834 ITypeInfo_Release((ITypeInfo*)This->next);
3837 HeapFree(GetProcessHeap(),0,This);
3843 /* ITypeInfo::GetTypeAttr
3845 * Retrieves a TYPEATTR structure that contains the attributes of the type
3849 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3850 LPTYPEATTR *ppTypeAttr)
3852 ICOM_THIS( ITypeInfoImpl, iface);
3853 TRACE("(%p)\n",This);
3854 /* FIXME: must do a copy here */
3855 *ppTypeAttr=&This->TypeAttr;
3859 /* ITypeInfo::GetTypeComp
3861 * Retrieves the ITypeComp interface for the type description, which enables a
3862 * client compiler to bind to the type description's members.
3865 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3866 ITypeComp * *ppTComp)
3868 ICOM_THIS( ITypeInfoImpl, iface);
3869 FIXME("(%p) stub!\n", This);
3873 /* ITypeInfo::GetFuncDesc
3875 * Retrieves the FUNCDESC structure that contains information about a
3876 * specified function.
3879 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3880 LPFUNCDESC *ppFuncDesc)
3882 ICOM_THIS( ITypeInfoImpl, iface);
3884 TLBFuncDesc * pFDesc;
3885 TRACE("(%p) index %d\n", This, index);
3886 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3889 /* FIXME: must do a copy here */
3890 *ppFuncDesc=&pFDesc->funcdesc;
3893 return E_INVALIDARG;
3896 /* ITypeInfo::GetVarDesc
3898 * Retrieves a VARDESC structure that describes the specified variable.
3901 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3902 LPVARDESC *ppVarDesc)
3904 ICOM_THIS( ITypeInfoImpl, iface);
3906 TLBVarDesc * pVDesc;
3907 TRACE("(%p) index %d\n", This, index);
3908 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3911 /* FIXME: must do a copy here */
3912 *ppVarDesc=&pVDesc->vardesc;
3915 return E_INVALIDARG;
3918 /* ITypeInfo_GetNames
3920 * Retrieves the variable with the specified member ID (or the name of the
3921 * property or method and its parameters) that correspond to the specified
3924 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3925 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3927 ICOM_THIS( ITypeInfoImpl, iface);
3928 TLBFuncDesc * pFDesc;
3929 TLBVarDesc * pVDesc;
3931 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3932 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3935 /* function found, now return function and parameter names */
3936 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3939 *rgBstrNames=SysAllocString(pFDesc->Name);
3941 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3947 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3950 *rgBstrNames=SysAllocString(pVDesc->Name);
3955 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3957 /* recursive search */
3960 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3962 if(SUCCEEDED(result))
3964 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3965 ITypeInfo_Release(pTInfo);
3968 WARN("Could not search inherited interface!\n");
3972 WARN("no names found\n");
3975 return TYPE_E_ELEMENTNOTFOUND;
3982 /* ITypeInfo::GetRefTypeOfImplType
3984 * If a type description describes a COM class, it retrieves the type
3985 * description of the implemented interface types. For an interface,
3986 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3990 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3995 ICOM_THIS( ITypeInfoImpl, iface);
3997 TLBImplType *pImpl = This->impltypelist;
3999 TRACE("(%p) index %d\n", This, index);
4000 if (TRACE_ON(ole)) dump_TypeInfo(This);
4004 /* only valid on dual interfaces;
4005 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4007 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4009 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4010 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4016 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4017 *pRefType = pImpl->hRef;
4022 /* get element n from linked list */
4023 for(i=0; pImpl && i<index; i++)
4025 pImpl = pImpl->next;
4028 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4030 *pRefType = pImpl->hRef;
4032 TRACE("-- 0x%08lx\n", pImpl->hRef );
4039 /* ITypeInfo::GetImplTypeFlags
4041 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4042 * or base interface in a type description.
4044 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4045 UINT index, INT *pImplTypeFlags)
4047 ICOM_THIS( ITypeInfoImpl, iface);
4051 TRACE("(%p) index %d\n", This, index);
4052 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4053 i++, pImpl=pImpl->next)
4055 if(i==index && pImpl){
4056 *pImplTypeFlags=pImpl->implflags;
4060 return TYPE_E_ELEMENTNOTFOUND;
4064 * Maps between member names and member IDs, and parameter names and
4067 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4068 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4070 ICOM_THIS( ITypeInfoImpl, iface);
4071 TLBFuncDesc * pFDesc;
4072 TLBVarDesc * pVDesc;
4075 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4077 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4079 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4080 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4081 for(i=1; i < cNames; i++){
4082 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4083 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4085 if( j<pFDesc->funcdesc.cParams)
4088 ret=DISP_E_UNKNOWNNAME;
4093 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4094 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4095 if(cNames) *pMemId=pVDesc->vardesc.memid;
4099 /* not found, see if this is and interface with an inheritance */
4100 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4101 This->TypeAttr.cImplTypes ){
4102 /* recursive search */
4104 ret=ITypeInfo_GetRefTypeInfo(iface,
4105 This->impltypelist->hRef, &pTInfo);
4107 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4108 ITypeInfo_Release(pTInfo);
4111 WARN("Could not search inherited interface!\n");
4113 WARN("no names found\n");
4114 return DISP_E_UNKNOWNNAME;
4117 /* ITypeInfo::Invoke
4119 * Invokes a method, or accesses a property of an object, that implements the
4120 * interface described by the type description.
4123 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4126 if (TRACE_ON(ole)) {
4128 TRACE("Calling %p(",func);
4129 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4141 res = func(args[0]);
4144 res = func(args[0],args[1]);
4147 res = func(args[0],args[1],args[2]);
4150 res = func(args[0],args[1],args[2],args[3]);
4153 res = func(args[0],args[1],args[2],args[3],args[4]);
4156 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4159 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4162 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4165 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4168 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4174 FIXME("unsupported calling convention %d\n",callconv);
4178 TRACE("returns %08lx\n",res);
4182 extern int const _argsize(DWORD vt);
4184 /****************************************************************************
4185 * Helper functions for Dispcall / Invoke, which copies one variant
4186 * with target type onto the argument stack.
4189 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4190 DWORD *argpos, VARIANT *arg, VARTYPE vt
4192 UINT arglen = _argsize(vt)*sizeof(DWORD);
4195 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4196 memcpy(argpos,&arg,sizeof(void*));
4200 if (V_VT(arg) == vt) {
4201 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4205 if (vt == VT_VARIANT) {
4206 memcpy(argpos, arg, arglen);
4209 /* Deref BYREF vars if there is need */
4210 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4211 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4214 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4215 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4216 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4219 if ((vt == VT_PTR) && tdesc)
4220 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4221 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4226 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4228 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing from vt 0x%x. Copying 4 byte.\n",tdesc->u.hreftype,V_VT(arg));
4229 memcpy(argpos, &V_UNION(arg,lVal), 4);
4232 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4233 switch (tattr->typekind) {
4235 if (V_VT(arg) == VT_I4) {
4236 memcpy(argpos, &V_UNION(arg,iVal), 4);
4239 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4242 tdesc = &(tattr->tdescAlias);
4243 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4244 ITypeInfo_Release(tinfo2);
4247 case TKIND_INTERFACE:
4248 if (V_VT(arg) == VT_DISPATCH) {
4250 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4251 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4254 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4255 if (SUCCEEDED(hres)) {
4256 memcpy(argpos,&disp,4);
4257 IUnknown_Release(V_UNION(arg,pdispVal));
4260 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4263 if (V_VT(arg) == VT_UNKNOWN) {
4264 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4267 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4269 case TKIND_DISPATCH:
4270 if (V_VT(arg) == VT_DISPATCH) {
4271 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4274 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4277 FIXME("TKIND_RECORD unhandled.\n");
4280 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4286 if (VariantChangeType(arg,arg,0,vt)==S_OK) {
4287 FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt, vt);
4288 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4291 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4295 /***********************************************************************
4296 * DispCallFunc (OLEAUT32.@)
4300 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4301 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4303 int i, argsize, argspos;
4307 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4308 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4310 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4311 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4313 for (i=0;i<cActuals;i++) {
4314 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4315 dump_Variant(prgpvarg[i]);
4316 argsize += _argsize(prgvt[i]);
4318 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4319 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4321 for (i=0;i<cActuals;i++) {
4322 VARIANT *arg = prgpvarg[i];
4323 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4324 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4325 argspos += _argsize(prgvt[i]);
4328 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4330 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4335 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4336 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4337 FIXME("Method returned %lx\n",hres);
4339 HeapFree(GetProcessHeap(),0,args);
4343 static HRESULT WINAPI ITypeInfo_fnInvoke(
4348 DISPPARAMS *pDispParams,
4349 VARIANT *pVarResult,
4350 EXCEPINFO *pExcepInfo,
4353 ICOM_THIS( ITypeInfoImpl, iface);
4354 TLBFuncDesc * pFDesc;
4355 TLBVarDesc * pVDesc;
4359 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4360 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4362 dump_DispParms(pDispParams);
4364 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4365 if (pFDesc->funcdesc.memid == memid) {
4366 if (pFDesc->funcdesc.invkind & dwFlags)
4370 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4371 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4372 switch (pFDesc->funcdesc.funckind) {
4373 case FUNC_PUREVIRTUAL:
4374 case FUNC_VIRTUAL: {
4376 int numargs, numargs2, argspos, args2pos;
4377 DWORD *args , *args2;
4380 numargs = 1; numargs2 = 0;
4381 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4382 if (i<pDispParams->cArgs)
4383 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4385 numargs += 1; /* sizeof(lpvoid) */
4386 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4390 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4391 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4393 args[0] = (DWORD)pIUnk;
4394 argspos = 1; args2pos = 0;
4395 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4396 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4397 if (i<pDispParams->cArgs) {
4398 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4399 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4400 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4401 if (FAILED(hres)) return hres;
4404 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4405 if (tdesc->vt != VT_PTR)
4406 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4407 /*FIXME: give pointers for the rest, so propertyget works*/
4408 args[argspos] = (DWORD)&args2[args2pos];
4410 /* If pointer to variant, pass reference it. */
4411 if ((tdesc->vt == VT_PTR) &&
4412 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4415 args[argspos]= (DWORD)pVarResult;
4420 if (pFDesc->funcdesc.cParamsOpt)
4421 FIXME("Does not support optional parameters (%d)\n",
4422 pFDesc->funcdesc.cParamsOpt
4425 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4426 pFDesc->funcdesc.callconv,
4430 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4432 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4433 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4434 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4435 /* If we are a pointer to a variant, we are done already */
4436 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4439 VariantInit(pVarResult);
4440 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4442 if (tdesc->vt == VT_PTR)
4443 tdesc = tdesc->u.lptdesc;
4444 if (tdesc->vt == VT_USERDEFINED) {
4448 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4450 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4453 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4454 switch (tattr->typekind) {
4456 FIXME("TKIND_ENUM unhandled.\n");
4459 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4460 tdesc = &(tattr->tdescAlias);
4463 case TKIND_INTERFACE:
4464 FIXME("TKIND_INTERFACE unhandled.\n");
4466 case TKIND_DISPATCH:
4467 FIXME("TKIND_DISPATCH unhandled.\n");
4470 FIXME("TKIND_RECORD unhandled.\n");
4473 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4476 ITypeInfo_Release(tinfo2);
4478 V_VT(pVarResult) = tdesc->vt;
4480 /* HACK: VB5 likes this.
4481 * I do not know why. There is 1 example in MSDN which uses
4482 * this which appears broken (mixes int vals and
4485 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4486 V_VT(pVarResult) = VT_DISPATCH;
4487 TRACE("storing into variant:\n");
4488 dump_Variant(pVarResult);
4492 HeapFree(GetProcessHeap(),0,args2);
4493 HeapFree(GetProcessHeap(),0,args);
4496 case FUNC_DISPATCH: {
4500 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4502 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4505 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4506 hr = IDispatch_Invoke(
4507 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4508 pVarResult,pExcepInfo,pArgErr
4511 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4512 IDispatch_Release(disp);
4516 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4520 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4521 if (pVDesc->vardesc.memid == memid) {
4522 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4523 dump_TLBVarDesc(pVDesc);
4528 /* not found, look for it in inherited interfaces */
4529 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4530 /* recursive search */
4533 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4535 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4536 ITypeInfo_Release(pTInfo);
4539 WARN("Could not search inherited interface!\n");
4541 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4542 return DISP_E_MEMBERNOTFOUND;
4545 /* ITypeInfo::GetDocumentation
4547 * Retrieves the documentation string, the complete Help file name and path,
4548 * and the context ID for the Help topic for a specified type description.
4550 * (Can be tested by the Visual Basic Editor in Word for instance.)
4552 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4553 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4554 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4556 ICOM_THIS( ITypeInfoImpl, iface);
4557 TLBFuncDesc * pFDesc;
4558 TLBVarDesc * pVDesc;
4559 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4560 " HelpContext(%p) HelpFile(%p)\n",
4561 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4562 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4564 *pBstrName=SysAllocString(This->Name);
4566 *pBstrDocString=SysAllocString(This->DocString);
4568 *pdwHelpContext=This->dwHelpContext;
4570 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4572 }else {/* for a member */
4573 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4574 if(pFDesc->funcdesc.memid==memid){
4576 *pBstrName = SysAllocString(pFDesc->Name);
4578 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4580 *pdwHelpContext=pFDesc->helpcontext;
4583 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4584 if(pVDesc->vardesc.memid==memid){
4586 *pBstrName = SysAllocString(pVDesc->Name);
4588 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4590 *pdwHelpContext=pVDesc->HelpContext;
4594 return TYPE_E_ELEMENTNOTFOUND;
4597 /* ITypeInfo::GetDllEntry
4599 * Retrieves a description or specification of an entry point for a function
4602 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4603 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4606 ICOM_THIS( ITypeInfoImpl, iface);
4607 TLBFuncDesc *pFDesc;
4609 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4611 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4612 if(pFDesc->funcdesc.memid==memid){
4613 dump_TypeInfo(This);
4614 dump_TLBFuncDescOne(pFDesc);
4616 /* FIXME: This is wrong, but how do you find that out? */
4618 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4619 *pBstrDllName = SysAllocString(oleaut32W);
4622 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4624 *pBstrName = SysAllocString(pFDesc->Entry);
4632 *pwOrdinal = (DWORD)pFDesc->Entry;
4638 /* ITypeInfo::GetRefTypeInfo
4640 * If a type description references other type descriptions, it retrieves
4641 * the referenced type descriptions.
4643 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4646 ITypeInfo **ppTInfo)
4648 ICOM_THIS( ITypeInfoImpl, iface);
4649 HRESULT result = E_FAIL;
4652 if (hRefType == -1 &&
4653 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4654 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4656 /* when we meet a DUAL dispinterface, we must create the interface
4659 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4662 /* the interface version contains the same information as the dispinterface
4663 * copy the contents of the structs.
4665 *pTypeInfoImpl = *This;
4666 pTypeInfoImpl->ref = 1;
4668 /* change the type to interface */
4669 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4671 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4673 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4678 TLBRefType *pRefType;
4679 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4680 if(pRefType->reference == hRefType)
4684 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4685 if(pRefType && hRefType != -1) {
4686 ITypeLib *pTLib = NULL;
4688 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4690 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4692 if(pRefType->pImpTLInfo->pImpTypeLib) {
4693 TRACE("typeinfo in imported typelib that is already loaded\n");
4694 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4695 ITypeLib2_AddRef((ITypeLib*) pTLib);
4698 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4699 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4700 pRefType->pImpTLInfo->wVersionMajor,
4701 pRefType->pImpTLInfo->wVersionMinor,
4702 pRefType->pImpTLInfo->lcid,
4705 if(!SUCCEEDED(result)) {
4706 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4707 result=LoadTypeLib(libnam, &pTLib);
4708 SysFreeString(libnam);
4710 if(SUCCEEDED(result)) {
4711 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4712 ITypeLib2_AddRef(pTLib);
4716 if(SUCCEEDED(result)) {
4717 if(pRefType->index == TLB_REF_USE_GUID)
4718 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4722 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4726 ITypeLib2_Release(pTLib);
4730 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4731 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4735 /* ITypeInfo::AddressOfMember
4737 * Retrieves the addresses of static functions or variables, such as those
4740 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4741 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4743 ICOM_THIS( ITypeInfoImpl, iface);
4744 FIXME("(%p) stub!\n", This);
4748 /* ITypeInfo::CreateInstance
4750 * Creates a new instance of a type that describes a component object class
4753 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4754 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4756 ICOM_THIS( ITypeInfoImpl, iface);
4757 FIXME("(%p) stub!\n", This);
4761 /* ITypeInfo::GetMops
4763 * Retrieves marshalling information.
4765 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4768 ICOM_THIS( ITypeInfoImpl, iface);
4769 FIXME("(%p) stub!\n", This);
4773 /* ITypeInfo::GetContainingTypeLib
4775 * Retrieves the containing type library and the index of the type description
4776 * within that type library.
4778 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4779 ITypeLib * *ppTLib, UINT *pIndex)
4781 ICOM_THIS( ITypeInfoImpl, iface);
4783 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
4785 *pIndex=This->index;
4786 TRACE("returning pIndex=%d", *pIndex);
4790 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4791 ITypeLib2_AddRef(*ppTLib);
4792 TRACE("returning ppTLib=%p", *ppTLib);
4798 /* ITypeInfo::ReleaseTypeAttr
4800 * Releases a TYPEATTR previously returned by GetTypeAttr.
4803 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4804 TYPEATTR* pTypeAttr)
4806 ICOM_THIS( ITypeInfoImpl, iface);
4807 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4810 /* ITypeInfo::ReleaseFuncDesc
4812 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4814 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
4816 FUNCDESC *pFuncDesc)
4818 ICOM_THIS( ITypeInfoImpl, iface);
4819 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4822 /* ITypeInfo::ReleaseVarDesc
4824 * Releases a VARDESC previously returned by GetVarDesc.
4826 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4829 ICOM_THIS( ITypeInfoImpl, iface);
4830 TRACE("(%p)->(%p)\n", This, pVarDesc);
4833 /* ITypeInfo2::GetTypeKind
4835 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4838 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4839 TYPEKIND *pTypeKind)
4841 ICOM_THIS( ITypeInfoImpl, iface);
4842 *pTypeKind=This->TypeAttr.typekind;
4843 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4847 /* ITypeInfo2::GetTypeFlags
4849 * Returns the type flags without any allocations. This returns a DWORD type
4850 * flag, which expands the type flags without growing the TYPEATTR (type
4854 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
4856 ICOM_THIS( ITypeInfoImpl, iface);
4857 *pTypeFlags=This->TypeAttr.wTypeFlags;
4858 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
4862 /* ITypeInfo2::GetFuncIndexOfMemId
4863 * Binds to a specific member based on a known DISPID, where the member name
4864 * is not known (for example, when binding to a default member).
4867 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4868 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4870 ICOM_THIS( ITypeInfoImpl, iface);
4871 TLBFuncDesc *pFuncInfo;
4874 /* FIXME: should check for invKind??? */
4875 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4876 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4882 result=E_INVALIDARG;
4884 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4885 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4889 /* TypeInfo2::GetVarIndexOfMemId
4891 * Binds to a specific member based on a known DISPID, where the member name
4892 * is not known (for example, when binding to a default member).
4895 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4896 MEMBERID memid, UINT *pVarIndex)
4898 ICOM_THIS( ITypeInfoImpl, iface);
4899 TLBVarDesc *pVarInfo;
4902 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4903 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4910 result=E_INVALIDARG;
4912 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4913 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4917 /* ITypeInfo2::GetCustData
4919 * Gets the custom data
4921 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4926 ICOM_THIS( ITypeInfoImpl, iface);
4927 TLBCustData *pCData;
4929 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4930 if( IsEqualIID(guid, &pCData->guid)) break;
4932 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4936 VariantInit( pVarVal);
4937 VariantCopy( pVarVal, &pCData->data);
4940 return E_INVALIDARG; /* FIXME: correct? */
4943 /* ITypeInfo2::GetFuncCustData
4945 * Gets the custom data
4947 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4953 ICOM_THIS( ITypeInfoImpl, iface);
4954 TLBCustData *pCData=NULL;
4955 TLBFuncDesc * pFDesc;
4957 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4958 pFDesc=pFDesc->next);
4961 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4962 if( IsEqualIID(guid, &pCData->guid)) break;
4964 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4967 VariantInit( pVarVal);
4968 VariantCopy( pVarVal, &pCData->data);
4971 return E_INVALIDARG; /* FIXME: correct? */
4974 /* ITypeInfo2::GetParamCustData
4976 * Gets the custom data
4978 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4985 ICOM_THIS( ITypeInfoImpl, iface);
4986 TLBCustData *pCData=NULL;
4987 TLBFuncDesc * pFDesc;
4990 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4992 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4993 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4994 pCData = pCData->next)
4995 if( IsEqualIID(guid, &pCData->guid)) break;
4997 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5001 VariantInit( pVarVal);
5002 VariantCopy( pVarVal, &pCData->data);
5005 return E_INVALIDARG; /* FIXME: correct? */
5008 /* ITypeInfo2::GetVarCustData
5010 * Gets the custom data
5012 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5018 ICOM_THIS( ITypeInfoImpl, iface);
5019 TLBCustData *pCData=NULL;
5020 TLBVarDesc * pVDesc;
5023 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5027 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5029 if( IsEqualIID(guid, &pCData->guid)) break;
5033 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5037 VariantInit( pVarVal);
5038 VariantCopy( pVarVal, &pCData->data);
5041 return E_INVALIDARG; /* FIXME: correct? */
5044 /* ITypeInfo2::GetImplCustData
5046 * Gets the custom data
5048 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5054 ICOM_THIS( ITypeInfoImpl, iface);
5055 TLBCustData *pCData=NULL;
5056 TLBImplType * pRDesc;
5059 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5063 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5065 if( IsEqualIID(guid, &pCData->guid)) break;
5069 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5073 VariantInit( pVarVal);
5074 VariantCopy( pVarVal, &pCData->data);
5077 return E_INVALIDARG; /* FIXME: correct? */
5080 /* ITypeInfo2::GetDocumentation2
5082 * Retrieves the documentation string, the complete Help file name and path,
5083 * the localization context to use, and the context ID for the library Help
5084 * topic in the Help file.
5087 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5091 BSTR *pbstrHelpString,
5092 DWORD *pdwHelpStringContext,
5093 BSTR *pbstrHelpStringDll)
5095 ICOM_THIS( ITypeInfoImpl, iface);
5096 TLBFuncDesc * pFDesc;
5097 TLBVarDesc * pVDesc;
5098 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5099 "HelpStringContext(%p) HelpStringDll(%p)\n",
5100 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5101 pbstrHelpStringDll );
5102 /* the help string should be obtained from the helpstringdll,
5103 * using the _DLLGetDocumentation function, based on the supplied
5104 * lcid. Nice to do sometime...
5106 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5108 *pbstrHelpString=SysAllocString(This->Name);
5109 if(pdwHelpStringContext)
5110 *pdwHelpStringContext=This->dwHelpStringContext;
5111 if(pbstrHelpStringDll)
5112 *pbstrHelpStringDll=
5113 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5115 }else {/* for a member */
5116 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5117 if(pFDesc->funcdesc.memid==memid){
5119 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5120 if(pdwHelpStringContext)
5121 *pdwHelpStringContext=pFDesc->HelpStringContext;
5122 if(pbstrHelpStringDll)
5123 *pbstrHelpStringDll=
5124 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5127 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5128 if(pVDesc->vardesc.memid==memid){
5130 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5131 if(pdwHelpStringContext)
5132 *pdwHelpStringContext=pVDesc->HelpStringContext;
5133 if(pbstrHelpStringDll)
5134 *pbstrHelpStringDll=
5135 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5139 return TYPE_E_ELEMENTNOTFOUND;
5142 /* ITypeInfo2::GetAllCustData
5144 * Gets all custom data items for the Type info.
5147 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5149 CUSTDATA *pCustData)
5151 ICOM_THIS( ITypeInfoImpl, iface);
5152 TLBCustData *pCData;
5155 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5157 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5158 if(pCustData->prgCustData ){
5159 pCustData->cCustData=This->ctCustData;
5160 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5161 pCustData->prgCustData[i].guid=pCData->guid;
5162 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5165 ERR(" OUT OF MEMORY! \n");
5166 return E_OUTOFMEMORY;
5171 /* ITypeInfo2::GetAllFuncCustData
5173 * Gets all custom data items for the specified Function
5176 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5179 CUSTDATA *pCustData)
5181 ICOM_THIS( ITypeInfoImpl, iface);
5182 TLBCustData *pCData;
5183 TLBFuncDesc * pFDesc;
5185 TRACE("(%p) index %d\n", This, index);
5186 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5187 pFDesc=pFDesc->next)
5190 pCustData->prgCustData =
5191 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5192 if(pCustData->prgCustData ){
5193 pCustData->cCustData=pFDesc->ctCustData;
5194 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5195 pCData = pCData->next){
5196 pCustData->prgCustData[i].guid=pCData->guid;
5197 VariantCopy(& pCustData->prgCustData[i].varValue,
5201 ERR(" OUT OF MEMORY! \n");
5202 return E_OUTOFMEMORY;
5206 return TYPE_E_ELEMENTNOTFOUND;
5209 /* ITypeInfo2::GetAllParamCustData
5211 * Gets all custom data items for the Functions
5214 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5215 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5217 ICOM_THIS( ITypeInfoImpl, iface);
5218 TLBCustData *pCData=NULL;
5219 TLBFuncDesc * pFDesc;
5221 TRACE("(%p) index %d\n", This, indexFunc);
5222 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5223 pFDesc=pFDesc->next)
5225 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5226 pCustData->prgCustData =
5227 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5228 sizeof(CUSTDATAITEM));
5229 if(pCustData->prgCustData ){
5230 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5231 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5232 pCData; i++, pCData = pCData->next){
5233 pCustData->prgCustData[i].guid=pCData->guid;
5234 VariantCopy(& pCustData->prgCustData[i].varValue,
5238 ERR(" OUT OF MEMORY! \n");
5239 return E_OUTOFMEMORY;
5243 return TYPE_E_ELEMENTNOTFOUND;
5246 /* ITypeInfo2::GetAllVarCustData
5248 * Gets all custom data items for the specified Variable
5251 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5252 UINT index, CUSTDATA *pCustData)
5254 ICOM_THIS( ITypeInfoImpl, iface);
5255 TLBCustData *pCData;
5256 TLBVarDesc * pVDesc;
5258 TRACE("(%p) index %d\n", This, index);
5259 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5260 pVDesc=pVDesc->next)
5263 pCustData->prgCustData =
5264 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5265 if(pCustData->prgCustData ){
5266 pCustData->cCustData=pVDesc->ctCustData;
5267 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5268 pCData = pCData->next){
5269 pCustData->prgCustData[i].guid=pCData->guid;
5270 VariantCopy(& pCustData->prgCustData[i].varValue,
5274 ERR(" OUT OF MEMORY! \n");
5275 return E_OUTOFMEMORY;
5279 return TYPE_E_ELEMENTNOTFOUND;
5282 /* ITypeInfo2::GetAllImplCustData
5284 * Gets all custom data items for the specified implementation type
5287 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5290 CUSTDATA *pCustData)
5292 ICOM_THIS( ITypeInfoImpl, iface);
5293 TLBCustData *pCData;
5294 TLBImplType * pRDesc;
5296 TRACE("(%p) index %d\n", This, index);
5297 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5298 pRDesc=pRDesc->next)
5301 pCustData->prgCustData =
5302 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5303 if(pCustData->prgCustData ){
5304 pCustData->cCustData=pRDesc->ctCustData;
5305 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5306 pCData = pCData->next){
5307 pCustData->prgCustData[i].guid=pCData->guid;
5308 VariantCopy(& pCustData->prgCustData[i].varValue,
5312 ERR(" OUT OF MEMORY! \n");
5313 return E_OUTOFMEMORY;
5317 return TYPE_E_ELEMENTNOTFOUND;
5320 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5322 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5324 ITypeInfo_fnQueryInterface,
5326 ITypeInfo_fnRelease,
5328 ITypeInfo_fnGetTypeAttr,
5329 ITypeInfo_fnGetTypeComp,
5330 ITypeInfo_fnGetFuncDesc,
5331 ITypeInfo_fnGetVarDesc,
5332 ITypeInfo_fnGetNames,
5333 ITypeInfo_fnGetRefTypeOfImplType,
5334 ITypeInfo_fnGetImplTypeFlags,
5335 ITypeInfo_fnGetIDsOfNames,
5337 ITypeInfo_fnGetDocumentation,
5338 ITypeInfo_fnGetDllEntry,
5339 ITypeInfo_fnGetRefTypeInfo,
5340 ITypeInfo_fnAddressOfMember,
5341 ITypeInfo_fnCreateInstance,
5342 ITypeInfo_fnGetMops,
5343 ITypeInfo_fnGetContainingTypeLib,
5344 ITypeInfo_fnReleaseTypeAttr,
5345 ITypeInfo_fnReleaseFuncDesc,
5346 ITypeInfo_fnReleaseVarDesc,
5348 ITypeInfo2_fnGetTypeKind,
5349 ITypeInfo2_fnGetTypeFlags,
5350 ITypeInfo2_fnGetFuncIndexOfMemId,
5351 ITypeInfo2_fnGetVarIndexOfMemId,
5352 ITypeInfo2_fnGetCustData,
5353 ITypeInfo2_fnGetFuncCustData,
5354 ITypeInfo2_fnGetParamCustData,
5355 ITypeInfo2_fnGetVarCustData,
5356 ITypeInfo2_fnGetImplTypeCustData,
5357 ITypeInfo2_fnGetDocumentation2,
5358 ITypeInfo2_fnGetAllCustData,
5359 ITypeInfo2_fnGetAllFuncCustData,
5360 ITypeInfo2_fnGetAllParamCustData,
5361 ITypeInfo2_fnGetAllVarCustData,
5362 ITypeInfo2_fnGetAllImplTypeCustData,