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];
287 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;
305 return TYPE_E_CANTLOADLIBRARY;
308 TRACE("File %s index %d\n", debugstr_w(szPath), index);
310 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
315 case REGKIND_DEFAULT:
316 /* FIXME: is this correct? */
317 if (!szFile || !szFile[0] ||
318 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
320 /* else fall-through */
321 case REGKIND_REGISTER:
322 /* FIXME: Help path? */
323 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
325 IUnknown_Release(*pptLib);
333 TRACE(" returns %08lx\n",res);
337 /******************************************************************************
338 * LoadRegTypeLib [OLEAUT32.162]
340 HRESULT WINAPI LoadRegTypeLib(
341 REFGUID rguid, /* [in] referenced guid */
342 WORD wVerMajor, /* [in] major version */
343 WORD wVerMinor, /* [in] minor version */
344 LCID lcid, /* [in] locale id */
345 ITypeLib **ppTLib) /* [out] path of typelib */
348 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
352 res= LoadTypeLib(bstr, ppTLib);
356 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
362 /******************************************************************************
363 * RegisterTypeLib [OLEAUT32.163]
364 * Adds information about a type library to the System Registry
366 * Docs: ITypeLib FAR * ptlib
367 * Docs: OLECHAR FAR* szFullPath
368 * Docs: OLECHAR FAR* szHelpDir
374 HRESULT WINAPI RegisterTypeLib(
375 ITypeLib * ptlib, /* [in] Pointer to the library*/
376 OLECHAR * szFullPath, /* [in] full Path of the library*/
377 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
388 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
390 if (ptlib == NULL || szFullPath == NULL)
393 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
396 StringFromGUID2(&attr->guid, guid, 80);
397 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
398 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
399 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
400 HeapFree(GetProcessHeap(), 0, guidA);
403 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
404 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
408 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
410 if (RegSetValueExW(key, NULL, 0, REG_SZ,
411 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
419 /* FIXME: This *seems* to be 0 always, not sure though */
420 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
421 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
423 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
424 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
432 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
433 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
436 /* FIXME: is %u correct? */
437 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
438 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
439 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
447 /* register OLE Automation-compatible interfaces for this typelib */
448 types = ITypeLib_GetTypeInfoCount(ptlib);
449 for (tidx=0; tidx<types; tidx++) {
450 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
451 LPOLESTR name = NULL;
452 ITypeInfo *tinfo = NULL;
454 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
456 case TKIND_INTERFACE:
457 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
458 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
461 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
462 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
465 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
466 /* coclasses should probably not be registered? */
469 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
473 TYPEATTR *tattr = NULL;
474 ITypeInfo_GetTypeAttr(tinfo, &tattr);
476 TRACE_(typelib)("guid=%s, flags=%04x (",
477 debugstr_guid(&tattr->guid),
479 if (TRACE_ON(typelib)) {
480 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
500 * FIXME: The 1 is just here until we implement rpcrt4
501 * stub/proxy handling. Until then it helps IShield
504 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
506 /* register interface<->typelib coupling */
507 StringFromGUID2(&tattr->guid, guid, 80);
508 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
509 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
510 HeapFree(GetProcessHeap(), 0, guidA);
512 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
513 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
515 RegSetValueExW(key, NULL, 0, REG_SZ,
516 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
518 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
519 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
520 RegSetValueExA(subKey, NULL, 0, REG_SZ,
524 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
525 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
526 RegSetValueExA(subKey, NULL, 0, REG_SZ,
531 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
532 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
534 StringFromGUID2(&attr->guid, guid, 80);
535 snprintf(ver, sizeof(ver), "%x.%x",
536 attr->wMajorVerNum, attr->wMinorVerNum);
537 RegSetValueExW(subKey, NULL, 0, REG_SZ,
538 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
539 RegSetValueExA(subKey, "Version", 0, REG_SZ,
546 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
548 ITypeInfo_Release(tinfo);
555 ITypeLib_ReleaseTLibAttr(ptlib, attr);
561 /******************************************************************************
562 * UnRegisterTypeLib [OLEAUT32.186]
563 * Removes information about a type library from the System Registry
570 HRESULT WINAPI UnRegisterTypeLib(
571 REFGUID libid, /* [in] Guid of the library */
572 WORD wVerMajor, /* [in] major version */
573 WORD wVerMinor, /* [in] minor version */
574 LCID lcid, /* [in] locale id */
577 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
578 return S_OK; /* FIXME: pretend everything is OK */
581 /*======================= ITypeLib implementation =======================*/
583 typedef struct tagTLBCustData
587 struct tagTLBCustData* next;
590 /* data structure for import typelibs */
591 typedef struct tagTLBImpLib
593 int offset; /* offset in the file (MSFT)
594 offset in nametable (SLTG)
595 just used to identify library while reading
597 GUID guid; /* libid */
598 BSTR name; /* name */
600 LCID lcid; /* lcid of imported typelib */
602 WORD wVersionMajor; /* major version number */
603 WORD wVersionMinor; /* minor version number */
605 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
606 NULL if not yet loaded */
607 struct tagTLBImpLib * next;
610 /* internal ITypeLib data */
611 typedef struct tagITypeLibImpl
613 ICOM_VFIELD(ITypeLib2);
615 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
617 /* strings can be stored in tlb as multibyte strings BUT they are *always*
618 * exported to the application as a UNICODE string.
624 unsigned long dwHelpContext;
625 int TypeInfoCount; /* nr of typeinfo's in librarry */
626 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
627 int ctCustData; /* number of items in cust data list */
628 TLBCustData * pCustData; /* linked list to cust data */
629 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
630 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
631 libary. Only used while read MSFT
635 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
637 /* ITypeLib methods */
638 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
639 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
641 /*======================= ITypeInfo implementation =======================*/
643 /* data for refernced types */
644 typedef struct tagTLBRefType
646 INT index; /* Type index for internal ref or for external ref
647 it the format is SLTG. -2 indicates to
650 GUID guid; /* guid of the referenced type */
651 /* if index == TLB_REF_USE_GUID */
653 HREFTYPE reference; /* The href of this ref */
654 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
655 TLB_REF_INTERNAL for internal refs
656 TLB_REF_NOT_FOUND for broken refs */
658 struct tagTLBRefType * next;
661 #define TLB_REF_USE_GUID -2
663 #define TLB_REF_INTERNAL (void*)-2
664 #define TLB_REF_NOT_FOUND (void*)-1
666 /* internal Parameter data */
667 typedef struct tagTLBParDesc
671 TLBCustData * pCustData; /* linked list to cust data */
674 /* internal Function data */
675 typedef struct tagTLBFuncDesc
677 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
678 BSTR Name; /* the name of this function */
679 TLBParDesc *pParamDesc; /* array with param names and custom data */
681 int HelpStringContext;
683 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
685 TLBCustData * pCustData; /* linked list to cust data; */
686 struct tagTLBFuncDesc * next;
689 /* internal Variable data */
690 typedef struct tagTLBVarDesc
692 VARDESC vardesc; /* lots of info on the variable and its attributes. */
693 BSTR Name; /* the name of this variable */
695 int HelpStringContext; /* FIXME: where? */
698 TLBCustData * pCustData;/* linked list to cust data; */
699 struct tagTLBVarDesc * next;
702 /* internal implemented interface data */
703 typedef struct tagTLBImplType
705 HREFTYPE hRef; /* hRef of interface */
706 int implflags; /* IMPLFLAG_*s */
708 TLBCustData * pCustData;/* linked list to custom data; */
709 struct tagTLBImplType *next;
712 /* internal TypeInfo data */
713 typedef struct tagITypeInfoImpl
715 ICOM_VFIELD(ITypeInfo2);
717 TYPEATTR TypeAttr ; /* _lots_ of type information. */
718 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
719 int index; /* index in this typelib; */
720 /* type libs seem to store the doc strings in ascii
721 * so why should we do it in unicode?
725 unsigned long dwHelpContext;
726 unsigned long dwHelpStringContext;
729 TLBFuncDesc * funclist; /* linked list with function descriptions */
732 TLBVarDesc * varlist; /* linked list with variable descriptions */
734 /* Implemented Interfaces */
735 TLBImplType * impltypelist;
737 TLBRefType * reflist;
739 TLBCustData * pCustData; /* linked list to cust data; */
740 struct tagITypeInfoImpl * next;
743 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
745 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
747 typedef struct tagTLBContext
749 unsigned int oStart; /* start of TLB in file */
750 unsigned int pos; /* current pos */
751 unsigned int length; /* total length */
752 void *mapping; /* memory mapping */
753 MSFT_SegDir * pTblDir;
754 ITypeLibImpl* pLibInfo;
758 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
763 static void dump_VarType(VARTYPE vt,char *szVarType) {
764 /* FIXME : we could have better trace here, depending on the VARTYPE
767 if (vt & VT_RESERVED)
768 szVarType += strlen(strcpy(szVarType, "reserved | "));
770 szVarType += strlen(strcpy(szVarType, "ref to "));
772 szVarType += strlen(strcpy(szVarType, "array of "));
774 szVarType += strlen(strcpy(szVarType, "vector of "));
775 switch(vt & VT_TYPEMASK) {
776 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
777 case VT_I2: sprintf(szVarType, "VT_I2"); break;
778 case VT_I4: sprintf(szVarType, "VT_I4"); break;
779 case VT_R4: sprintf(szVarType, "VT_R4"); break;
780 case VT_R8: sprintf(szVarType, "VT_R8"); break;
781 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
782 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
783 case VT_CY: sprintf(szVarType, "VT_CY"); break;
784 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
785 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
786 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
787 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
788 case VT_I1: sprintf(szVarType, "VT_I1"); break;
789 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
790 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
791 case VT_INT: sprintf(szVarType, "VT_INT"); break;
792 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
793 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
794 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
795 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
796 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
800 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
801 if (pTD->vt & VT_RESERVED)
802 szVarType += strlen(strcpy(szVarType, "reserved | "));
803 if (pTD->vt & VT_BYREF)
804 szVarType += strlen(strcpy(szVarType, "ref to "));
805 if (pTD->vt & VT_ARRAY)
806 szVarType += strlen(strcpy(szVarType, "array of "));
807 if (pTD->vt & VT_VECTOR)
808 szVarType += strlen(strcpy(szVarType, "vector of "));
809 switch(pTD->vt & VT_TYPEMASK) {
810 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
811 case VT_I2: sprintf(szVarType, "VT_I2"); break;
812 case VT_I4: sprintf(szVarType, "VT_I4"); break;
813 case VT_R4: sprintf(szVarType, "VT_R4"); break;
814 case VT_R8: sprintf(szVarType, "VT_R8"); break;
815 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
816 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
817 case VT_CY: sprintf(szVarType, "VT_CY"); break;
818 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
819 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
820 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
821 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
822 case VT_I1: sprintf(szVarType, "VT_I1"); break;
823 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
824 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
825 case VT_INT: sprintf(szVarType, "VT_INT"); break;
826 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
827 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
828 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
829 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
830 pTD->u.hreftype); break;
831 case VT_PTR: sprintf(szVarType, "ptr to ");
832 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
834 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
835 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
837 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
838 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
839 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
842 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
846 void dump_ELEMDESC(ELEMDESC *edesc) {
848 dump_TypeDesc(&edesc->tdesc,buf);
849 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
850 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
851 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
853 void dump_FUNCDESC(FUNCDESC *funcdesc) {
855 MESSAGE("memid is %08lx\n",funcdesc->memid);
856 for (i=0;i<funcdesc->cParams;i++) {
857 MESSAGE("Param %d:\n",i);
858 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
860 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
861 switch (funcdesc->funckind) {
862 case FUNC_VIRTUAL: MESSAGE("virtual");break;
863 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
864 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
865 case FUNC_STATIC: MESSAGE("static");break;
866 case FUNC_DISPATCH: MESSAGE("dispatch");break;
867 default: MESSAGE("unknown");break;
869 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
870 switch (funcdesc->invkind) {
871 case INVOKE_FUNC: MESSAGE("func");break;
872 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
873 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
874 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
876 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
877 switch (funcdesc->callconv) {
878 case CC_CDECL: MESSAGE("cdecl");break;
879 case CC_PASCAL: MESSAGE("pascal");break;
880 case CC_STDCALL: MESSAGE("stdcall");break;
881 case CC_SYSCALL: MESSAGE("syscall");break;
884 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
885 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
886 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
889 void dump_IDLDESC(IDLDESC *idl) {
890 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
893 static char * typekind_desc[] =
906 void dump_TYPEATTR(TYPEATTR *tattr) {
908 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
909 MESSAGE("\tlcid: %ld\n",tattr->lcid);
910 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
911 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
912 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
913 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
914 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
915 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
916 MESSAGE("\tcVars: %d\n", tattr->cVars);
917 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
918 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
919 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
920 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
921 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
922 dump_TypeDesc(&tattr->tdescAlias,buf);
923 MESSAGE("\ttypedesc: %s\n", buf);
924 dump_IDLDESC(&tattr->idldescType);
927 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
930 if (!TRACE_ON(typelib))
932 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
933 for (i=0;i<pfd->funcdesc.cParams;i++)
934 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
937 dump_FUNCDESC(&(pfd->funcdesc));
939 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
940 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
942 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
946 dump_TLBFuncDescOne(pfd);
950 static void dump_TLBVarDesc(TLBVarDesc * pvd)
954 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
959 static void dump_TLBImpLib(TLBImpLib *import)
961 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
962 debugstr_w(import->name));
963 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
964 import->wVersionMinor, import->lcid, import->offset);
967 static void dump_TLBRefType(TLBRefType * prt)
971 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
973 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
975 TRACE_(typelib)("type no: %d\n", prt->index);
977 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
978 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
979 TRACE_(typelib)("in lib\n");
980 dump_TLBImpLib(prt->pImpTLInfo);
986 static void dump_TLBImplType(TLBImplType * impl)
990 "implementing/inheriting interface hRef = %lx implflags %x\n",
991 impl->hRef, impl->implflags);
996 void dump_Variant(VARIANT * pvar)
1001 TRACE("(%p)\n", pvar);
1005 ZeroMemory(szVarType, sizeof(szVarType));
1007 /* FIXME : we could have better trace here, depending on the VARTYPE
1010 dump_VarType(V_VT(pvar),szVarType);
1012 TRACE("VARTYPE: %s\n", szVarType);
1014 if (V_VT(pvar) & VT_BYREF) {
1015 ref = V_UNION(pvar, byref);
1018 else ref = &V_UNION(pvar, cVal);
1020 if (V_VT(pvar) & VT_ARRAY) {
1024 if (V_VT(pvar) & VT_VECTOR) {
1029 switch (V_VT(pvar) & VT_TYPEMASK)
1032 TRACE("%d\n", *(short*)ref);
1037 TRACE("%u\n", *(UINT*)ref);
1042 TRACE("%d\n", *(INT*)ref);
1046 TRACE("%3.3e\n", *(float*)ref);
1050 TRACE("%3.3e\n", *(double*)ref);
1054 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1058 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1063 TRACE("%p\n", *(LPVOID*)ref);
1067 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1073 memset( &TM, 0, sizeof(TM) );
1075 if( DateToTm( *(DATE*)ref, 0, &TM ) == FALSE ) {
1076 TRACE("invalid date? (?)%ld %f\n", *(long*)ref, *(double *)ref);
1078 TRACE("(yyyymmdd) %4.4d-%2.2d-%2.2d (time) %2.2d:%2.2d:%2.2d [%f]\n",
1079 TM.tm_year, TM.tm_mon+1, TM.tm_mday,
1080 TM.tm_hour, TM.tm_min, TM.tm_sec, *(double *)ref);
1086 TRACE("%ld (hi), %lu (lo)\n", ((CY *)ref)->s.Hi, ((CY *)ref)->s.Lo);
1091 TRACE("(?)%ld\n", *(long*)ref);
1096 static void dump_DispParms(DISPPARAMS * pdp)
1100 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1102 while (index < pdp->cArgs)
1104 dump_Variant( &pdp->rgvarg[index] );
1109 static void dump_TypeInfo(ITypeInfoImpl * pty)
1111 TRACE("%p ref=%u\n", pty, pty->ref);
1112 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1113 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1114 TRACE("fct:%u var:%u impl:%u\n",
1115 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1116 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1117 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1118 dump_TLBFuncDesc(pty->funclist);
1119 dump_TLBVarDesc(pty->varlist);
1120 dump_TLBImplType(pty->impltypelist);
1123 void dump_VARDESC(VARDESC *v)
1125 MESSAGE("memid %ld\n",v->memid);
1126 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1127 MESSAGE("oInst %ld\n",v->u.oInst);
1128 dump_ELEMDESC(&(v->elemdescVar));
1129 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1130 MESSAGE("varkind %d\n",v->varkind);
1133 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1135 /* VT_LPWSTR is largest type that */
1136 /* may appear in type description*/
1137 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1138 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1139 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1140 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1141 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1142 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1146 static void TLB_abort()
1150 static void * TLB_Alloc(unsigned size)
1153 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1155 ERR("cannot allocate memory\n");
1160 static void TLB_Free(void * ptr)
1162 HeapFree(GetProcessHeap(), 0, ptr);
1166 /**********************************************************************
1168 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1171 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1173 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1174 pcx->pos, count, pcx->oStart, pcx->length, where);
1176 if (where != DO_NOT_SEEK)
1178 where += pcx->oStart;
1179 if (where > pcx->length)
1182 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1187 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1188 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1193 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1198 ret = MSFT_Read(buffer, count, pcx, where);
1199 FromLEDWords(buffer, ret);
1204 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1209 ret = MSFT_Read(buffer, count, pcx, where);
1210 FromLEWords(buffer, ret);
1215 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1217 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1218 memset(pGuid,0, sizeof(GUID));
1221 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1222 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1223 pGuid->Data2 = FromLEWord(pGuid->Data2);
1224 pGuid->Data3 = FromLEWord(pGuid->Data3);
1225 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1228 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1231 MSFT_NameIntro niName;
1233 WCHAR* pwstring = NULL;
1234 BSTR bstrName = NULL;
1236 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1237 pcx->pTblDir->pNametab.offset+offset);
1238 niName.namelen &= 0xFF; /* FIXME: correct ? */
1239 name=TLB_Alloc((niName.namelen & 0xff) +1);
1240 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1241 name[niName.namelen & 0xff]='\0';
1243 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1246 /* no invalid characters in string */
1249 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1251 /* don't check for invalid character since this has been done previously */
1252 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1254 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1255 lengthInChars = SysStringLen(bstrName);
1256 HeapFree(GetProcessHeap(), 0, pwstring);
1259 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1263 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1270 if(offset<0) return NULL;
1271 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1272 if(length <= 0) return 0;
1273 string=TLB_Alloc(length +1);
1274 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1275 string[length]='\0';
1277 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1278 string, -1, NULL, 0);
1280 /* no invalid characters in string */
1283 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1285 /* don't check for invalid character since this has been done previously */
1286 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1288 bstr = SysAllocStringLen(pwstring, lengthInChars);
1289 lengthInChars = SysStringLen(bstr);
1290 HeapFree(GetProcessHeap(), 0, pwstring);
1293 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1297 * read a value and fill a VARIANT structure
1299 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1303 TRACE_(typelib)("\n");
1305 if(offset <0) { /* data are packed in here */
1306 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1307 V_UNION(pVar, iVal) = offset & 0xffff;
1310 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1311 pcx->pTblDir->pCustData.offset + offset );
1312 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1313 switch (V_VT(pVar)){
1314 case VT_EMPTY: /* FIXME: is this right? */
1315 case VT_NULL: /* FIXME: is this right? */
1316 case VT_I2 : /* this should not happen */
1327 case VT_VOID : /* FIXME: is this right? */
1335 case VT_DECIMAL : /* FIXME: is this right? */
1338 /* pointer types with known behaviour */
1341 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1343 FIXME("BSTR length = %d?\n", size);
1345 ptr=TLB_Alloc(size);/* allocate temp buffer */
1346 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1347 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1348 /* FIXME: do we need a AtoW conversion here? */
1349 V_UNION(pVar, bstrVal[size])=L'\0';
1350 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1355 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1362 case VT_USERDEFINED :
1368 case VT_STREAMED_OBJECT :
1369 case VT_STORED_OBJECT :
1370 case VT_BLOB_OBJECT :
1375 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1379 if(size>0) /* (big|small) endian correct? */
1380 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1384 * create a linked list with custom data
1386 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1392 TRACE_(typelib)("\n");
1396 pNew=TLB_Alloc(sizeof(TLBCustData));
1397 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1398 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1399 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1400 /* add new custom data at head of the list */
1401 pNew->next=*ppCustData;
1403 offset = entry.next;
1408 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1412 pTd->vt=type & VT_TYPEMASK;
1414 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1416 if(pTd->vt == VT_USERDEFINED)
1417 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1419 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1423 MSFT_DoFuncs(TLBContext* pcx,
1428 TLBFuncDesc** pptfd)
1431 * member information is stored in a data structure at offset
1432 * indicated by the memoffset field of the typeinfo structure
1433 * There are several distinctive parts.
1434 * the first part starts with a field that holds the total length
1435 * of this (first) part excluding this field. Then follow the records,
1436 * for each member there is one record.
1438 * First entry is always the length of the record (excluding this
1440 * Rest of the record depends on the type of the member. If there is
1441 * a field indicating the member type (function variable intereface etc)
1442 * I have not found it yet. At this time we depend on the information
1443 * in the type info and the usual order how things are stored.
1445 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1448 * Third is a equal sized array with file offsets to the name entry
1451 * Forth and last (?) part is an array with offsets to the records in the
1452 * first part of this file segment.
1455 int infolen, nameoffset, reclength, nrattributes, i;
1456 int recoffset = offset + sizeof(INT);
1459 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1461 TRACE_(typelib)("\n");
1463 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1465 for ( i = 0; i < cFuncs ; i++ )
1467 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1469 /* name, eventually add to a hash table */
1470 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1471 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1473 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1475 /* read the function information record */
1476 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1480 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1482 /* do the attributes */
1483 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1486 if ( nrattributes > 0 )
1488 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1490 if ( nrattributes > 1 )
1492 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1493 pFuncRec->OptAttr[1]) ;
1495 if ( nrattributes > 2 )
1497 if ( pFuncRec->FKCCIC & 0x2000 )
1499 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1503 (*pptfd)->Entry = MSFT_ReadString(pcx,
1504 pFuncRec->OptAttr[2]);
1506 if( nrattributes > 5 )
1508 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1510 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1513 pFuncRec->OptAttr[6],
1514 &(*pptfd)->pCustData);
1521 /* fill the FuncDesc Structure */
1522 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1523 offset + infolen + ( i + 1) * sizeof(INT));
1525 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1526 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1527 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1528 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1529 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1530 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1531 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1535 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1538 /* do the parameters/arguments */
1539 if(pFuncRec->nrargs)
1542 MSFT_ParameterInfo paraminfo;
1544 (*pptfd)->funcdesc.lprgelemdescParam =
1545 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1547 (*pptfd)->pParamDesc =
1548 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1550 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1551 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1553 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1555 TYPEDESC* lpArgTypeDesc = 0;
1559 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1562 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1564 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1566 /* SEEK value = jump to offset,
1567 * from there jump to the end of record,
1568 * go back by (j-1) arguments
1570 MSFT_ReadLEDWords( ¶minfo ,
1571 sizeof(MSFT_ParameterInfo), pcx,
1572 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1573 * sizeof(MSFT_ParameterInfo)));
1575 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1577 while ( lpArgTypeDesc != NULL )
1579 switch ( lpArgTypeDesc->vt )
1582 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1586 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1589 case VT_USERDEFINED:
1590 MSFT_DoRefType(pcx, pTI,
1591 lpArgTypeDesc->u.hreftype);
1593 lpArgTypeDesc = NULL;
1597 lpArgTypeDesc = NULL;
1603 /* parameter is the return value! */
1604 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1606 TYPEDESC* lpArgTypeDesc;
1608 (*pptfd)->funcdesc.elemdescFunc =
1609 (*pptfd)->funcdesc.lprgelemdescParam[j];
1611 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1613 while ( lpArgTypeDesc != NULL )
1615 switch ( lpArgTypeDesc->vt )
1618 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1622 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1626 case VT_USERDEFINED:
1629 lpArgTypeDesc->u.hreftype);
1631 lpArgTypeDesc = NULL;
1635 lpArgTypeDesc = NULL;
1640 /* second time around */
1641 for(j=0;j<pFuncRec->nrargs;j++)
1644 (*pptfd)->pParamDesc[j].Name =
1645 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1648 if ( (PARAMFLAG_FHASDEFAULT &
1649 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1650 ((pFuncRec->FKCCIC) & 0x1000) )
1652 INT* pInt = (INT *)((char *)pFuncRec +
1654 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1656 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1658 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1659 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1661 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1665 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1668 pFuncRec->OptAttr[7+j],
1669 &(*pptfd)->pParamDesc[j].pCustData);
1674 /* scode is not used: archaic win16 stuff FIXME: right? */
1675 (*pptfd)->funcdesc.cScodes = 0 ;
1676 (*pptfd)->funcdesc.lprgscode = NULL ;
1678 pptfd = & ((*pptfd)->next);
1679 recoffset += reclength;
1682 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1683 int cVars, int offset, TLBVarDesc ** pptvd)
1685 int infolen, nameoffset, reclength;
1687 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1691 TRACE_(typelib)("\n");
1693 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1694 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1695 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1696 recoffset += offset+sizeof(INT);
1697 for(i=0;i<cVars;i++){
1698 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1699 /* name, eventually add to a hash table */
1700 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1701 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1702 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1703 /* read the variable information record */
1704 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1706 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1708 if(reclength >(6*sizeof(INT)) )
1709 (*pptvd)->HelpContext=pVarRec->HelpContext;
1710 if(reclength >(7*sizeof(INT)) )
1711 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1712 if(reclength >(8*sizeof(INT)) )
1713 if(reclength >(9*sizeof(INT)) )
1714 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1715 /* fill the VarDesc Structure */
1716 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1717 offset + infolen + ( i + 1) * sizeof(INT));
1718 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1719 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1720 MSFT_GetTdesc(pcx, pVarRec->DataType,
1721 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1722 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1723 if(pVarRec->VarKind == VAR_CONST ){
1724 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1725 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1726 pVarRec->OffsValue, pcx);
1728 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1729 pptvd=&((*pptvd)->next);
1730 recoffset += reclength;
1733 /* fill in data for a hreftype (offset). When the refernced type is contained
1734 * in the typelib, it's just an (file) offset in the type info base dir.
1735 * If comes from import, it's an offset+1 in the ImpInfo table
1737 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1741 TLBRefType **ppRefType = &pTI->reflist;
1743 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1746 if((*ppRefType)->reference == offset)
1748 ppRefType = &(*ppRefType)->next;
1751 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1752 sizeof(**ppRefType));
1754 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1755 /* external typelib */
1756 MSFT_ImpInfo impinfo;
1757 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1759 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1761 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1762 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1763 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1764 if(pImpLib->offset==impinfo.oImpFile) break;
1765 pImpLib=pImpLib->next;
1768 (*ppRefType)->reference=offset;
1769 (*ppRefType)->pImpTLInfo = pImpLib;
1770 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1771 (*ppRefType)->index = TLB_REF_USE_GUID;
1773 ERR("Cannot find a reference\n");
1774 (*ppRefType)->reference=-1;
1775 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1778 /* in this typelib */
1779 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1780 (*ppRefType)->reference=offset;
1781 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1785 /* process Implemented Interfaces of a com class */
1786 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1790 MSFT_RefRecord refrec;
1791 TLBImplType **ppImpl = &pTI->impltypelist;
1793 TRACE_(typelib)("\n");
1795 for(i=0;i<count;i++){
1796 if(offset<0) break; /* paranoia */
1797 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1798 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1799 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1800 (*ppImpl)->hRef = refrec.reftype;
1801 (*ppImpl)->implflags=refrec.flags;
1802 (*ppImpl)->ctCustData=
1803 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1804 offset=refrec.onext;
1805 ppImpl=&((*ppImpl)->next);
1809 * process a typeinfo record
1811 ITypeInfoImpl * MSFT_DoTypeInfo(
1814 ITypeLibImpl * pLibInfo)
1816 MSFT_TypeInfoBase tiBase;
1817 ITypeInfoImpl *ptiRet;
1819 TRACE_(typelib)("count=%u\n", count);
1821 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1822 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1823 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1824 /* this is where we are coming from */
1825 ptiRet->pTypeLib = pLibInfo;
1826 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1827 ptiRet->index=count;
1828 /* fill in the typeattr fields */
1829 FIXME("Assign constructor/destructor memid\n");
1831 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1832 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1833 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1834 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1835 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1836 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1837 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1838 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1839 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1840 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1841 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1842 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1843 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1844 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1845 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1846 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1847 MSFT_GetTdesc(pcx, tiBase.datatype1,
1848 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1851 /* IDLDESC idldescType; *//* never saw this one != zero */
1853 /* name, eventually add to a hash table */
1854 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1855 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1857 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1858 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1859 ptiRet->dwHelpContext=tiBase.helpcontext;
1860 /* note: InfoType's Help file and HelpStringDll come from the containing
1861 * library. Further HelpString and Docstring appear to be the same thing :(
1864 if(ptiRet->TypeAttr.cFuncs >0 )
1865 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1866 ptiRet->TypeAttr.cVars,
1867 tiBase.memoffset, & ptiRet->funclist);
1869 if(ptiRet->TypeAttr.cVars >0 )
1870 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1871 ptiRet->TypeAttr.cVars,
1872 tiBase.memoffset, & ptiRet->varlist);
1873 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1874 switch(ptiRet->TypeAttr.typekind)
1877 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1880 case TKIND_DISPATCH:
1881 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1883 if (tiBase.datatype1 != -1)
1885 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1886 ptiRet->impltypelist->hRef = tiBase.datatype1;
1889 { /* FIXME: This is a really bad hack to add IDispatch */
1890 char* szStdOle = "stdole2.tlb\0";
1891 int nStdOleLen = strlen(szStdOle);
1892 TLBRefType **ppRef = &ptiRet->reflist;
1895 if((*ppRef)->reference == -1)
1897 ppRef = &(*ppRef)->next;
1900 *ppRef = TLB_Alloc(sizeof(**ppRef));
1901 (*ppRef)->guid = IID_IDispatch;
1902 (*ppRef)->reference = -1;
1903 (*ppRef)->index = TLB_REF_USE_GUID;
1904 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1905 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1906 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1909 MultiByteToWideChar(CP_ACP,
1913 (*ppRef)->pImpTLInfo->name,
1914 SysStringLen((*ppRef)->pImpTLInfo->name));
1916 (*ppRef)->pImpTLInfo->lcid = 0;
1917 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1918 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1923 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1924 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1925 ptiRet->impltypelist->hRef = tiBase.datatype1;
1930 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1932 TRACE_(typelib)("%s guid: %s kind:%s\n",
1933 debugstr_w(ptiRet->Name),
1934 debugstr_guid(&ptiRet->TypeAttr.guid),
1935 typekind_desc[ptiRet->TypeAttr.typekind]);
1940 /****************************************************************************
1943 * find the type of the typelib file and map the typelib resource into
1946 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1947 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1948 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1950 int ret = TYPE_E_CANTLOADLIBRARY;
1951 DWORD dwSignature = 0;
1954 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1958 /* check the signature of the file */
1959 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1960 if (INVALID_HANDLE_VALUE != hFile)
1962 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1965 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1968 /* retrieve file size */
1969 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1971 /* first try to load as *.tlb */
1972 dwSignature = FromLEDWord(*((DWORD*) pBase));
1973 if ( dwSignature == MSFT_SIGNATURE)
1975 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1977 else if ( dwSignature == SLTG_SIGNATURE)
1979 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1981 UnmapViewOfFile(pBase);
1983 CloseHandle(hMapping);
1988 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1990 /* find the typelibrary resource*/
1991 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1992 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1995 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1999 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2002 LPVOID pBase = LockResource(hGlobal);
2003 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2007 /* try to load as incore resource */
2008 dwSignature = FromLEDWord(*((DWORD*) pBase));
2009 if ( dwSignature == MSFT_SIGNATURE)
2011 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2013 else if ( dwSignature == SLTG_SIGNATURE)
2015 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2019 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2022 FreeResource( hGlobal );
2025 FreeLibrary(hinstDLL);
2032 ERR("Loading of typelib %s failed with error %ld\n",
2033 debugstr_w(pszFileName), GetLastError());
2038 /*================== ITypeLib(2) Methods ===================================*/
2040 /****************************************************************************
2041 * ITypeLib2_Constructor_MSFT
2043 * loading an MSFT typelib from an in-memory image
2045 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2049 MSFT_Header tlbHeader;
2050 MSFT_SegDir tlbSegDir;
2051 ITypeLibImpl * pTypeLibImpl;
2053 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2055 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2056 if (!pTypeLibImpl) return NULL;
2058 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2059 pTypeLibImpl->ref = 1;
2061 /* get pointer to beginning of typelib data */
2065 cx.pLibInfo = pTypeLibImpl;
2066 cx.length = dwTLBLength;
2069 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2071 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2072 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2073 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2076 /* there is a small amount of information here until the next important
2078 * the segment directory . Try to calculate the amount of data */
2079 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2081 /* now read the segment directory */
2082 TRACE("read segment directory (at %ld)\n",lPSegDir);
2083 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2084 cx.pTblDir = &tlbSegDir;
2086 /* just check two entries */
2087 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2089 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2090 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2094 /* now fill our internal data */
2095 /* TLIBATTR fields */
2096 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2098 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2099 /* Windows seems to have zero here, is this correct? */
2100 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2101 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2103 pTypeLibImpl->LibAttr.lcid = 0;
2105 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2106 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2107 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2108 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2110 /* name, eventually add to a hash table */
2111 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2114 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2115 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2117 if( tlbHeader.varflags & HELPDLLFLAG)
2120 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2121 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2124 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2127 if(tlbHeader.CustomDataOffset >= 0)
2129 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2132 /* fill in typedescriptions */
2133 if(tlbSegDir.pTypdescTab.length > 0)
2135 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2137 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2138 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2141 /* FIXME: add several sanity checks here */
2142 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2143 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2145 /* FIXME: check safearray */
2147 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2149 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2151 else if(td[0] == VT_CARRAY)
2153 /* array descr table here */
2154 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2156 else if(td[0] == VT_USERDEFINED)
2158 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2160 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2163 /* second time around to fill the array subscript info */
2166 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2167 if(tlbSegDir.pArrayDescriptions.offset>0)
2169 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2170 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2173 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2175 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2177 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2179 for(j = 0; j<td[2]; j++)
2181 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2182 sizeof(INT), &cx, DO_NOT_SEEK);
2183 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2184 sizeof(INT), &cx, DO_NOT_SEEK);
2189 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2190 ERR("didn't find array description data\n");
2195 /* imported type libs */
2196 if(tlbSegDir.pImpFiles.offset>0)
2198 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2199 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2202 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2204 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2205 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2206 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2208 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2209 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2210 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2211 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2214 (*ppImpLib)->name = TLB_Alloc(size+1);
2215 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2216 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2217 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2219 ppImpLib = &(*ppImpLib)->next;
2224 if(tlbHeader.nrtypeinfos >= 0 )
2226 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2227 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2230 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2232 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2234 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2235 ppTI = &((*ppTI)->next);
2236 (pTypeLibImpl->TypeInfoCount)++;
2240 TRACE("(%p)\n", pTypeLibImpl);
2241 return (ITypeLib2*) pTypeLibImpl;
2245 static BSTR TLB_MultiByteToBSTR(char *ptr)
2251 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2252 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2253 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2254 ret = SysAllocString(nameW);
2255 HeapFree(GetProcessHeap(), 0, nameW);
2259 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2265 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2266 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2270 guid->Data4[0] = s >> 8;
2271 guid->Data4[1] = s & 0xff;
2274 for(i = 0; i < 6; i++) {
2275 memcpy(b, str + 24 + 2 * i, 2);
2276 guid->Data4[i + 2] = strtol(b, NULL, 16);
2281 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2288 bytelen = *(WORD*)ptr;
2289 if(bytelen == 0xffff) return 2;
2290 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2291 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2292 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2293 *pBstr = SysAllocStringLen(nameW, len);
2294 HeapFree(GetProcessHeap(), 0, nameW);
2298 static WORD SLTG_ReadStringA(char *ptr, char **str)
2303 bytelen = *(WORD*)ptr;
2304 if(bytelen == 0xffff) return 2;
2305 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2306 memcpy(*str, ptr + 2, bytelen);
2307 (*str)[bytelen] = '\0';
2311 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2313 char *ptr = pLibBlk;
2316 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2317 FIXME("libblk magic = %04x\n", w);
2322 if((w = *(WORD*)ptr) != 0xffff) {
2323 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2328 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2330 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2332 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2335 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2338 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2341 ptr += 4; /* skip res12 */
2343 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2346 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2349 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2352 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2353 ptr += sizeof(GUID);
2355 return ptr - (char*)pLibBlk;
2358 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2361 TYPEDESC *pTD = &pElem->tdesc;
2363 /* Handle [in/out] first */
2364 if((*pType & 0xc000) == 0xc000)
2365 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2366 else if(*pType & 0x8000)
2367 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2368 else if(*pType & 0x4000)
2369 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2371 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2374 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2377 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2380 if((*pType & 0xe00) == 0xe00) {
2382 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2384 pTD = pTD->u.lptdesc;
2386 switch(*pType & 0x7f) {
2389 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2391 pTD = pTD->u.lptdesc;
2394 case VT_USERDEFINED:
2395 pTD->vt = VT_USERDEFINED;
2396 pTD->u.hreftype = *(++pType) / 4;
2402 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2405 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2407 pTD->vt = VT_CARRAY;
2408 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2410 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2411 pTD->u.lpadesc->cDims = pSA->cDims;
2412 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2413 pSA->cDims * sizeof(SAFEARRAYBOUND));
2415 pTD = &pTD->u.lpadesc->tdescElem;
2421 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2425 pTD->vt = VT_SAFEARRAY;
2426 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2428 pTD = pTD->u.lptdesc;
2432 pTD->vt = *pType & 0x7f;
2442 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2447 TLBRefType **ppRefType;
2449 if(pRef->magic != SLTG_REF_MAGIC) {
2450 FIXME("Ref magic = %x\n", pRef->magic);
2453 name = ( (char*)(&pRef->names) + pRef->number);
2455 ppRefType = &pTI->reflist;
2456 for(ref = 0; ref < pRef->number >> 3; ref++) {
2458 unsigned int lib_offs, type_num;
2460 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2461 sizeof(**ppRefType));
2463 name += SLTG_ReadStringA(name, &refname);
2464 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2465 FIXME("Can't sscanf ref\n");
2466 if(lib_offs != 0xffff) {
2467 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2470 if((*import)->offset == lib_offs)
2472 import = &(*import)->next;
2475 char fname[MAX_PATH+1];
2478 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2480 (*import)->offset = lib_offs;
2481 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2483 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2484 &(*import)->wVersionMajor,
2485 &(*import)->wVersionMinor,
2486 &(*import)->lcid, fname) != 4) {
2487 FIXME("can't sscanf ref %s\n",
2488 pNameTable + lib_offs + 40);
2490 len = strlen(fname);
2491 if(fname[len-1] != '#')
2492 FIXME("fname = %s\n", fname);
2493 fname[len-1] = '\0';
2494 (*import)->name = TLB_MultiByteToBSTR(fname);
2496 (*ppRefType)->pImpTLInfo = *import;
2497 } else { /* internal ref */
2498 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2500 (*ppRefType)->reference = ref;
2501 (*ppRefType)->index = type_num;
2503 HeapFree(GetProcessHeap(), 0, refname);
2504 ppRefType = &(*ppRefType)->next;
2506 if((BYTE)*name != SLTG_REF_MAGIC)
2507 FIXME("End of ref block magic = %x\n", *name);
2508 dump_TLBRefType(pTI->reflist);
2511 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2514 SLTG_ImplInfo *info;
2515 TLBImplType **ppImplType = &pTI->impltypelist;
2516 /* I don't really get this structure, usually it's 0x16 bytes
2517 long, but iuser.tlb contains some that are 0x18 bytes long.
2518 That's ok because we can use the next ptr to jump to the next
2519 one. But how do we know the length of the last one? The WORD
2520 at offs 0x8 might be the clue. For now I'm just assuming that
2521 the last one is the regular 0x16 bytes. */
2523 info = (SLTG_ImplInfo*)pBlk;
2525 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2526 sizeof(**ppImplType));
2527 (*ppImplType)->hRef = info->ref;
2528 (*ppImplType)->implflags = info->impltypeflags;
2529 pTI->TypeAttr.cImplTypes++;
2530 ppImplType = &(*ppImplType)->next;
2532 if(info->next == 0xffff)
2535 FIXME("Interface inheriting more than one interface\n");
2536 info = (SLTG_ImplInfo*)(pBlk + info->next);
2538 info++; /* see comment at top of function */
2542 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2545 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2546 SLTG_MemberHeader *pMemHeader;
2547 char *pFirstItem, *pNextItem;
2549 if(pTIHeader->href_table != 0xffffffff) {
2550 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2555 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2557 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2559 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2560 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2563 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2567 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2570 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2571 SLTG_MemberHeader *pMemHeader;
2572 SLTG_Function *pFunc;
2573 char *pFirstItem, *pNextItem;
2574 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2577 if(pTIHeader->href_table != 0xffffffff) {
2578 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2582 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2584 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2586 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2587 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2590 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2591 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2596 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2597 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2598 FIXME("func magic = %02x\n", pFunc->magic);
2601 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2602 sizeof(**ppFuncDesc));
2603 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2605 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2606 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2607 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2608 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2609 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2610 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2612 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2613 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2615 if(pFunc->retnextopt & 0x80)
2616 pType = &pFunc->rettype;
2618 pType = (WORD*)(pFirstItem + pFunc->rettype);
2621 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2623 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2624 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2625 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2626 (*ppFuncDesc)->pParamDesc =
2627 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2628 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2630 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2632 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2633 char *paramName = pNameTable + *pArg;
2635 /* If arg type follows then paramName points to the 2nd
2636 letter of the name, else the next WORD is an offset to
2637 the arg type and paramName points to the first letter.
2638 So let's take one char off paramName and see if we're
2639 pointing at an alpha-numeric char. However if *pArg is
2640 0xffff or 0xfffe then the param has no name, the former
2641 meaning that the next WORD is the type, the latter
2642 meaning the the next WORD is an offset to the type. */
2647 else if(*pArg == 0xfffe) {
2651 else if(!isalnum(*(paramName-1)))
2656 if(HaveOffs) { /* the next word is an offset to type */
2657 pType = (WORD*)(pFirstItem + *pArg);
2658 SLTG_DoType(pType, pFirstItem,
2659 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2664 pArg = SLTG_DoType(pArg, pFirstItem,
2665 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2668 /* Are we an optional param ? */
2669 if((*ppFuncDesc)->funcdesc.cParams - param <=
2670 (*ppFuncDesc)->funcdesc.cParamsOpt)
2671 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2674 (*ppFuncDesc)->pParamDesc[param].Name =
2675 TLB_MultiByteToBSTR(paramName);
2679 ppFuncDesc = &((*ppFuncDesc)->next);
2680 if(pFunc->next == 0xffff) break;
2682 pTI->TypeAttr.cFuncs = num;
2683 dump_TLBFuncDesc(pTI->funclist);
2684 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2687 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2690 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2691 SLTG_MemberHeader *pMemHeader;
2692 SLTG_RecordItem *pItem;
2694 TLBVarDesc **ppVarDesc = &pTI->varlist;
2699 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2701 pFirstItem = (char*)(pMemHeader + 1);
2702 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2703 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2704 if(pItem->magic != SLTG_RECORD_MAGIC) {
2705 FIXME("record magic = %02x\n", pItem->magic);
2708 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2709 sizeof(**ppVarDesc));
2710 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2711 (*ppVarDesc)->vardesc.memid = pItem->memid;
2712 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2713 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2715 if(pItem->typepos == 0x02)
2716 pType = &pItem->type;
2717 else if(pItem->typepos == 0x00)
2718 pType = (WORD*)(pFirstItem + pItem->type);
2720 FIXME("typepos = %02x\n", pItem->typepos);
2724 SLTG_DoType(pType, pFirstItem,
2725 &(*ppVarDesc)->vardesc.elemdescVar);
2727 /* FIXME("helpcontext, helpstring\n"); */
2729 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2731 ppVarDesc = &((*ppVarDesc)->next);
2732 if(pItem->next == 0xffff) break;
2734 pTI->TypeAttr.cVars = num;
2735 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2738 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2741 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2742 SLTG_MemberHeader *pMemHeader;
2743 SLTG_AliasItem *pItem;
2746 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2747 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2750 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2751 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2752 if (pItem->vt == 0xffff) {
2753 if (i<(pMemHeader->cbExtra/4-1))
2754 FIXME("Endmarker too early in process alias data!\n");
2758 FIXME("Chain extends over last entry?\n");
2761 if (pItem->vt == VT_USERDEFINED) {
2762 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2763 /* guessing here ... */
2764 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2765 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2768 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2769 FIXME("alias %d: 0x%x\n",i,pItem->res02);
2773 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2776 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
2779 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2780 SLTG_MemberHeader *pMemHeader;
2781 SLTG_AliasItem *pItem;
2783 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2784 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2785 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
2786 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
2787 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
2790 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2793 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2794 SLTG_MemberHeader *pMemHeader;
2795 SLTG_EnumItem *pItem;
2797 TLBVarDesc **ppVarDesc = &pTI->varlist;
2800 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2802 pFirstItem = (char*)(pMemHeader + 1);
2803 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2804 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2805 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2806 FIXME("enumitem magic = %04x\n", pItem->magic);
2809 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2810 sizeof(**ppVarDesc));
2811 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2812 (*ppVarDesc)->vardesc.memid = pItem->memid;
2813 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2815 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2816 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2817 *(INT*)(pItem->value + pFirstItem);
2818 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2819 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2820 /* FIXME("helpcontext, helpstring\n"); */
2822 ppVarDesc = &((*ppVarDesc)->next);
2823 if(pItem->next == 0xffff) break;
2825 pTI->TypeAttr.cVars = num;
2826 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2829 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2830 managable copy of it into this */
2843 } SLTG_InternalOtherTypeInfo;
2845 /****************************************************************************
2846 * ITypeLib2_Constructor_SLTG
2848 * loading a SLTG typelib from an in-memory image
2850 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2852 ITypeLibImpl *pTypeLibImpl;
2853 SLTG_Header *pHeader;
2854 SLTG_BlkEntry *pBlkEntry;
2858 LPVOID pBlk, pFirstBlk;
2859 SLTG_LibBlk *pLibBlk;
2860 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2861 char *pAfterOTIBlks = NULL;
2862 char *pNameTable, *ptr;
2865 ITypeInfoImpl **ppTypeInfoImpl;
2867 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2869 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2870 if (!pTypeLibImpl) return NULL;
2872 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2873 pTypeLibImpl->ref = 1;
2878 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2879 pHeader->nrOfFileBlks );
2880 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
2881 FIXME("Header type magic 0x%08lx not supported.\n",
2882 pHeader->SLTG_magic);
2886 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2887 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2889 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2890 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2892 /* Next we have a magic block */
2893 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2895 /* Let's see if we're still in sync */
2896 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2897 sizeof(SLTG_COMPOBJ_MAGIC))) {
2898 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2901 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2902 sizeof(SLTG_DIR_MAGIC))) {
2903 FIXME("dir magic = %s\n", pMagic->dir_magic);
2907 pIndex = (SLTG_Index*)(pMagic+1);
2909 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2911 pFirstBlk = (LPVOID)(pPad9 + 1);
2913 /* We'll set up a ptr to the main library block, which is the last one. */
2915 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2916 pBlkEntry[order].next != 0;
2917 order = pBlkEntry[order].next - 1, i++) {
2918 pBlk = (char*)pBlk + pBlkEntry[order].len;
2922 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2924 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2929 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2931 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2932 sizeof(*pOtherTypeInfoBlks) *
2933 pTypeLibImpl->TypeInfoCount);
2936 ptr = (char*)pLibBlk + len;
2938 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2942 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2944 w = *(WORD*)(ptr + 2);
2947 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2949 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2950 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2952 w = *(WORD*)(ptr + 4 + len);
2954 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2956 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2958 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2959 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2961 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2962 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2963 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2965 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2967 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2970 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2971 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2972 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2973 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2974 len += sizeof(SLTG_OtherTypeInfo);
2978 pAfterOTIBlks = ptr;
2980 /* Skip this WORD and get the next DWORD */
2981 len = *(DWORD*)(pAfterOTIBlks + 2);
2983 /* Now add this to pLibBLk look at what we're pointing at and
2984 possibly add 0x20, then add 0x216, sprinkle a bit a magic
2985 dust and we should be pointing at the beginning of the name
2988 pNameTable = (char*)pLibBlk + len;
2990 switch(*(WORD*)pNameTable) {
2997 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3001 pNameTable += 0x216;
3005 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3007 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3010 /* Hopefully we now have enough ptrs set up to actually read in
3011 some TypeInfos. It's not clear which order to do them in, so
3012 I'll just follow the links along the BlkEntry chain and read
3013 them in in the order in which they're in the file */
3015 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3017 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3018 pBlkEntry[order].next != 0;
3019 order = pBlkEntry[order].next - 1, i++) {
3021 SLTG_TypeInfoHeader *pTIHeader;
3022 SLTG_TypeInfoTail *pTITail;
3024 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3025 pOtherTypeInfoBlks[i].index_name)) {
3026 FIXME("Index strings don't match\n");
3031 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3032 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3035 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3036 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3037 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
3038 (*ppTypeInfoImpl)->index = i;
3039 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3040 pOtherTypeInfoBlks[i].name_offs +
3042 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3043 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3045 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3046 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3047 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3048 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3049 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3051 if((pTIHeader->typeflags1 & 7) != 2)
3052 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3053 if(pTIHeader->typeflags3 != 2)
3054 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3056 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3057 debugstr_w((*ppTypeInfoImpl)->Name),
3058 typekind_desc[pTIHeader->typekind],
3059 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3060 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3062 switch(pTIHeader->typekind) {
3064 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3068 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3071 case TKIND_INTERFACE:
3072 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3076 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3080 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3081 if (pTITail->tdescalias_vt)
3082 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3085 case TKIND_DISPATCH:
3086 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3090 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3096 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3097 but we've already set those */
3098 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3099 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3100 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3102 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3124 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3125 pBlk = (char*)pBlk + pBlkEntry[order].len;
3128 if(i != pTypeLibImpl->TypeInfoCount) {
3129 FIXME("Somehow processed %d TypeInfos\n", i);
3133 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3134 return (ITypeLib2*)pTypeLibImpl;
3137 /* ITypeLib::QueryInterface
3139 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3144 ICOM_THIS( ITypeLibImpl, iface);
3146 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3149 if(IsEqualIID(riid, &IID_IUnknown) ||
3150 IsEqualIID(riid,&IID_ITypeLib)||
3151 IsEqualIID(riid,&IID_ITypeLib2))
3158 ITypeLib2_AddRef(iface);
3159 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3162 TRACE("-- Interface: E_NOINTERFACE\n");
3163 return E_NOINTERFACE;
3168 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3170 ICOM_THIS( ITypeLibImpl, iface);
3172 TRACE("(%p)->ref is %u\n",This, This->ref);
3174 return ++(This->ref);
3177 /* ITypeLib::Release
3179 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3181 ICOM_THIS( ITypeLibImpl, iface);
3185 TRACE("(%p)->(%u)\n",This, This->ref);
3189 /* FIXME destroy child objects */
3191 TRACE(" destroying ITypeLib(%p)\n",This);
3195 SysFreeString(This->Name);
3199 if (This->DocString)
3201 SysFreeString(This->DocString);
3202 This->DocString = NULL;
3207 SysFreeString(This->HelpFile);
3208 This->HelpFile = NULL;
3211 if (This->HelpStringDll)
3213 SysFreeString(This->HelpStringDll);
3214 This->HelpStringDll = NULL;
3217 if (This->pTypeInfo) /* can be NULL */
3218 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3219 HeapFree(GetProcessHeap(),0,This);
3226 /* ITypeLib::GetTypeInfoCount
3228 * Returns the number of type descriptions in the type library
3230 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3232 ICOM_THIS( ITypeLibImpl, iface);
3233 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3234 return This->TypeInfoCount;
3237 /* ITypeLib::GetTypeInfo
3239 * retrieves the specified type description in the library.
3241 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3244 ITypeInfo **ppTInfo)
3248 ICOM_THIS( ITypeLibImpl, iface);
3249 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3251 TRACE("(%p)->(index=%d) \n", This, index);
3253 if (!ppTInfo) return E_INVALIDARG;
3255 /* search element n in list */
3256 for(i=0; i < index; i++)
3258 pTypeInfo = pTypeInfo->next;
3261 TRACE("-- element not found\n");
3262 return TYPE_E_ELEMENTNOTFOUND;
3266 *ppTInfo = (ITypeInfo *) pTypeInfo;
3268 ITypeInfo_AddRef(*ppTInfo);
3269 TRACE("-- found (%p)\n",*ppTInfo);
3274 /* ITypeLibs::GetTypeInfoType
3276 * Retrieves the type of a type description.
3278 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3283 ICOM_THIS( ITypeLibImpl, iface);
3285 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3287 TRACE("(%p) index %d \n",This, index);
3289 if(!pTKind) return E_INVALIDARG;
3291 /* search element n in list */
3292 for(i=0; i < index; i++)
3296 TRACE("-- element not found\n");
3297 return TYPE_E_ELEMENTNOTFOUND;
3299 pTInfo = pTInfo->next;
3302 *pTKind = pTInfo->TypeAttr.typekind;
3303 TRACE("-- found Type (%d)\n", *pTKind);
3307 /* ITypeLib::GetTypeInfoOfGuid
3309 * Retrieves the type description that corresponds to the specified GUID.
3312 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3315 ITypeInfo **ppTInfo)
3317 ICOM_THIS( ITypeLibImpl, iface);
3318 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3320 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3322 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3324 /* search linked list for guid */
3325 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3327 pTypeInfo = pTypeInfo->next;
3331 /* end of list reached */
3332 TRACE("-- element not found\n");
3333 return TYPE_E_ELEMENTNOTFOUND;
3337 TRACE("-- found (%p, %s)\n",
3339 debugstr_w(pTypeInfo->Name));
3341 *ppTInfo = (ITypeInfo*)pTypeInfo;
3342 ITypeInfo_AddRef(*ppTInfo);
3346 /* ITypeLib::GetLibAttr
3348 * Retrieves the structure that contains the library's attributes.
3351 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3353 LPTLIBATTR *ppTLibAttr)
3355 ICOM_THIS( ITypeLibImpl, iface);
3356 TRACE("(%p)\n",This);
3357 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3358 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3362 /* ITypeLib::GetTypeComp
3364 * Enables a client compiler to bind to a library's types, variables,
3365 * constants, and global functions.
3368 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3370 ITypeComp **ppTComp)
3372 ICOM_THIS( ITypeLibImpl, iface);
3373 FIXME("(%p): stub!\n",This);
3377 /* ITypeLib::GetDocumentation
3379 * Retrieves the library's documentation string, the complete Help file name
3380 * and path, and the context identifier for the library Help topic in the Help
3383 * On a successful return all non-null BSTR pointers will have been set,
3386 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3390 BSTR *pBstrDocString,
3391 DWORD *pdwHelpContext,
3392 BSTR *pBstrHelpFile)
3394 ICOM_THIS( ITypeLibImpl, iface);
3396 HRESULT result = E_INVALIDARG;
3401 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3403 pBstrName, pBstrDocString,
3404 pdwHelpContext, pBstrHelpFile);
3408 /* documentation for the typelib */
3412 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3418 if (This->DocString)
3419 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3420 else if (This->Name)
3421 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3423 *pBstrDocString = NULL;
3427 *pdwHelpContext = This->dwHelpContext;
3432 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3434 *pBstrHelpFile = NULL;
3441 /* for a typeinfo */
3442 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3444 if(SUCCEEDED(result))
3446 result = ITypeInfo_GetDocumentation(pTInfo,
3450 pdwHelpContext, pBstrHelpFile);
3452 ITypeInfo_Release(pTInfo);
3457 if (pBstrDocString) SysFreeString (*pBstrDocString);
3459 if (pBstrName) SysFreeString (*pBstrName);
3461 return STG_E_INSUFFICIENTMEMORY;
3466 * Indicates whether a passed-in string contains the name of a type or member
3467 * described in the library.
3470 static HRESULT WINAPI ITypeLib2_fnIsName(
3476 ICOM_THIS( ITypeLibImpl, iface);
3477 ITypeInfoImpl *pTInfo;
3478 TLBFuncDesc *pFInfo;
3481 UINT nNameBufLen = SysStringLen(szNameBuf);
3483 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3487 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3488 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3489 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3490 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3491 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3492 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3493 goto ITypeLib2_fnIsName_exit;
3495 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3496 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3501 ITypeLib2_fnIsName_exit:
3502 TRACE("(%p)slow! search for %s: %s found!\n", This,
3503 debugstr_w(szNameBuf), *pfName?"NOT":"");
3508 /* ITypeLib::FindName
3510 * Finds occurrences of a type description in a type library. This may be used
3511 * to quickly verify that a name exists in a type library.
3514 static HRESULT WINAPI ITypeLib2_fnFindName(
3518 ITypeInfo **ppTInfo,
3522 ICOM_THIS( ITypeLibImpl, iface);
3523 ITypeInfoImpl *pTInfo;
3524 TLBFuncDesc *pFInfo;
3528 UINT nNameBufLen = SysStringLen(szNameBuf);
3530 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3531 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3532 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3533 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3534 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3535 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3536 goto ITypeLib2_fnFindName_exit;
3538 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3539 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3541 ITypeLib2_fnFindName_exit:
3542 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3543 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3546 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3547 This, *pcFound, debugstr_w(szNameBuf), j);
3554 /* ITypeLib::ReleaseTLibAttr
3556 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3559 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3561 TLIBATTR *pTLibAttr)
3563 ICOM_THIS( ITypeLibImpl, iface);
3564 TRACE("freeing (%p)\n",This);
3565 HeapFree(GetProcessHeap(),0,pTLibAttr);
3569 /* ITypeLib2::GetCustData
3571 * gets the custom data
3573 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3578 ICOM_THIS( ITypeLibImpl, iface);
3579 TLBCustData *pCData;
3581 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3583 if( IsEqualIID(guid, &pCData->guid)) break;
3586 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3590 VariantInit( pVarVal);
3591 VariantCopy( pVarVal, &pCData->data);
3594 return E_INVALIDARG; /* FIXME: correct? */
3597 /* ITypeLib2::GetLibStatistics
3599 * Returns statistics about a type library that are required for efficient
3600 * sizing of hash tables.
3603 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3605 ULONG *pcUniqueNames,
3606 ULONG *pcchUniqueNames)
3608 ICOM_THIS( ITypeLibImpl, iface);
3610 FIXME("(%p): stub!\n", This);
3612 if(pcUniqueNames) *pcUniqueNames=1;
3613 if(pcchUniqueNames) *pcchUniqueNames=1;
3617 /* ITypeLib2::GetDocumentation2
3619 * Retrieves the library's documentation string, the complete Help file name
3620 * and path, the localization context to use, and the context ID for the
3621 * library Help topic in the Help file.
3624 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3628 BSTR *pbstrHelpString,
3629 DWORD *pdwHelpStringContext,
3630 BSTR *pbstrHelpStringDll)
3632 ICOM_THIS( ITypeLibImpl, iface);
3636 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3638 /* the help string should be obtained from the helpstringdll,
3639 * using the _DLLGetDocumentation function, based on the supplied
3640 * lcid. Nice to do sometime...
3644 /* documentation for the typelib */
3646 *pbstrHelpString=SysAllocString(This->DocString);
3647 if(pdwHelpStringContext)
3648 *pdwHelpStringContext=This->dwHelpContext;
3649 if(pbstrHelpStringDll)
3650 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3656 /* for a typeinfo */
3657 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3659 if(SUCCEEDED(result))
3661 ITypeInfo2 * pTInfo2;
3662 result = ITypeInfo_QueryInterface(pTInfo,
3664 (LPVOID*) &pTInfo2);
3666 if(SUCCEEDED(result))
3668 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3672 pdwHelpStringContext,
3673 pbstrHelpStringDll);
3675 ITypeInfo2_Release(pTInfo2);
3678 ITypeInfo_Release(pTInfo);
3684 /* ITypeLib2::GetAllCustData
3686 * Gets all custom data items for the library.
3689 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3691 CUSTDATA *pCustData)
3693 ICOM_THIS( ITypeLibImpl, iface);
3694 TLBCustData *pCData;
3696 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3697 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3698 if(pCustData->prgCustData ){
3699 pCustData->cCustData=This->ctCustData;
3700 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3701 pCustData->prgCustData[i].guid=pCData->guid;
3702 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3705 ERR(" OUT OF MEMORY! \n");
3706 return E_OUTOFMEMORY;
3711 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3712 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3713 ITypeLib2_fnQueryInterface,
3715 ITypeLib2_fnRelease,
3716 ITypeLib2_fnGetTypeInfoCount,
3717 ITypeLib2_fnGetTypeInfo,
3718 ITypeLib2_fnGetTypeInfoType,
3719 ITypeLib2_fnGetTypeInfoOfGuid,
3720 ITypeLib2_fnGetLibAttr,
3721 ITypeLib2_fnGetTypeComp,
3722 ITypeLib2_fnGetDocumentation,
3724 ITypeLib2_fnFindName,
3725 ITypeLib2_fnReleaseTLibAttr,
3727 ITypeLib2_fnGetCustData,
3728 ITypeLib2_fnGetLibStatistics,
3729 ITypeLib2_fnGetDocumentation2,
3730 ITypeLib2_fnGetAllCustData
3733 /*================== ITypeInfo(2) Methods ===================================*/
3734 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3736 ITypeInfoImpl * pTypeInfoImpl;
3738 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3741 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3742 pTypeInfoImpl->ref=1;
3744 TRACE("(%p)\n", pTypeInfoImpl);
3745 return (ITypeInfo2*) pTypeInfoImpl;
3748 /* ITypeInfo::QueryInterface
3750 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3755 ICOM_THIS( ITypeLibImpl, iface);
3757 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3760 if(IsEqualIID(riid, &IID_IUnknown) ||
3761 IsEqualIID(riid,&IID_ITypeInfo)||
3762 IsEqualIID(riid,&IID_ITypeInfo2))
3766 ITypeInfo_AddRef(iface);
3767 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3770 TRACE("-- Interface: E_NOINTERFACE\n");
3771 return E_NOINTERFACE;
3774 /* ITypeInfo::AddRef
3776 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3778 ICOM_THIS( ITypeInfoImpl, iface);
3782 TRACE("(%p)->ref is %u\n",This, This->ref);
3786 /* ITypeInfo::Release
3788 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3790 ICOM_THIS( ITypeInfoImpl, iface);
3794 TRACE("(%p)->(%u)\n",This, This->ref);
3798 FIXME("destroy child objects\n");
3800 TRACE("destroying ITypeInfo(%p)\n",This);
3803 SysFreeString(This->Name);
3807 if (This->DocString)
3809 SysFreeString(This->DocString);
3810 This->DocString = 0;
3815 ITypeInfo_Release((ITypeInfo*)This->next);
3818 HeapFree(GetProcessHeap(),0,This);
3824 /* ITypeInfo::GetTypeAttr
3826 * Retrieves a TYPEATTR structure that contains the attributes of the type
3830 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3831 LPTYPEATTR *ppTypeAttr)
3833 ICOM_THIS( ITypeInfoImpl, iface);
3834 TRACE("(%p)\n",This);
3835 /* FIXME: must do a copy here */
3836 *ppTypeAttr=&This->TypeAttr;
3840 /* ITypeInfo::GetTypeComp
3842 * Retrieves the ITypeComp interface for the type description, which enables a
3843 * client compiler to bind to the type description's members.
3846 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3847 ITypeComp * *ppTComp)
3849 ICOM_THIS( ITypeInfoImpl, iface);
3850 FIXME("(%p) stub!\n", This);
3854 /* ITypeInfo::GetFuncDesc
3856 * Retrieves the FUNCDESC structure that contains information about a
3857 * specified function.
3860 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3861 LPFUNCDESC *ppFuncDesc)
3863 ICOM_THIS( ITypeInfoImpl, iface);
3865 TLBFuncDesc * pFDesc;
3866 TRACE("(%p) index %d\n", This, index);
3867 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3870 /* FIXME: must do a copy here */
3871 *ppFuncDesc=&pFDesc->funcdesc;
3874 return E_INVALIDARG;
3877 /* ITypeInfo::GetVarDesc
3879 * Retrieves a VARDESC structure that describes the specified variable.
3882 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3883 LPVARDESC *ppVarDesc)
3885 ICOM_THIS( ITypeInfoImpl, iface);
3887 TLBVarDesc * pVDesc;
3888 TRACE("(%p) index %d\n", This, index);
3889 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3892 /* FIXME: must do a copy here */
3893 *ppVarDesc=&pVDesc->vardesc;
3896 return E_INVALIDARG;
3899 /* ITypeInfo_GetNames
3901 * Retrieves the variable with the specified member ID (or the name of the
3902 * property or method and its parameters) that correspond to the specified
3905 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3906 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3908 ICOM_THIS( ITypeInfoImpl, iface);
3909 TLBFuncDesc * pFDesc;
3910 TLBVarDesc * pVDesc;
3912 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3913 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3916 /* function found, now return function and parameter names */
3917 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3920 *rgBstrNames=SysAllocString(pFDesc->Name);
3922 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3928 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3931 *rgBstrNames=SysAllocString(pVDesc->Name);
3936 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3938 /* recursive search */
3941 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3943 if(SUCCEEDED(result))
3945 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3946 ITypeInfo_Release(pTInfo);
3949 WARN("Could not search inherited interface!\n");
3953 WARN("no names found\n");
3956 return TYPE_E_ELEMENTNOTFOUND;
3963 /* ITypeInfo::GetRefTypeOfImplType
3965 * If a type description describes a COM class, it retrieves the type
3966 * description of the implemented interface types. For an interface,
3967 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3971 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3976 ICOM_THIS( ITypeInfoImpl, iface);
3978 TLBImplType *pImpl = This->impltypelist;
3980 TRACE("(%p) index %d\n", This, index);
3981 if (TRACE_ON(ole)) dump_TypeInfo(This);
3985 /* only valid on dual interfaces;
3986 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3988 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3990 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3991 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3997 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3998 *pRefType = pImpl->hRef;
4003 /* get element n from linked list */
4004 for(i=0; pImpl && i<index; i++)
4006 pImpl = pImpl->next;
4009 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4011 *pRefType = pImpl->hRef;
4013 TRACE("-- 0x%08lx\n", pImpl->hRef );
4020 /* ITypeInfo::GetImplTypeFlags
4022 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4023 * or base interface in a type description.
4025 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4026 UINT index, INT *pImplTypeFlags)
4028 ICOM_THIS( ITypeInfoImpl, iface);
4032 TRACE("(%p) index %d\n", This, index);
4033 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4034 i++, pImpl=pImpl->next)
4036 if(i==index && pImpl){
4037 *pImplTypeFlags=pImpl->implflags;
4041 return TYPE_E_ELEMENTNOTFOUND;
4045 * Maps between member names and member IDs, and parameter names and
4048 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4049 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4051 ICOM_THIS( ITypeInfoImpl, iface);
4052 TLBFuncDesc * pFDesc;
4053 TLBVarDesc * pVDesc;
4056 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4058 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4060 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4061 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4062 for(i=1; i < cNames; i++){
4063 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4064 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4066 if( j<pFDesc->funcdesc.cParams)
4069 ret=DISP_E_UNKNOWNNAME;
4074 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4075 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4076 if(cNames) *pMemId=pVDesc->vardesc.memid;
4080 /* not found, see if this is and interface with an inheritance */
4081 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
4082 This->TypeAttr.cImplTypes ){
4083 /* recursive search */
4085 ret=ITypeInfo_GetRefTypeInfo(iface,
4086 This->impltypelist->hRef, &pTInfo);
4088 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4089 ITypeInfo_Release(pTInfo);
4092 WARN("Could not search inherited interface!\n");
4094 WARN("no names found\n");
4095 return DISP_E_UNKNOWNNAME;
4098 /* ITypeInfo::Invoke
4100 * Invokes a method, or accesses a property of an object, that implements the
4101 * interface described by the type description.
4104 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
4107 if (TRACE_ON(ole)) {
4109 MESSAGE("Calling %p(",func);
4110 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
4119 DWORD (WINAPI *xfunc)() = func;
4124 DWORD (WINAPI *xfunc)(DWORD) = func;
4125 res = xfunc(args[0]);
4129 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
4130 res = xfunc(args[0],args[1]);
4134 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
4135 res = xfunc(args[0],args[1],args[2]);
4139 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
4140 res = xfunc(args[0],args[1],args[2],args[3]);
4144 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4145 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
4149 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4150 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
4154 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4155 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4159 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4160 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4164 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
4165 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4169 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4175 FIXME("unsupported calling convention %d\n",callconv);
4179 TRACE("returns %08lx\n",res);
4183 extern int const _argsize(DWORD vt);
4185 /****************************************************************************
4186 * Helper functions for Dispcall / Invoke, which copies one variant
4187 * with target type onto the argument stack.
4190 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4191 DWORD *argpos, VARIANT *arg, VARTYPE vt
4193 UINT arglen = _argsize(vt)*sizeof(DWORD);
4196 if (V_VT(arg) == vt) {
4197 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4201 if (vt == VT_VARIANT) {
4202 memcpy(argpos, arg, arglen);
4205 /* Deref BYREF vars if there is need */
4206 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4207 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4210 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4211 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4212 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4215 if ((vt == VT_PTR) && tdesc)
4216 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4217 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4222 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4224 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));
4225 memcpy(argpos, &V_UNION(arg,lVal), 4);
4228 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4229 switch (tattr->typekind) {
4231 if (V_VT(arg) == VT_I4) {
4232 memcpy(argpos, &V_UNION(arg,iVal), 4);
4235 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4238 tdesc = &(tattr->tdescAlias);
4239 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4240 ITypeInfo_Release(tinfo2);
4243 case TKIND_INTERFACE:
4244 if (V_VT(arg) == VT_DISPATCH) {
4246 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4247 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4250 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4251 if (SUCCEEDED(hres)) {
4252 memcpy(argpos,&disp,4);
4253 IUnknown_Release(V_UNION(arg,pdispVal));
4256 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4259 if (V_VT(arg) == VT_UNKNOWN) {
4260 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4263 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4265 case TKIND_DISPATCH:
4266 if (V_VT(arg) == VT_DISPATCH) {
4267 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4270 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4273 FIXME("TKIND_RECORD unhandled.\n");
4276 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4282 if (VariantChangeType(arg,arg,0,vt)==S_OK) {
4283 FIXME("argument was coerced in-place (0x%x -> 0x%x); source data has been modified!!!\n", oldvt, vt);
4284 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4287 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4291 /***********************************************************************
4292 * DispCallFunc (OLEAUT32.@)
4296 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4297 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4299 int i, argsize, argspos;
4303 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4304 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4306 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4307 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4309 for (i=0;i<cActuals;i++) {
4310 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4311 dump_Variant(prgpvarg[i]);
4312 argsize += _argsize(prgvt[i]);
4314 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4315 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4317 for (i=0;i<cActuals;i++) {
4318 VARIANT *arg = prgpvarg[i];
4319 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4320 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4321 argspos += _argsize(prgvt[i]);
4324 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4326 _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize,args);
4331 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4332 hres = _invoke((*(DWORD***)pvInstance)[oVft/4],cc,argsize,args);
4333 FIXME("Method returned %lx\n",hres);
4335 HeapFree(GetProcessHeap(),0,args);
4339 static HRESULT WINAPI ITypeInfo_fnInvoke(
4344 DISPPARAMS *pDispParams,
4345 VARIANT *pVarResult,
4346 EXCEPINFO *pExcepInfo,
4349 ICOM_THIS( ITypeInfoImpl, iface);
4350 TLBFuncDesc * pFDesc;
4351 TLBVarDesc * pVDesc;
4355 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4356 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4358 dump_DispParms(pDispParams);
4360 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4361 if (pFDesc->funcdesc.memid == memid) {
4362 if (pFDesc->funcdesc.invkind & dwFlags)
4366 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4367 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4368 switch (pFDesc->funcdesc.funckind) {
4369 case FUNC_PUREVIRTUAL:
4370 case FUNC_VIRTUAL: {
4372 int numargs, numargs2, argspos, args2pos;
4373 DWORD *args , *args2;
4376 numargs = 1; numargs2 = 0;
4377 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4378 if (i<pDispParams->cArgs)
4379 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4381 numargs += 1; /* sizeof(lpvoid) */
4382 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4386 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4387 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4389 args[0] = (DWORD)pIUnk;
4390 argspos = 1; args2pos = 0;
4391 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4392 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4393 if (i<pDispParams->cArgs) {
4394 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4395 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4396 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4397 if (FAILED(hres)) return hres;
4400 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4401 if (tdesc->vt != VT_PTR)
4402 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4403 /*FIXME: give pointers for the rest, so propertyget works*/
4404 args[argspos] = (DWORD)&args2[args2pos];
4406 /* If pointer to variant, pass reference it. */
4407 if ((tdesc->vt == VT_PTR) &&
4408 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4411 args[argspos]= (DWORD)pVarResult;
4416 if (pFDesc->funcdesc.cParamsOpt)
4417 FIXME("Does not support optional parameters (%d)\n",
4418 pFDesc->funcdesc.cParamsOpt
4421 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4422 pFDesc->funcdesc.callconv,
4426 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4428 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4429 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4430 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4431 /* If we are a pointer to a variant, we are done already */
4432 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4435 VariantInit(pVarResult);
4436 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4438 if (tdesc->vt == VT_PTR)
4439 tdesc = tdesc->u.lptdesc;
4440 if (tdesc->vt == VT_USERDEFINED) {
4444 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4446 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4449 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4450 switch (tattr->typekind) {
4452 FIXME("TKIND_ENUM unhandled.\n");
4455 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4456 tdesc = &(tattr->tdescAlias);
4459 case TKIND_INTERFACE:
4460 FIXME("TKIND_INTERFACE unhandled.\n");
4462 case TKIND_DISPATCH:
4463 FIXME("TKIND_DISPATCH unhandled.\n");
4466 FIXME("TKIND_RECORD unhandled.\n");
4469 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4472 ITypeInfo_Release(tinfo2);
4474 V_VT(pVarResult) = tdesc->vt;
4476 /* HACK: VB5 likes this.
4477 * I do not know why. There is 1 example in MSDN which uses
4478 * this which appears broken (mixes int vals and
4481 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4482 V_VT(pVarResult) = VT_DISPATCH;
4483 TRACE("storing into variant:\n");
4484 dump_Variant(pVarResult);
4488 HeapFree(GetProcessHeap(),0,args2);
4489 HeapFree(GetProcessHeap(),0,args);
4492 case FUNC_DISPATCH: {
4496 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4498 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4501 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4502 hr = IDispatch_Invoke(
4503 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4504 pVarResult,pExcepInfo,pArgErr
4507 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4508 IDispatch_Release(disp);
4512 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4516 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4517 if (pVDesc->vardesc.memid == memid) {
4518 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4519 dump_TLBVarDesc(pVDesc);
4524 /* not found, look for it in inherited interfaces */
4525 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4526 /* recursive search */
4529 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4531 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4532 ITypeInfo_Release(pTInfo);
4535 WARN("Could not search inherited interface!\n");
4537 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4538 return DISP_E_MEMBERNOTFOUND;
4541 /* ITypeInfo::GetDocumentation
4543 * Retrieves the documentation string, the complete Help file name and path,
4544 * and the context ID for the Help topic for a specified type description.
4546 * (Can be tested by the Visual Basic Editor in Word for instance.)
4548 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4549 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4550 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4552 ICOM_THIS( ITypeInfoImpl, iface);
4553 TLBFuncDesc * pFDesc;
4554 TLBVarDesc * pVDesc;
4555 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4556 " HelpContext(%p) HelpFile(%p)\n",
4557 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4558 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4560 *pBstrName=SysAllocString(This->Name);
4562 *pBstrDocString=SysAllocString(This->DocString);
4564 *pdwHelpContext=This->dwHelpContext;
4566 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4568 }else {/* for a member */
4569 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4570 if(pFDesc->funcdesc.memid==memid){
4572 *pBstrName = SysAllocString(pFDesc->Name);
4574 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4576 *pdwHelpContext=pFDesc->helpcontext;
4579 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4580 if(pVDesc->vardesc.memid==memid){
4582 *pBstrName = SysAllocString(pVDesc->Name);
4584 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4586 *pdwHelpContext=pVDesc->HelpContext;
4590 return TYPE_E_ELEMENTNOTFOUND;
4593 /* ITypeInfo::GetDllEntry
4595 * Retrieves a description or specification of an entry point for a function
4598 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4599 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4602 ICOM_THIS( ITypeInfoImpl, iface);
4603 TLBFuncDesc *pFDesc;
4605 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4607 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4608 if(pFDesc->funcdesc.memid==memid){
4609 dump_TypeInfo(This);
4610 dump_TLBFuncDescOne(pFDesc);
4612 /* FIXME: This is wrong, but how do you find that out? */
4614 const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4615 *pBstrDllName = SysAllocString(oleaut32W);
4618 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4620 *pBstrName = SysAllocString(pFDesc->Entry);
4628 *pwOrdinal = (DWORD)pFDesc->Entry;
4634 /* ITypeInfo::GetRefTypeInfo
4636 * If a type description references other type descriptions, it retrieves
4637 * the referenced type descriptions.
4639 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4642 ITypeInfo **ppTInfo)
4644 ICOM_THIS( ITypeInfoImpl, iface);
4645 HRESULT result = E_FAIL;
4648 if (hRefType == -1 &&
4649 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4650 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4652 /* when we meet a DUAL dispinterface, we must create the interface
4655 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4658 /* the interface version contains the same information as the dispinterface
4659 * copy the contents of the structs.
4661 *pTypeInfoImpl = *This;
4662 pTypeInfoImpl->ref = 1;
4664 /* change the type to interface */
4665 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4667 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4669 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4674 TLBRefType *pRefType;
4675 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4676 if(pRefType->reference == hRefType)
4680 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4681 if(pRefType && hRefType != -1) {
4682 ITypeLib *pTLib = NULL;
4684 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4686 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4688 if(pRefType->pImpTLInfo->pImpTypeLib) {
4689 TRACE("typeinfo in imported typelib that is already loaded\n");
4690 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4691 ITypeLib2_AddRef((ITypeLib*) pTLib);
4694 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4695 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4696 pRefType->pImpTLInfo->wVersionMajor,
4697 pRefType->pImpTLInfo->wVersionMinor,
4698 pRefType->pImpTLInfo->lcid,
4701 if(!SUCCEEDED(result)) {
4702 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4703 result=LoadTypeLib(libnam, &pTLib);
4704 SysFreeString(libnam);
4706 if(SUCCEEDED(result)) {
4707 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4708 ITypeLib2_AddRef(pTLib);
4712 if(SUCCEEDED(result)) {
4713 if(pRefType->index == TLB_REF_USE_GUID)
4714 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4718 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4722 ITypeLib2_Release(pTLib);
4726 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4727 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4731 /* ITypeInfo::AddressOfMember
4733 * Retrieves the addresses of static functions or variables, such as those
4736 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4737 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4739 ICOM_THIS( ITypeInfoImpl, iface);
4740 FIXME("(%p) stub!\n", This);
4744 /* ITypeInfo::CreateInstance
4746 * Creates a new instance of a type that describes a component object class
4749 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4750 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4752 ICOM_THIS( ITypeInfoImpl, iface);
4753 FIXME("(%p) stub!\n", This);
4757 /* ITypeInfo::GetMops
4759 * Retrieves marshaling information.
4761 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4764 ICOM_THIS( ITypeInfoImpl, iface);
4765 FIXME("(%p) stub!\n", This);
4769 /* ITypeInfo::GetContainingTypeLib
4771 * Retrieves the containing type library and the index of the type description
4772 * within that type library.
4774 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4775 ITypeLib * *ppTLib, UINT *pIndex)
4777 ICOM_THIS( ITypeInfoImpl, iface);
4779 return E_INVALIDARG;
4780 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4781 *pIndex=This->index;
4782 ITypeLib2_AddRef(*ppTLib);
4783 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4787 /* ITypeInfo::ReleaseTypeAttr
4789 * Releases a TYPEATTR previously returned by GetTypeAttr.
4792 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4793 TYPEATTR* pTypeAttr)
4795 ICOM_THIS( ITypeInfoImpl, iface);
4796 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4799 /* ITypeInfo::ReleaseFuncDesc
4801 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4803 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
4805 FUNCDESC *pFuncDesc)
4807 ICOM_THIS( ITypeInfoImpl, iface);
4808 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4811 /* ITypeInfo::ReleaseVarDesc
4813 * Releases a VARDESC previously returned by GetVarDesc.
4815 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4818 ICOM_THIS( ITypeInfoImpl, iface);
4819 TRACE("(%p)->(%p)\n", This, pVarDesc);
4822 /* ITypeInfo2::GetTypeKind
4824 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4827 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4828 TYPEKIND *pTypeKind)
4830 ICOM_THIS( ITypeInfoImpl, iface);
4831 *pTypeKind=This->TypeAttr.typekind;
4832 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4836 /* ITypeInfo2::GetTypeFlags
4838 * Returns the type flags without any allocations. This returns a DWORD type
4839 * flag, which expands the type flags without growing the TYPEATTR (type
4843 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
4845 ICOM_THIS( ITypeInfoImpl, iface);
4846 *pTypeFlags=This->TypeAttr.wTypeFlags;
4847 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
4851 /* ITypeInfo2::GetFuncIndexOfMemId
4852 * Binds to a specific member based on a known DISPID, where the member name
4853 * is not known (for example, when binding to a default member).
4856 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4857 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4859 ICOM_THIS( ITypeInfoImpl, iface);
4860 TLBFuncDesc *pFuncInfo;
4863 /* FIXME: should check for invKind??? */
4864 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4865 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4871 result=E_INVALIDARG;
4873 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4874 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4878 /* TypeInfo2::GetVarIndexOfMemId
4880 * Binds to a specific member based on a known DISPID, where the member name
4881 * is not known (for example, when binding to a default member).
4884 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4885 MEMBERID memid, UINT *pVarIndex)
4887 ICOM_THIS( ITypeInfoImpl, iface);
4888 TLBVarDesc *pVarInfo;
4891 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4892 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4899 result=E_INVALIDARG;
4901 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4902 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4906 /* ITypeInfo2::GetCustData
4908 * Gets the custom data
4910 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4915 ICOM_THIS( ITypeInfoImpl, iface);
4916 TLBCustData *pCData;
4918 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4919 if( IsEqualIID(guid, &pCData->guid)) break;
4921 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4925 VariantInit( pVarVal);
4926 VariantCopy( pVarVal, &pCData->data);
4929 return E_INVALIDARG; /* FIXME: correct? */
4932 /* ITypeInfo2::GetFuncCustData
4934 * Gets the custom data
4936 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4942 ICOM_THIS( ITypeInfoImpl, iface);
4943 TLBCustData *pCData=NULL;
4944 TLBFuncDesc * pFDesc;
4946 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4947 pFDesc=pFDesc->next);
4950 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4951 if( IsEqualIID(guid, &pCData->guid)) break;
4953 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4956 VariantInit( pVarVal);
4957 VariantCopy( pVarVal, &pCData->data);
4960 return E_INVALIDARG; /* FIXME: correct? */
4963 /* ITypeInfo2::GetParamCustData
4965 * Gets the custom data
4967 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4974 ICOM_THIS( ITypeInfoImpl, iface);
4975 TLBCustData *pCData=NULL;
4976 TLBFuncDesc * pFDesc;
4979 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4981 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4982 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4983 pCData = pCData->next)
4984 if( IsEqualIID(guid, &pCData->guid)) break;
4986 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4990 VariantInit( pVarVal);
4991 VariantCopy( pVarVal, &pCData->data);
4994 return E_INVALIDARG; /* FIXME: correct? */
4997 /* ITypeInfo2::GetVarCustData
4999 * Gets the custom data
5001 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5007 ICOM_THIS( ITypeInfoImpl, iface);
5008 TLBCustData *pCData=NULL;
5009 TLBVarDesc * pVDesc;
5012 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5016 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5018 if( IsEqualIID(guid, &pCData->guid)) break;
5022 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5026 VariantInit( pVarVal);
5027 VariantCopy( pVarVal, &pCData->data);
5030 return E_INVALIDARG; /* FIXME: correct? */
5033 /* ITypeInfo2::GetImplCustData
5035 * Gets the custom data
5037 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5043 ICOM_THIS( ITypeInfoImpl, iface);
5044 TLBCustData *pCData=NULL;
5045 TLBImplType * pRDesc;
5048 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5052 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5054 if( IsEqualIID(guid, &pCData->guid)) break;
5058 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5062 VariantInit( pVarVal);
5063 VariantCopy( pVarVal, &pCData->data);
5066 return E_INVALIDARG; /* FIXME: correct? */
5069 /* ITypeInfo2::GetDocumentation2
5071 * Retrieves the documentation string, the complete Help file name and path,
5072 * the localization context to use, and the context ID for the library Help
5073 * topic in the Help file.
5076 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5080 BSTR *pbstrHelpString,
5081 DWORD *pdwHelpStringContext,
5082 BSTR *pbstrHelpStringDll)
5084 ICOM_THIS( ITypeInfoImpl, iface);
5085 TLBFuncDesc * pFDesc;
5086 TLBVarDesc * pVDesc;
5087 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5088 "HelpStringContext(%p) HelpStringDll(%p)\n",
5089 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5090 pbstrHelpStringDll );
5091 /* the help string should be obtained from the helpstringdll,
5092 * using the _DLLGetDocumentation function, based on the supplied
5093 * lcid. Nice to do sometime...
5095 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5097 *pbstrHelpString=SysAllocString(This->Name);
5098 if(pdwHelpStringContext)
5099 *pdwHelpStringContext=This->dwHelpStringContext;
5100 if(pbstrHelpStringDll)
5101 *pbstrHelpStringDll=
5102 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5104 }else {/* for a member */
5105 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5106 if(pFDesc->funcdesc.memid==memid){
5108 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5109 if(pdwHelpStringContext)
5110 *pdwHelpStringContext=pFDesc->HelpStringContext;
5111 if(pbstrHelpStringDll)
5112 *pbstrHelpStringDll=
5113 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5116 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5117 if(pVDesc->vardesc.memid==memid){
5119 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5120 if(pdwHelpStringContext)
5121 *pdwHelpStringContext=pVDesc->HelpStringContext;
5122 if(pbstrHelpStringDll)
5123 *pbstrHelpStringDll=
5124 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5128 return TYPE_E_ELEMENTNOTFOUND;
5131 /* ITypeInfo2::GetAllCustData
5133 * Gets all custom data items for the Type info.
5136 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5138 CUSTDATA *pCustData)
5140 ICOM_THIS( ITypeInfoImpl, iface);
5141 TLBCustData *pCData;
5144 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5146 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5147 if(pCustData->prgCustData ){
5148 pCustData->cCustData=This->ctCustData;
5149 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5150 pCustData->prgCustData[i].guid=pCData->guid;
5151 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5154 ERR(" OUT OF MEMORY! \n");
5155 return E_OUTOFMEMORY;
5160 /* ITypeInfo2::GetAllFuncCustData
5162 * Gets all custom data items for the specified Function
5165 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5168 CUSTDATA *pCustData)
5170 ICOM_THIS( ITypeInfoImpl, iface);
5171 TLBCustData *pCData;
5172 TLBFuncDesc * pFDesc;
5174 TRACE("(%p) index %d\n", This, index);
5175 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5176 pFDesc=pFDesc->next)
5179 pCustData->prgCustData =
5180 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5181 if(pCustData->prgCustData ){
5182 pCustData->cCustData=pFDesc->ctCustData;
5183 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5184 pCData = pCData->next){
5185 pCustData->prgCustData[i].guid=pCData->guid;
5186 VariantCopy(& pCustData->prgCustData[i].varValue,
5190 ERR(" OUT OF MEMORY! \n");
5191 return E_OUTOFMEMORY;
5195 return TYPE_E_ELEMENTNOTFOUND;
5198 /* ITypeInfo2::GetAllParamCustData
5200 * Gets all custom data items for the Functions
5203 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5204 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5206 ICOM_THIS( ITypeInfoImpl, iface);
5207 TLBCustData *pCData=NULL;
5208 TLBFuncDesc * pFDesc;
5210 TRACE("(%p) index %d\n", This, indexFunc);
5211 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5212 pFDesc=pFDesc->next)
5214 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5215 pCustData->prgCustData =
5216 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5217 sizeof(CUSTDATAITEM));
5218 if(pCustData->prgCustData ){
5219 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5220 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5221 pCData; i++, pCData = pCData->next){
5222 pCustData->prgCustData[i].guid=pCData->guid;
5223 VariantCopy(& pCustData->prgCustData[i].varValue,
5227 ERR(" OUT OF MEMORY! \n");
5228 return E_OUTOFMEMORY;
5232 return TYPE_E_ELEMENTNOTFOUND;
5235 /* ITypeInfo2::GetAllVarCustData
5237 * Gets all custom data items for the specified Variable
5240 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5241 UINT index, CUSTDATA *pCustData)
5243 ICOM_THIS( ITypeInfoImpl, iface);
5244 TLBCustData *pCData;
5245 TLBVarDesc * pVDesc;
5247 TRACE("(%p) index %d\n", This, index);
5248 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5249 pVDesc=pVDesc->next)
5252 pCustData->prgCustData =
5253 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5254 if(pCustData->prgCustData ){
5255 pCustData->cCustData=pVDesc->ctCustData;
5256 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5257 pCData = pCData->next){
5258 pCustData->prgCustData[i].guid=pCData->guid;
5259 VariantCopy(& pCustData->prgCustData[i].varValue,
5263 ERR(" OUT OF MEMORY! \n");
5264 return E_OUTOFMEMORY;
5268 return TYPE_E_ELEMENTNOTFOUND;
5271 /* ITypeInfo2::GetAllImplCustData
5273 * Gets all custom data items for the specified implementation type
5276 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5279 CUSTDATA *pCustData)
5281 ICOM_THIS( ITypeInfoImpl, iface);
5282 TLBCustData *pCData;
5283 TLBImplType * pRDesc;
5285 TRACE("(%p) index %d\n", This, index);
5286 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5287 pRDesc=pRDesc->next)
5290 pCustData->prgCustData =
5291 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5292 if(pCustData->prgCustData ){
5293 pCustData->cCustData=pRDesc->ctCustData;
5294 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5295 pCData = pCData->next){
5296 pCustData->prgCustData[i].guid=pCData->guid;
5297 VariantCopy(& pCustData->prgCustData[i].varValue,
5301 ERR(" OUT OF MEMORY! \n");
5302 return E_OUTOFMEMORY;
5306 return TYPE_E_ELEMENTNOTFOUND;
5309 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5311 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5313 ITypeInfo_fnQueryInterface,
5315 ITypeInfo_fnRelease,
5317 ITypeInfo_fnGetTypeAttr,
5318 ITypeInfo_fnGetTypeComp,
5319 ITypeInfo_fnGetFuncDesc,
5320 ITypeInfo_fnGetVarDesc,
5321 ITypeInfo_fnGetNames,
5322 ITypeInfo_fnGetRefTypeOfImplType,
5323 ITypeInfo_fnGetImplTypeFlags,
5324 ITypeInfo_fnGetIDsOfNames,
5326 ITypeInfo_fnGetDocumentation,
5327 ITypeInfo_fnGetDllEntry,
5328 ITypeInfo_fnGetRefTypeInfo,
5329 ITypeInfo_fnAddressOfMember,
5330 ITypeInfo_fnCreateInstance,
5331 ITypeInfo_fnGetMops,
5332 ITypeInfo_fnGetContainingTypeLib,
5333 ITypeInfo_fnReleaseTypeAttr,
5334 ITypeInfo_fnReleaseFuncDesc,
5335 ITypeInfo_fnReleaseVarDesc,
5337 ITypeInfo2_fnGetTypeKind,
5338 ITypeInfo2_fnGetTypeFlags,
5339 ITypeInfo2_fnGetFuncIndexOfMemId,
5340 ITypeInfo2_fnGetVarIndexOfMemId,
5341 ITypeInfo2_fnGetCustData,
5342 ITypeInfo2_fnGetFuncCustData,
5343 ITypeInfo2_fnGetParamCustData,
5344 ITypeInfo2_fnGetVarCustData,
5345 ITypeInfo2_fnGetImplTypeCustData,
5346 ITypeInfo2_fnGetDocumentation2,
5347 ITypeInfo2_fnGetAllCustData,
5348 ITypeInfo2_fnGetAllFuncCustData,
5349 ITypeInfo2_fnGetAllParamCustData,
5350 ITypeInfo2_fnGetAllVarCustData,
5351 ITypeInfo2_fnGetAllImplTypeCustData,