4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * --------------------------------------------------------------------------------------
10 * Known problems (2000, Francois Jacques)
12 * - Tested using OLEVIEW (Platform SDK tool) only.
14 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
15 * creating by doing a straight copy of the dispinterface instance and just changing
16 * its typekind. Pointed structures aren't copied - only the address of the pointers.
17 * So when you release the dispinterface, you delete the vtable-interface structures
18 * as well... fortunately, clean up of structures is not implemented.
20 * - locale stuff is partially implemented but hasn't been tested.
22 * - typelib file is still read in its entirety, but it is released now.
23 * - some garbage is read from function names on some very rare occasions.
25 * --------------------------------------------------------------------------------------
26 * Known problems left from previous implementation (1999, Rein Klazes) :
28 * -. Data structures are straightforward, but slow for look-ups.
29 * -. (related) nothing is hashed
30 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
31 * of them I don't know yet how to implement them.
32 * -. Most error return values are just guessed not checked with windows
34 * -. didn't bother with a c++ interface
35 * -. lousy fatal error handling
36 * -. some methods just return pointers to internal data structures, this is
37 * partly laziness, partly I want to check how windows does it.
49 #include "winnls.h" /* for PRIMARYLANGID */
50 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
53 #include "wine/unicode.h"
54 #include "wine/obj_base.h"
58 #include "debugtools.h"
61 DEFAULT_DEBUG_CHANNEL(ole);
62 DECLARE_DEBUG_CHANNEL(typelib);
64 /****************************************************************************
65 * QueryPathOfRegTypeLib [TYPELIB.14]
67 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
72 QueryPathOfRegTypeLib16(
73 REFGUID guid, /* [in] referenced guid */
74 WORD wMaj, /* [in] major version */
75 WORD wMin, /* [in] minor version */
76 LCID lcid, /* [in] locale id */
77 LPBSTR16 path /* [out] path of typelib */
80 char typelibkey[100],pathname[260];
86 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
87 guid->Data1, guid->Data2, guid->Data3,
88 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
89 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
92 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
93 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
96 plen = sizeof(pathname);
97 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
98 /* try again without lang specific id */
100 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
101 FIXME("key %s not found\n",typelibkey);
104 *path = SysAllocString16(pathname);
108 /****************************************************************************
109 * QueryPathOfRegTypeLib [OLEAUT32.164]
114 QueryPathOfRegTypeLib(
115 REFGUID guid, /* [in] referenced guid */
116 WORD wMaj, /* [in] major version */
117 WORD wMin, /* [in] minor version */
118 LCID lcid, /* [in] locale id */
119 LPBSTR path ) /* [out] path of typelib */
121 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
122 string termination character on output strings */
126 DWORD dwPathLen = _MAX_PATH;
130 char szTypeLibKey[100];
131 char szPath[dwPathLen];
139 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
145 sprintf(szTypeLibKey,
146 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
147 guid->Data1, guid->Data2, guid->Data3,
148 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
149 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
154 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
158 else if (myLCID == lcid)
160 /* try with sub-langid */
161 myLCID = SUBLANGID(lcid);
163 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
165 /* try with system langid */
175 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
176 BSTR bstrPath = SysAllocStringLen(NULL,len);
178 MultiByteToWideChar(CP_ACP,
190 TRACE_(typelib)("%s not found\n", szTypeLibKey);
195 /******************************************************************************
196 * CreateTypeLib [OLEAUT32.160] creates a typelib
202 HRESULT WINAPI CreateTypeLib(
203 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
205 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
208 /******************************************************************************
209 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
211 * Docs: OLECHAR FAR* szFile
212 * Docs: iTypeLib FAR* FAR* pptLib
218 HRESULT WINAPI LoadTypeLib16(
219 LPOLESTR szFile, /* [in] Name of file to load from */
220 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
222 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
230 /******************************************************************************
231 * LoadTypeLib [OLEAUT32.161]
232 * Loads and registers a type library
234 * Docs: OLECHAR FAR* szFile
235 * Docs: iTypeLib FAR* FAR* pptLib
241 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
243 HRESULT WINAPI LoadTypeLib(
244 const OLECHAR *szFile,/* [in] Name of file to load from */
245 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
248 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
251 /******************************************************************************
252 * LoadTypeLibEx [OLEAUT32.183]
253 * Loads and optionally registers a type library
259 HRESULT WINAPI LoadTypeLibEx(
260 LPCOLESTR szFile, /* [in] Name of file to load from */
261 REGKIND regkind, /* [in] Specify kind of registration */
262 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
264 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
268 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
270 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
273 /* Look for a trailing '\\' followed by an index */
274 pIndexStr = strrchrW(szFile, '\\');
275 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
276 index = wcstol(pIndexStr, NULL, 10);
277 memcpy(szFileCopy, szFile,
278 (pIndexStr - szFile - 1) * sizeof(WCHAR));
279 szFileCopy[pIndexStr - szFile - 1] = '\0';
280 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
282 return TYPE_E_CANTLOADLIBRARY;
283 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
284 return TYPE_E_CANTLOADLIBRARY;
286 return TYPE_E_CANTLOADLIBRARY;
289 TRACE("File %s index %d\n", debugstr_w(szPath), index);
291 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
296 case REGKIND_DEFAULT:
297 /* FIXME: is this correct? */
298 if (!szFile || !szFile[0] ||
299 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
301 /* else fall-through */
302 case REGKIND_REGISTER:
303 /* FIXME: Help path? */
304 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
306 IUnknown_Release(*pptLib);
314 TRACE(" returns %08lx\n",res);
318 /******************************************************************************
319 * LoadRegTypeLib [OLEAUT32.162]
321 HRESULT WINAPI LoadRegTypeLib(
322 REFGUID rguid, /* [in] referenced guid */
323 WORD wVerMajor, /* [in] major version */
324 WORD wVerMinor, /* [in] minor version */
325 LCID lcid, /* [in] locale id */
326 ITypeLib **ppTLib) /* [out] path of typelib */
329 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
333 res= LoadTypeLib(bstr, ppTLib);
337 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
343 /******************************************************************************
344 * RegisterTypeLib [OLEAUT32.163]
345 * Adds information about a type library to the System Registry
347 * Docs: ITypeLib FAR * ptlib
348 * Docs: OLECHAR FAR* szFullPath
349 * Docs: OLECHAR FAR* szHelpDir
355 HRESULT WINAPI RegisterTypeLib(
356 ITypeLib * ptlib, /* [in] Pointer to the library*/
357 OLECHAR * szFullPath, /* [in] full Path of the library*/
358 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
369 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
371 if (ptlib == NULL || szFullPath == NULL)
374 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
377 StringFromGUID2(&attr->guid, guid, 80);
378 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
379 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
380 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
381 HeapFree(GetProcessHeap(), 0, guidA);
384 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
385 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
389 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
391 if (RegSetValueExW(key, NULL, 0, REG_SZ,
392 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
400 /* FIXME: This *seems* to be 0 always, not sure though */
401 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
402 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
404 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
405 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
413 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
414 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
417 /* FIXME: is %u correct? */
418 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
419 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
420 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
428 /* register OLE Automation-compatible interfaces for this typelib */
429 types = ITypeLib_GetTypeInfoCount(ptlib);
430 for (tidx=0; tidx<types; tidx++) {
431 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
432 LPOLESTR name = NULL;
433 ITypeInfo *tinfo = NULL;
435 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
437 case TKIND_INTERFACE:
438 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
439 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
442 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
443 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
446 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
447 /* coclasses should probably not be registered? */
450 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
454 TYPEATTR *tattr = NULL;
455 ITypeInfo_GetTypeAttr(tinfo, &tattr);
457 TRACE_(typelib)("guid=%s, flags=%04x\n",
458 debugstr_guid(&tattr->guid),
460 if (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION) {
461 /* register interface<->typelib coupling */
462 StringFromGUID2(&tattr->guid, guid, 80);
463 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
464 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
465 HeapFree(GetProcessHeap(), 0, guidA);
467 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
468 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
470 RegSetValueExW(key, NULL, 0, REG_SZ,
471 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
473 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
474 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
475 RegSetValueExA(subKey, NULL, 0, REG_SZ,
479 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
480 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
481 RegSetValueExA(subKey, NULL, 0, REG_SZ,
486 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
487 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
489 StringFromGUID2(&attr->guid, guid, 80);
490 snprintf(ver, sizeof(ver), "%x.%x",
491 attr->wMajorVerNum, attr->wMinorVerNum);
492 RegSetValueExW(subKey, NULL, 0, REG_SZ,
493 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
494 RegSetValueExA(subKey, "Version", 0, REG_SZ,
501 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
503 ITypeInfo_Release(tinfo);
510 ITypeLib_ReleaseTLibAttr(ptlib, attr);
516 /******************************************************************************
517 * UnRegisterTypeLib [OLEAUT32.186]
518 * Removes information about a type library from the System Registry
525 HRESULT WINAPI UnRegisterTypeLib(
526 REFGUID libid, /* [in] Guid of the library */
527 WORD wVerMajor, /* [in] major version */
528 WORD wVerMinor, /* [in] minor version */
529 LCID lcid, /* [in] locale id */
532 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
533 return S_OK; /* FIXME: pretend everything is OK */
536 /****************************************************************************
537 * OaBuildVersion (TYPELIB.15)
539 * known TYPELIB.DLL versions:
541 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
542 * OLE 2.02 1993-94 02 3002
545 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
546 * OLE 2.1 NT 1993-95 ?? ???
547 * OLE 2.3.1 W95 23 700
548 * OLE2 4.0 NT4SP6 1993-98 40 4277
550 DWORD WINAPI OaBuildVersion16(void)
552 /* FIXME: I'd like to return the highest currently known version value
553 * in case the user didn't force a --winver, but I don't know how
554 * to retrieve the "versionForced" info from misc/version.c :(
555 * (this would be useful in other places, too) */
556 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
557 switch(GetVersion() & 0x8000ffff) /* mask off build number */
559 case 0x80000a03: /* WIN31 */
560 return MAKELONG(3027, 3); /* WfW 3.11 */
561 case 0x80000004: /* WIN95 */
562 return MAKELONG(700, 23); /* Win95A */
563 case 0x80000a04: /* WIN98 */
564 return MAKELONG(3024, 10); /* W98 SE */
565 case 0x00000004: /* NT4 */
566 return MAKELONG(4277, 40); /* NT4 SP6 */
568 FIXME("Version value not known yet. Please investigate it!\n");
573 /* for better debugging info leave the static out for the time being */
576 /*======================= ITypeLib implementation =======================*/
578 typedef struct tagTLBCustData
582 struct tagTLBCustData* next;
585 /* data structure for import typelibs */
586 typedef struct tagTLBImpLib
588 int offset; /* offset in the file (MSFT)
589 offset in nametable (SLTG)
590 just used to identify library while reading
592 GUID guid; /* libid */
593 BSTR name; /* name */
595 LCID lcid; /* lcid of imported typelib */
597 WORD wVersionMajor; /* major version number */
598 WORD wVersionMinor; /* minor version number */
600 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
601 NULL if not yet loaded */
602 struct tagTLBImpLib * next;
605 /* internal ITypeLib data */
606 typedef struct tagITypeLibImpl
608 ICOM_VFIELD(ITypeLib2);
610 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
612 /* strings can be stored in tlb as multibyte strings BUT they are *always*
613 * exported to the application as a UNICODE string.
619 unsigned long dwHelpContext;
620 int TypeInfoCount; /* nr of typeinfo's in librarry */
621 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
622 int ctCustData; /* number of items in cust data list */
623 TLBCustData * pCustData; /* linked list to cust data */
624 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
625 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
626 libary. Only used while read MSFT
630 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
632 /* ITypeLib methods */
633 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
634 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
636 /*======================= ITypeInfo implementation =======================*/
638 /* data for refernced types */
639 typedef struct tagTLBRefType
641 INT index; /* Type index for internal ref or for external ref
642 it the format is SLTG. -2 indicates to
645 GUID guid; /* guid of the referenced type */
646 /* if index == TLB_REF_USE_GUID */
648 HREFTYPE reference; /* The href of this ref */
649 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
650 TLB_REF_INTERNAL for internal refs
651 TLB_REF_NOT_FOUND for broken refs */
653 struct tagTLBRefType * next;
656 #define TLB_REF_USE_GUID -2
658 #define TLB_REF_INTERNAL (void*)-2
659 #define TLB_REF_NOT_FOUND (void*)-1
661 /* internal Parameter data */
662 typedef struct tagTLBParDesc
666 TLBCustData * pCustData; /* linked list to cust data */
669 /* internal Function data */
670 typedef struct tagTLBFuncDesc
672 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
673 BSTR Name; /* the name of this function */
674 TLBParDesc *pParamDesc; /* array with param names and custom data */
676 int HelpStringContext;
678 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
680 TLBCustData * pCustData; /* linked list to cust data; */
681 struct tagTLBFuncDesc * next;
684 /* internal Variable data */
685 typedef struct tagTLBVarDesc
687 VARDESC vardesc; /* lots of info on the variable and its attributes. */
688 BSTR Name; /* the name of this variable */
690 int HelpStringContext; /* FIXME: where? */
693 TLBCustData * pCustData;/* linked list to cust data; */
694 struct tagTLBVarDesc * next;
697 /* internal implemented interface data */
698 typedef struct tagTLBImplType
700 HREFTYPE hRef; /* hRef of interface */
701 int implflags; /* IMPLFLAG_*s */
703 TLBCustData * pCustData;/* linked list to custom data; */
704 struct tagTLBImplType *next;
707 /* internal TypeInfo data */
708 typedef struct tagITypeInfoImpl
710 ICOM_VFIELD(ITypeInfo2);
712 TYPEATTR TypeAttr ; /* _lots_ of type information. */
713 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
714 int index; /* index in this typelib; */
715 /* type libs seem to store the doc strings in ascii
716 * so why should we do it in unicode?
720 unsigned long dwHelpContext;
721 unsigned long dwHelpStringContext;
724 TLBFuncDesc * funclist; /* linked list with function descriptions */
727 TLBVarDesc * varlist; /* linked list with variable descriptions */
729 /* Implemented Interfaces */
730 TLBImplType * impltypelist;
732 TLBRefType * reflist;
734 TLBCustData * pCustData; /* linked list to cust data; */
735 struct tagITypeInfoImpl * next;
738 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
740 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
742 typedef struct tagTLBContext
744 unsigned int oStart; /* start of TLB in file */
745 unsigned int pos; /* current pos */
746 unsigned int length; /* total length */
747 void *mapping; /* memory mapping */
748 MSFT_SegDir * pTblDir;
749 ITypeLibImpl* pLibInfo;
753 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
758 static void dump_VarType(VARTYPE vt,char *szVarType) {
759 /* FIXME : we could have better trace here, depending on the VARTYPE
762 if (vt & VT_RESERVED)
763 szVarType += strlen(strcpy(szVarType, "reserved | "));
765 szVarType += strlen(strcpy(szVarType, "ref to "));
767 szVarType += strlen(strcpy(szVarType, "array of "));
769 szVarType += strlen(strcpy(szVarType, "vector of "));
770 switch(vt & VT_TYPEMASK) {
771 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
772 case VT_I2: sprintf(szVarType, "VT_I2"); break;
773 case VT_I4: sprintf(szVarType, "VT_I4"); break;
774 case VT_R4: sprintf(szVarType, "VT_R4"); break;
775 case VT_R8: sprintf(szVarType, "VT_R8"); break;
776 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
777 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
778 case VT_CY: sprintf(szVarType, "VT_CY"); break;
779 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
780 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
781 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
782 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
783 case VT_I1: sprintf(szVarType, "VT_I1"); break;
784 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
785 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
786 case VT_INT: sprintf(szVarType, "VT_INT"); break;
787 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
788 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
789 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
790 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
791 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
795 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
796 if (pTD->vt & VT_RESERVED)
797 szVarType += strlen(strcpy(szVarType, "reserved | "));
798 if (pTD->vt & VT_BYREF)
799 szVarType += strlen(strcpy(szVarType, "ref to "));
800 if (pTD->vt & VT_ARRAY)
801 szVarType += strlen(strcpy(szVarType, "array of "));
802 if (pTD->vt & VT_VECTOR)
803 szVarType += strlen(strcpy(szVarType, "vector of "));
804 switch(pTD->vt & VT_TYPEMASK) {
805 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
806 case VT_I2: sprintf(szVarType, "VT_I2"); break;
807 case VT_I4: sprintf(szVarType, "VT_I4"); break;
808 case VT_R4: sprintf(szVarType, "VT_R4"); break;
809 case VT_R8: sprintf(szVarType, "VT_R8"); break;
810 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
811 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
812 case VT_CY: sprintf(szVarType, "VT_CY"); break;
813 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
814 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
815 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
816 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
817 case VT_I1: sprintf(szVarType, "VT_I1"); break;
818 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
819 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
820 case VT_INT: sprintf(szVarType, "VT_INT"); break;
821 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
822 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
823 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
824 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
825 pTD->u.hreftype); break;
826 case VT_PTR: sprintf(szVarType, "ptr to ");
827 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
829 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
830 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
832 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
833 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
834 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
837 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
841 static void dump_ELEMDESC(ELEMDESC *edesc) {
843 dump_TypeDesc(&edesc->tdesc,buf);
844 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
845 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
846 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
848 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
850 MESSAGE("memid is %08lx\n",funcdesc->memid);
851 for (i=0;i<funcdesc->cParams;i++) {
852 MESSAGE("Param %d:\n",i);
853 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
855 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
856 switch (funcdesc->funckind) {
857 case FUNC_VIRTUAL: MESSAGE("virtual");break;
858 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
859 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
860 case FUNC_STATIC: MESSAGE("static");break;
861 case FUNC_DISPATCH: MESSAGE("dispatch");break;
862 default: MESSAGE("unknown");break;
864 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
865 switch (funcdesc->invkind) {
866 case INVOKE_FUNC: MESSAGE("func");break;
867 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
868 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
869 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
871 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
872 switch (funcdesc->callconv) {
873 case CC_CDECL: MESSAGE("cdecl");break;
874 case CC_PASCAL: MESSAGE("pascal");break;
875 case CC_STDCALL: MESSAGE("stdcall");break;
876 case CC_SYSCALL: MESSAGE("syscall");break;
879 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
880 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
881 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
883 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
886 if (!TRACE_ON(typelib))
888 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
889 for (i=0;i<pfd->funcdesc.cParams;i++)
890 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
893 dump_FUNCDESC(&(pfd->funcdesc));
895 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
896 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
898 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
902 dump_TLBFuncDescOne(pfd);
906 static void dump_TLBVarDesc(TLBVarDesc * pvd)
910 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
915 static void dump_TLBImpLib(TLBImpLib *import)
917 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
918 debugstr_w(import->name));
919 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
920 import->wVersionMinor, import->lcid, import->offset);
923 static void dump_TLBRefType(TLBRefType * prt)
927 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
929 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
931 TRACE_(typelib)("type no: %d\n", prt->index);
933 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
934 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
935 TRACE_(typelib)("in lib\n");
936 dump_TLBImpLib(prt->pImpTLInfo);
942 static void dump_TLBImplType(TLBImplType * impl)
946 "implementing/inheriting interface hRef = %lx implflags %x\n",
947 impl->hRef, impl->implflags);
952 static void dump_Variant(VARIANT * pvar)
957 TRACE("(%p)\n", pvar);
961 ZeroMemory(szVarType, sizeof(szVarType));
963 /* FIXME : we could have better trace here, depending on the VARTYPE
966 dump_VarType(V_VT(pvar),szVarType);
968 TRACE("VARTYPE: %s\n", szVarType);
970 if (V_VT(pvar) & VT_BYREF) {
971 ref = V_UNION(pvar, byref);
974 else ref = &V_UNION(pvar, cVal);
976 if (V_VT(pvar) & VT_ARRAY) {
980 if (V_VT(pvar) & VT_VECTOR) {
988 TRACE("%d\n", *(short*)ref);
992 TRACE("%d\n", *(INT*)ref);
996 TRACE("%3.3e\n", *(float*)ref);
1000 TRACE("%3.3e\n", *(double*)ref);
1004 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1008 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1013 TRACE("%p\n", *(LPVOID*)ref);
1017 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1021 TRACE("(?)%ld\n", *(long*)ref);
1026 static void dump_DispParms(DISPPARAMS * pdp)
1030 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1032 while (index < pdp->cArgs)
1034 dump_Variant( &pdp->rgvarg[index] );
1039 static char * typekind_desc[] =
1052 static void dump_TypeInfo(ITypeInfoImpl * pty)
1054 TRACE("%p ref=%u\n", pty, pty->ref);
1055 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1056 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1057 TRACE("fct:%u var:%u impl:%u\n",
1058 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1059 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1060 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1061 dump_TLBFuncDesc(pty->funclist);
1062 dump_TLBVarDesc(pty->varlist);
1063 dump_TLBImplType(pty->impltypelist);
1066 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1068 /* VT_LPWSTR is largest type that */
1069 /* may appear in type description*/
1070 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1071 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1072 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1073 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1074 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1075 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1079 static void TLB_abort()
1083 static void * TLB_Alloc(unsigned size)
1086 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1088 ERR("cannot allocate memory\n");
1093 static void TLB_Free(void * ptr)
1095 HeapFree(GetProcessHeap(), 0, ptr);
1099 /**********************************************************************
1101 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1104 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1106 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1107 pcx->pos, count, pcx->oStart, pcx->length, where);
1109 if (where != DO_NOT_SEEK)
1111 where += pcx->oStart;
1112 if (where > pcx->length)
1115 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1120 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1121 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1126 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1128 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1130 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1131 memset(pGuid,0, sizeof(GUID));
1134 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1137 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1140 MSFT_NameIntro niName;
1142 WCHAR* pwstring = NULL;
1143 BSTR bstrName = NULL;
1145 MSFT_Read(&niName, sizeof(niName), pcx,
1146 pcx->pTblDir->pNametab.offset+offset);
1147 niName.namelen &= 0xFF; /* FIXME: correct ? */
1148 name=TLB_Alloc((niName.namelen & 0xff) +1);
1149 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1150 name[niName.namelen & 0xff]='\0';
1152 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1155 /* no invalid characters in string */
1158 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1160 /* don't check for invalid character since this has been done previously */
1161 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1163 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1164 lengthInChars = SysStringLen(bstrName);
1165 HeapFree(GetProcessHeap(), 0, pwstring);
1168 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1172 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1179 if(offset<0) return NULL;
1180 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1181 if(length <= 0) return 0;
1182 string=TLB_Alloc(length +1);
1183 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1184 string[length]='\0';
1186 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1187 string, -1, NULL, 0);
1189 /* no invalid characters in string */
1192 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1194 /* don't check for invalid character since this has been done previously */
1195 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1197 bstr = SysAllocStringLen(pwstring, lengthInChars);
1198 lengthInChars = SysStringLen(bstr);
1199 HeapFree(GetProcessHeap(), 0, pwstring);
1202 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1206 * read a value and fill a VARIANT structure
1208 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1212 TRACE_(typelib)("\n");
1214 if(offset <0) { /* data are packed in here */
1215 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1216 V_UNION(pVar, iVal) = offset & 0xffff;
1219 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1220 pcx->pTblDir->pCustData.offset + offset );
1221 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1222 switch (V_VT(pVar)){
1223 case VT_EMPTY: /* FIXME: is this right? */
1224 case VT_NULL: /* FIXME: is this right? */
1225 case VT_I2 : /* this should not happen */
1236 case VT_VOID : /* FIXME: is this right? */
1244 case VT_DECIMAL : /* FIXME: is this right? */
1247 /* pointer types with known behaviour */
1250 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1252 FIXME("BSTR length = %d?\n", size);
1254 ptr=TLB_Alloc(size);/* allocate temp buffer */
1255 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1256 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1257 /* FIXME: do we need a AtoW conversion here? */
1258 V_UNION(pVar, bstrVal[size])=L'\0';
1259 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1264 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1271 case VT_USERDEFINED :
1277 case VT_STREAMED_OBJECT :
1278 case VT_STORED_OBJECT :
1279 case VT_BLOB_OBJECT :
1284 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1288 if(size>0) /* (big|small) endian correct? */
1289 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1293 * create a linked list with custom data
1295 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1301 TRACE_(typelib)("\n");
1305 pNew=TLB_Alloc(sizeof(TLBCustData));
1306 MSFT_Read(&entry, sizeof(entry), pcx,
1307 pcx->pTblDir->pCDGuids.offset+offset);
1308 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1309 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1310 /* add new custom data at head of the list */
1311 pNew->next=*ppCustData;
1313 offset = entry.next;
1318 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1322 pTd->vt=type & VT_TYPEMASK;
1324 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1326 if(pTd->vt == VT_USERDEFINED)
1327 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1329 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1333 MSFT_DoFuncs(TLBContext* pcx,
1338 TLBFuncDesc** pptfd)
1341 * member information is stored in a data structure at offset
1342 * indicated by the memoffset field of the typeinfo structure
1343 * There are several distinctive parts.
1344 * the first part starts with a field that holds the total length
1345 * of this (first) part excluding this field. Then follow the records,
1346 * for each member there is one record.
1348 * First entry is always the length of the record (excluding this
1350 * Rest of the record depends on the type of the member. If there is
1351 * a field indicating the member type (function variable intereface etc)
1352 * I have not found it yet. At this time we depend on the information
1353 * in the type info and the usual order how things are stored.
1355 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1358 * Third is a equal sized array with file offsets to the name entry
1361 * Forth and last (?) part is an array with offsets to the records in the
1362 * first part of this file segment.
1365 int infolen, nameoffset, reclength, nrattributes, i;
1366 int recoffset = offset + sizeof(INT);
1369 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1371 TRACE_(typelib)("\n");
1373 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1375 for ( i = 0; i < cFuncs ; i++ )
1377 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1379 /* name, eventually add to a hash table */
1380 MSFT_Read(&nameoffset,
1383 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1385 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1387 /* read the function information record */
1388 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1392 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1394 /* do the attributes */
1395 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1398 if ( nrattributes > 0 )
1400 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1402 if ( nrattributes > 1 )
1404 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1405 pFuncRec->OptAttr[1]) ;
1407 if ( nrattributes > 2 )
1409 if ( pFuncRec->FKCCIC & 0x2000 )
1411 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1415 (*pptfd)->Entry = MSFT_ReadString(pcx,
1416 pFuncRec->OptAttr[2]);
1418 if( nrattributes > 5 )
1420 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1422 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1425 pFuncRec->OptAttr[6],
1426 &(*pptfd)->pCustData);
1433 /* fill the FuncDesc Structure */
1434 MSFT_Read( & (*pptfd)->funcdesc.memid,
1436 offset + infolen + ( i + 1) * sizeof(INT));
1438 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1439 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1440 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1441 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1442 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1443 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1444 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1448 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1451 /* do the parameters/arguments */
1452 if(pFuncRec->nrargs)
1455 MSFT_ParameterInfo paraminfo;
1457 (*pptfd)->funcdesc.lprgelemdescParam =
1458 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1460 (*pptfd)->pParamDesc =
1461 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1463 MSFT_Read(¶minfo,
1466 recoffset + reclength -
1467 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1469 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1471 TYPEDESC* lpArgTypeDesc = 0;
1475 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1478 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1480 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1482 /* SEEK value = jump to offset,
1483 * from there jump to the end of record,
1484 * go back by (j-1) arguments
1486 MSFT_Read( ¶minfo ,
1487 sizeof(MSFT_ParameterInfo), pcx,
1488 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1489 * sizeof(MSFT_ParameterInfo)));
1491 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1493 while ( lpArgTypeDesc != NULL )
1495 switch ( lpArgTypeDesc->vt )
1498 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1502 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1505 case VT_USERDEFINED:
1506 MSFT_DoRefType(pcx, pTI,
1507 lpArgTypeDesc->u.hreftype);
1509 lpArgTypeDesc = NULL;
1513 lpArgTypeDesc = NULL;
1519 /* parameter is the return value! */
1520 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1522 TYPEDESC* lpArgTypeDesc;
1524 (*pptfd)->funcdesc.elemdescFunc =
1525 (*pptfd)->funcdesc.lprgelemdescParam[j];
1527 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1529 while ( lpArgTypeDesc != NULL )
1531 switch ( lpArgTypeDesc->vt )
1534 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1538 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1542 case VT_USERDEFINED:
1545 lpArgTypeDesc->u.hreftype);
1547 lpArgTypeDesc = NULL;
1551 lpArgTypeDesc = NULL;
1556 /* second time around */
1557 for(j=0;j<pFuncRec->nrargs;j++)
1560 (*pptfd)->pParamDesc[j].Name =
1561 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1564 if ( (PARAMFLAG_FHASDEFAULT &
1565 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1566 ((pFuncRec->FKCCIC) & 0x1000) )
1568 INT* pInt = (INT *)((char *)pFuncRec +
1570 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1572 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1574 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1575 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1577 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1581 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1584 pFuncRec->OptAttr[7+j],
1585 &(*pptfd)->pParamDesc[j].pCustData);
1590 /* scode is not used: archaic win16 stuff FIXME: right? */
1591 (*pptfd)->funcdesc.cScodes = 0 ;
1592 (*pptfd)->funcdesc.lprgscode = NULL ;
1594 pptfd = & ((*pptfd)->next);
1595 recoffset += reclength;
1598 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1599 int cVars, int offset, TLBVarDesc ** pptvd)
1601 int infolen, nameoffset, reclength;
1603 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1607 TRACE_(typelib)("\n");
1609 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1610 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1611 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1612 recoffset += offset+sizeof(INT);
1613 for(i=0;i<cVars;i++){
1614 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1615 /* name, eventually add to a hash table */
1616 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1617 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1618 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1619 /* read the variable information record */
1620 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1622 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1624 if(reclength >(6*sizeof(INT)) )
1625 (*pptvd)->HelpContext=pVarRec->HelpContext;
1626 if(reclength >(7*sizeof(INT)) )
1627 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1628 if(reclength >(8*sizeof(INT)) )
1629 if(reclength >(9*sizeof(INT)) )
1630 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1631 /* fill the VarDesc Structure */
1632 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1633 offset + infolen + ( i + 1) * sizeof(INT));
1634 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1635 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1636 MSFT_GetTdesc(pcx, pVarRec->DataType,
1637 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1638 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1639 if(pVarRec->VarKind == VAR_CONST ){
1640 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1641 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1642 pVarRec->OffsValue, pcx);
1644 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1645 pptvd=&((*pptvd)->next);
1646 recoffset += reclength;
1649 /* fill in data for a hreftype (offset). When the refernced type is contained
1650 * in the typelib, it's just an (file) offset in the type info base dir.
1651 * If comes from import, it's an offset+1 in the ImpInfo table
1653 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1657 TLBRefType **ppRefType = &pTI->reflist;
1659 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1662 if((*ppRefType)->reference == offset)
1664 ppRefType = &(*ppRefType)->next;
1667 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1668 sizeof(**ppRefType));
1670 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1671 /* external typelib */
1672 MSFT_ImpInfo impinfo;
1673 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1675 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1677 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1678 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1679 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1680 if(pImpLib->offset==impinfo.oImpFile) break;
1681 pImpLib=pImpLib->next;
1684 (*ppRefType)->reference=offset;
1685 (*ppRefType)->pImpTLInfo = pImpLib;
1686 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1687 (*ppRefType)->index = TLB_REF_USE_GUID;
1689 ERR("Cannot find a reference\n");
1690 (*ppRefType)->reference=-1;
1691 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1694 /* in this typelib */
1695 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1696 (*ppRefType)->reference=offset;
1697 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1701 /* process Implemented Interfaces of a com class */
1702 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1706 MSFT_RefRecord refrec;
1707 TLBImplType **ppImpl = &pTI->impltypelist;
1709 TRACE_(typelib)("\n");
1711 for(i=0;i<count;i++){
1712 if(offset<0) break; /* paranoia */
1713 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1714 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1715 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1716 (*ppImpl)->hRef = refrec.reftype;
1717 (*ppImpl)->implflags=refrec.flags;
1718 (*ppImpl)->ctCustData=
1719 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1720 offset=refrec.onext;
1721 ppImpl=&((*ppImpl)->next);
1725 * process a typeinfo record
1727 ITypeInfoImpl * MSFT_DoTypeInfo(
1730 ITypeLibImpl * pLibInfo)
1732 MSFT_TypeInfoBase tiBase;
1733 ITypeInfoImpl *ptiRet;
1735 TRACE_(typelib)("count=%u\n", count);
1737 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1738 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1739 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1740 /* this is where we are coming from */
1741 ptiRet->pTypeLib = pLibInfo;
1742 ITypeLib2_AddRef((ITypeLib2 *)pLibInfo);
1743 ptiRet->index=count;
1744 /* fill in the typeattr fields */
1745 FIXME("Assign constructor/destructor memid\n");
1747 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1748 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1749 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1750 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1751 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1752 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1753 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1754 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1755 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1756 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1757 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1758 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1759 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1760 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1761 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1762 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1763 MSFT_GetTdesc(pcx, tiBase.datatype1,
1764 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1767 /* IDLDESC idldescType; *//* never saw this one != zero */
1769 /* name, eventually add to a hash table */
1770 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1771 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1773 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1774 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1775 ptiRet->dwHelpContext=tiBase.helpcontext;
1776 /* note: InfoType's Help file and HelpStringDll come from the containing
1777 * library. Further HelpString and Docstring appear to be the same thing :(
1780 if(ptiRet->TypeAttr.cFuncs >0 )
1781 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1782 ptiRet->TypeAttr.cVars,
1783 tiBase.memoffset, & ptiRet->funclist);
1785 if(ptiRet->TypeAttr.cVars >0 )
1786 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1787 ptiRet->TypeAttr.cVars,
1788 tiBase.memoffset, & ptiRet->varlist);
1789 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1790 switch(ptiRet->TypeAttr.typekind)
1793 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1796 case TKIND_DISPATCH:
1797 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1799 if (tiBase.datatype1 != -1)
1801 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1802 ptiRet->impltypelist->hRef = tiBase.datatype1;
1805 { /* FIXME: This is a really bad hack to add IDispatch */
1806 char* szStdOle = "stdole2.tlb\0";
1807 int nStdOleLen = strlen(szStdOle);
1808 TLBRefType **ppRef = &ptiRet->reflist;
1811 if((*ppRef)->reference == -1)
1813 ppRef = &(*ppRef)->next;
1816 *ppRef = TLB_Alloc(sizeof(**ppRef));
1817 (*ppRef)->guid = IID_IDispatch;
1818 (*ppRef)->reference = -1;
1819 (*ppRef)->index = TLB_REF_USE_GUID;
1820 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1821 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1822 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1825 MultiByteToWideChar(CP_ACP,
1829 (*ppRef)->pImpTLInfo->name,
1830 SysStringLen((*ppRef)->pImpTLInfo->name));
1832 (*ppRef)->pImpTLInfo->lcid = 0;
1833 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1834 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1839 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1840 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1841 ptiRet->impltypelist->hRef = tiBase.datatype1;
1846 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1848 TRACE_(typelib)("%s guid: %s kind:%s\n",
1849 debugstr_w(ptiRet->Name),
1850 debugstr_guid(&ptiRet->TypeAttr.guid),
1851 typekind_desc[ptiRet->TypeAttr.typekind]);
1856 /****************************************************************************
1859 * find the type of the typelib file and map the typelib resource into
1862 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1863 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1864 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1866 int ret = TYPE_E_CANTLOADLIBRARY;
1867 DWORD dwSignature = 0;
1870 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1874 /* check the signature of the file */
1875 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1876 if (INVALID_HANDLE_VALUE != hFile)
1878 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1881 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1884 /* retrieve file size */
1885 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1887 /* first try to load as *.tlb */
1888 dwSignature = *((DWORD*) pBase);
1889 if ( dwSignature == MSFT_SIGNATURE)
1891 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1893 else if ( dwSignature == SLTG_SIGNATURE)
1895 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1897 UnmapViewOfFile(pBase);
1899 CloseHandle(hMapping);
1904 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1906 /* find the typelibrary resource*/
1907 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1908 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1911 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1915 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1918 LPVOID pBase = LockResource(hGlobal);
1919 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1923 /* try to load as incore resource */
1924 dwSignature = *((DWORD*) pBase);
1925 if ( dwSignature == MSFT_SIGNATURE)
1927 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1929 else if ( dwSignature == SLTG_SIGNATURE)
1931 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1935 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1938 FreeResource( hGlobal );
1941 FreeLibrary(hinstDLL);
1948 ERR("Loading of typelib %s failed with error %ld\n",
1949 debugstr_w(pszFileName), GetLastError());
1954 /*================== ITypeLib(2) Methods ===================================*/
1956 /****************************************************************************
1957 * ITypeLib2_Constructor_MSFT
1959 * loading an MSFT typelib from an in-memory image
1961 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
1965 MSFT_Header tlbHeader;
1966 MSFT_SegDir tlbSegDir;
1967 ITypeLibImpl * pTypeLibImpl;
1969 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1971 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1972 if (!pTypeLibImpl) return NULL;
1974 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1975 pTypeLibImpl->ref = 1;
1977 /* get pointer to beginning of typelib data */
1981 cx.pLibInfo = pTypeLibImpl;
1982 cx.length = dwTLBLength;
1985 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1987 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
1988 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
1989 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
1992 /* there is a small amount of information here until the next important
1994 * the segment directory . Try to calculate the amount of data */
1995 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
1997 /* now read the segment directory */
1998 TRACE("read segment directory (at %ld)\n",lPSegDir);
1999 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2000 cx.pTblDir = &tlbSegDir;
2002 /* just check two entries */
2003 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2005 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2006 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2010 /* now fill our internal data */
2011 /* TLIBATTR fields */
2012 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2014 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2015 /* Windows seems to have zero here, is this correct? */
2016 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2017 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2019 pTypeLibImpl->LibAttr.lcid = 0;
2021 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2022 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2023 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2024 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2026 /* name, eventually add to a hash table */
2027 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2030 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2031 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2033 if( tlbHeader.varflags & HELPDLLFLAG)
2036 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2037 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2040 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2043 if(tlbHeader.CustomDataOffset >= 0)
2045 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2048 /* fill in typedescriptions */
2049 if(tlbSegDir.pTypdescTab.length > 0)
2051 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2053 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2054 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2057 /* FIXME: add several sanity checks here */
2058 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2059 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2061 /* FIXME: check safearray */
2063 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2065 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2067 else if(td[0] == VT_CARRAY)
2069 /* array descr table here */
2070 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2072 else if(td[0] == VT_USERDEFINED)
2074 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2076 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2079 /* second time around to fill the array subscript info */
2082 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2083 if(tlbSegDir.pArrayDescriptions.offset>0)
2085 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2086 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2089 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2091 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2093 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2095 for(j = 0; j<td[2]; j++)
2097 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2098 sizeof(INT), &cx, DO_NOT_SEEK);
2099 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2100 sizeof(INT), &cx, DO_NOT_SEEK);
2105 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2106 ERR("didn't find array description data\n");
2111 /* imported type libs */
2112 if(tlbSegDir.pImpFiles.offset>0)
2114 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2115 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2118 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2120 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2121 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2122 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2124 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2125 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2126 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2127 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2130 (*ppImpLib)->name = TLB_Alloc(size+1);
2131 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2132 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2133 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2135 ppImpLib = &(*ppImpLib)->next;
2140 if(tlbHeader.nrtypeinfos >= 0 )
2142 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2143 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2146 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2148 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2150 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2151 ppTI = &((*ppTI)->next);
2152 (pTypeLibImpl->TypeInfoCount)++;
2156 TRACE("(%p)\n", pTypeLibImpl);
2157 return (ITypeLib2*) pTypeLibImpl;
2161 static BSTR TLB_MultiByteToBSTR(char *ptr)
2167 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2168 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2169 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2170 ret = SysAllocString(nameW);
2171 HeapFree(GetProcessHeap(), 0, nameW);
2175 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2181 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2182 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2186 guid->Data4[0] = s >> 8;
2187 guid->Data4[1] = s & 0xff;
2190 for(i = 0; i < 6; i++) {
2191 memcpy(b, str + 24 + 2 * i, 2);
2192 guid->Data4[i + 2] = strtol(b, NULL, 16);
2197 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2204 bytelen = *(WORD*)ptr;
2205 if(bytelen == 0xffff) return 2;
2206 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2207 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2208 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2209 *pBstr = SysAllocStringLen(nameW, len);
2210 HeapFree(GetProcessHeap(), 0, nameW);
2214 static WORD SLTG_ReadStringA(char *ptr, char **str)
2219 bytelen = *(WORD*)ptr;
2220 if(bytelen == 0xffff) return 2;
2221 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2222 memcpy(*str, ptr + 2, bytelen);
2223 (*str)[bytelen] = '\0';
2227 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2229 char *ptr = pLibBlk;
2232 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2233 FIXME("libblk magic = %04x\n", w);
2238 if((w = *(WORD*)ptr) != 0xffff) {
2239 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2244 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2246 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2248 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2251 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2254 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2257 ptr += 4; /* skip res12 */
2259 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2262 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2265 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2268 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2269 ptr += sizeof(GUID);
2271 return ptr - (char*)pLibBlk;
2274 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2277 TYPEDESC *pTD = &pElem->tdesc;
2279 /* Handle [in/out] first */
2280 if((*pType & 0xc000) == 0xc000)
2281 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2282 else if(*pType & 0x8000)
2283 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2284 else if(*pType & 0x4000)
2285 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2287 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2290 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2293 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2296 if((*pType & 0xe00) == 0xe00) {
2298 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2300 pTD = pTD->u.lptdesc;
2302 switch(*pType & 0x7f) {
2305 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2307 pTD = pTD->u.lptdesc;
2310 case VT_USERDEFINED:
2311 pTD->vt = VT_USERDEFINED;
2312 pTD->u.hreftype = *(++pType) / 4;
2318 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2321 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2323 pTD->vt = VT_CARRAY;
2324 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2326 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2327 pTD->u.lpadesc->cDims = pSA->cDims;
2328 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2329 pSA->cDims * sizeof(SAFEARRAYBOUND));
2331 pTD = &pTD->u.lpadesc->tdescElem;
2337 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2341 pTD->vt = VT_SAFEARRAY;
2342 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2344 pTD = pTD->u.lptdesc;
2348 pTD->vt = *pType & 0x7f;
2358 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2363 TLBRefType **ppRefType;
2365 if(pRef->magic != SLTG_REF_MAGIC) {
2366 FIXME("Ref magic = %x\n", pRef->magic);
2369 name = ( (char*)(&pRef->names) + pRef->number);
2371 ppRefType = &pTI->reflist;
2372 for(ref = 0; ref < pRef->number >> 3; ref++) {
2374 unsigned int lib_offs, type_num;
2376 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2377 sizeof(**ppRefType));
2379 name += SLTG_ReadStringA(name, &refname);
2380 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2381 FIXME("Can't sscanf ref\n");
2382 if(lib_offs != 0xffff) {
2383 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2386 if((*import)->offset == lib_offs)
2388 import = &(*import)->next;
2391 char fname[MAX_PATH+1];
2394 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2396 (*import)->offset = lib_offs;
2397 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2399 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2400 &(*import)->wVersionMajor,
2401 &(*import)->wVersionMinor,
2402 &(*import)->lcid, fname) != 4) {
2403 FIXME("can't sscanf ref %s\n",
2404 pNameTable + lib_offs + 40);
2406 len = strlen(fname);
2407 if(fname[len-1] != '#')
2408 FIXME("fname = %s\n", fname);
2409 fname[len-1] = '\0';
2410 (*import)->name = TLB_MultiByteToBSTR(fname);
2412 (*ppRefType)->pImpTLInfo = *import;
2413 } else { /* internal ref */
2414 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2416 (*ppRefType)->reference = ref;
2417 (*ppRefType)->index = type_num;
2419 HeapFree(GetProcessHeap(), 0, refname);
2420 ppRefType = &(*ppRefType)->next;
2422 if((BYTE)*name != SLTG_REF_MAGIC)
2423 FIXME("End of ref block magic = %x\n", *name);
2424 dump_TLBRefType(pTI->reflist);
2427 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2430 SLTG_ImplInfo *info;
2431 TLBImplType **ppImplType = &pTI->impltypelist;
2432 /* I don't really get this structure, usually it's 0x16 bytes
2433 long, but iuser.tlb contains some that are 0x18 bytes long.
2434 That's ok because we can use the next ptr to jump to the next
2435 one. But how do we know the length of the last one? The WORD
2436 at offs 0x8 might be the clue. For now I'm just assuming that
2437 the last one is the regular 0x16 bytes. */
2439 info = (SLTG_ImplInfo*)pBlk;
2441 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2442 sizeof(**ppImplType));
2443 (*ppImplType)->hRef = info->ref;
2444 (*ppImplType)->implflags = info->impltypeflags;
2445 pTI->TypeAttr.cImplTypes++;
2446 ppImplType = &(*ppImplType)->next;
2448 if(info->next == 0xffff)
2451 FIXME("Interface inheriting more than one interface\n");
2452 info = (SLTG_ImplInfo*)(pBlk + info->next);
2454 info++; /* see comment at top of function */
2458 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2461 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2462 SLTG_MemberHeader *pMemHeader;
2463 char *pFirstItem, *pNextItem;
2465 if(pTIHeader->href_table != 0xffffffff) {
2466 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2471 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2473 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2475 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2476 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2479 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2483 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2486 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2487 SLTG_MemberHeader *pMemHeader;
2488 SLTG_Function *pFunc;
2489 char *pFirstItem, *pNextItem;
2490 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2493 if(pTIHeader->href_table != 0xffffffff) {
2494 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2498 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2500 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2502 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2503 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2506 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2507 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2512 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2513 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2514 FIXME("func magic = %02x\n", pFunc->magic);
2517 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2518 sizeof(**ppFuncDesc));
2519 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2521 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2522 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2523 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2524 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2525 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2526 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2528 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2529 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2531 if(pFunc->retnextopt & 0x80)
2532 pType = &pFunc->rettype;
2534 pType = (WORD*)(pFirstItem + pFunc->rettype);
2537 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2539 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2540 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2541 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2542 (*ppFuncDesc)->pParamDesc =
2543 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2544 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2546 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2548 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2549 char *paramName = pNameTable + *pArg;
2551 /* If arg type follows then paramName points to the 2nd
2552 letter of the name, else the next WORD is an offset to
2553 the arg type and paramName points to the first letter.
2554 So let's take one char off paramName and see if we're
2555 pointing at an alpha-numeric char. However if *pArg is
2556 0xffff or 0xfffe then the param has no name, the former
2557 meaning that the next WORD is the type, the latter
2558 meaning the the next WORD is an offset to the type. */
2563 else if(*pArg == 0xfffe) {
2567 else if(!isalnum(*(paramName-1)))
2572 if(HaveOffs) { /* the next word is an offset to type */
2573 pType = (WORD*)(pFirstItem + *pArg);
2574 SLTG_DoType(pType, pFirstItem,
2575 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2580 pArg = SLTG_DoType(pArg, pFirstItem,
2581 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2584 /* Are we an optional param ? */
2585 if((*ppFuncDesc)->funcdesc.cParams - param <=
2586 (*ppFuncDesc)->funcdesc.cParamsOpt)
2587 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2590 (*ppFuncDesc)->pParamDesc[param].Name =
2591 TLB_MultiByteToBSTR(paramName);
2595 ppFuncDesc = &((*ppFuncDesc)->next);
2596 if(pFunc->next == 0xffff) break;
2598 pTI->TypeAttr.cFuncs = num;
2599 dump_TLBFuncDesc(pTI->funclist);
2600 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2603 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2606 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2607 SLTG_MemberHeader *pMemHeader;
2608 SLTG_RecordItem *pItem;
2610 TLBVarDesc **ppVarDesc = &pTI->varlist;
2615 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2617 pFirstItem = (char*)(pMemHeader + 1);
2618 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2619 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2620 if(pItem->magic != SLTG_RECORD_MAGIC) {
2621 FIXME("record magic = %02x\n", pItem->magic);
2624 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2625 sizeof(**ppVarDesc));
2626 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2627 (*ppVarDesc)->vardesc.memid = pItem->memid;
2628 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2629 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2631 if(pItem->typepos == 0x02)
2632 pType = &pItem->type;
2633 else if(pItem->typepos == 0x00)
2634 pType = (WORD*)(pFirstItem + pItem->type);
2636 FIXME("typepos = %02x\n", pItem->typepos);
2640 SLTG_DoType(pType, pFirstItem,
2641 &(*ppVarDesc)->vardesc.elemdescVar);
2643 /* FIXME("helpcontext, helpstring\n"); */
2645 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2647 ppVarDesc = &((*ppVarDesc)->next);
2648 if(pItem->next == 0xffff) break;
2650 pTI->TypeAttr.cVars = num;
2651 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2654 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2657 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2658 SLTG_MemberHeader *pMemHeader;
2659 SLTG_EnumItem *pItem;
2661 TLBVarDesc **ppVarDesc = &pTI->varlist;
2664 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2666 pFirstItem = (char*)(pMemHeader + 1);
2667 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2668 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2669 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2670 FIXME("enumitem magic = %04x\n", pItem->magic);
2673 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2674 sizeof(**ppVarDesc));
2675 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2676 (*ppVarDesc)->vardesc.memid = pItem->memid;
2677 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2679 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2680 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2681 *(INT*)(pItem->value + pFirstItem);
2682 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2683 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2684 /* FIXME("helpcontext, helpstring\n"); */
2686 ppVarDesc = &((*ppVarDesc)->next);
2687 if(pItem->next == 0xffff) break;
2689 pTI->TypeAttr.cVars = num;
2690 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2693 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2694 managable copy of it into this */
2707 } SLTG_InternalOtherTypeInfo;
2709 /****************************************************************************
2710 * ITypeLib2_Constructor_SLTG
2712 * loading a SLTG typelib from an in-memory image
2714 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2716 ITypeLibImpl *pTypeLibImpl;
2717 SLTG_Header *pHeader;
2718 SLTG_BlkEntry *pBlkEntry;
2722 LPVOID pBlk, pFirstBlk;
2723 SLTG_LibBlk *pLibBlk;
2724 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2725 char *pAfterOTIBlks = NULL;
2726 char *pNameTable, *ptr;
2729 ITypeInfoImpl **ppTypeInfoImpl;
2731 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2733 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2734 if (!pTypeLibImpl) return NULL;
2736 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2737 pTypeLibImpl->ref = 1;
2742 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2743 pHeader->nrOfFileBlks );
2744 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2745 FIXME("Header type magic 0x%08lx not supported.\n",
2746 pHeader->SLTG_magic);
2750 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2751 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2753 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2754 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2756 /* Next we have a magic block */
2757 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2759 /* Let's see if we're still in sync */
2760 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2761 sizeof(SLTG_COMPOBJ_MAGIC))) {
2762 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2765 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2766 sizeof(SLTG_DIR_MAGIC))) {
2767 FIXME("dir magic = %s\n", pMagic->dir_magic);
2771 pIndex = (SLTG_Index*)(pMagic+1);
2773 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2775 pFirstBlk = (LPVOID)(pPad9 + 1);
2777 /* We'll set up a ptr to the main library block, which is the last one. */
2779 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2780 pBlkEntry[order].next != 0;
2781 order = pBlkEntry[order].next - 1, i++) {
2782 pBlk += pBlkEntry[order].len;
2786 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2788 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2793 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2795 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2796 sizeof(*pOtherTypeInfoBlks) *
2797 pTypeLibImpl->TypeInfoCount);
2800 ptr = (char*)pLibBlk + len;
2802 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2806 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2808 w = *(WORD*)(ptr + 2);
2811 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2813 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2814 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2816 w = *(WORD*)(ptr + 4 + len);
2818 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2820 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2822 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2823 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2825 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2826 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2827 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2829 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2831 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2834 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2835 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2836 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2837 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2838 len += sizeof(SLTG_OtherTypeInfo);
2842 pAfterOTIBlks = ptr;
2844 /* Skip this WORD and get the next DWORD */
2845 len = *(DWORD*)(pAfterOTIBlks + 2);
2847 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2848 magic dust and we should be pointing at the beginning of the name
2851 pNameTable = (char*)pLibBlk + len + 0x216;
2855 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2857 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2860 /* Hopefully we now have enough ptrs set up to actually read in
2861 some TypeInfos. It's not clear which order to do them in, so
2862 I'll just follow the links along the BlkEntry chain and read
2863 them in in the order in which they're in the file */
2865 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2867 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2868 pBlkEntry[order].next != 0;
2869 order = pBlkEntry[order].next - 1, i++) {
2871 SLTG_TypeInfoHeader *pTIHeader;
2872 SLTG_TypeInfoTail *pTITail;
2874 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2875 pOtherTypeInfoBlks[i].index_name)) {
2876 FIXME("Index strings don't match\n");
2881 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2882 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2885 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2886 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2887 ITypeLib2_AddRef((ITypeLib2 *)pTypeLibImpl);
2888 (*ppTypeInfoImpl)->index = i;
2889 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2890 pOtherTypeInfoBlks[i].name_offs +
2892 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2893 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2895 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2896 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2897 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2898 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2899 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2901 if((pTIHeader->typeflags1 & 7) != 2)
2902 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2903 if(pTIHeader->typeflags3 != 2)
2904 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2906 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2907 debugstr_w((*ppTypeInfoImpl)->Name),
2908 typekind_desc[pTIHeader->typekind],
2909 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2910 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2912 switch(pTIHeader->typekind) {
2914 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2918 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2921 case TKIND_INTERFACE:
2922 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2926 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2930 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2936 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2937 but we've already set those */
2938 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2939 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2940 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2942 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2943 pBlk += pBlkEntry[order].len;
2946 if(i != pTypeLibImpl->TypeInfoCount) {
2947 FIXME("Somehow processed %d TypeInfos\n", i);
2951 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2952 return (ITypeLib2*)pTypeLibImpl;
2955 /* ITypeLib::QueryInterface
2957 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2962 ICOM_THIS( ITypeLibImpl, iface);
2964 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2967 if(IsEqualIID(riid, &IID_IUnknown) ||
2968 IsEqualIID(riid,&IID_ITypeLib)||
2969 IsEqualIID(riid,&IID_ITypeLib2))
2976 ITypeLib2_AddRef(iface);
2977 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2980 TRACE("-- Interface: E_NOINTERFACE\n");
2981 return E_NOINTERFACE;
2986 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
2988 ICOM_THIS( ITypeLibImpl, iface);
2990 TRACE("(%p)->ref is %u\n",This, This->ref);
2992 return ++(This->ref);
2995 /* ITypeLib::Release
2997 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
2999 ICOM_THIS( ITypeLibImpl, iface);
3003 TRACE("(%p)->(%u)\n",This, This->ref);
3007 /* FIXME destroy child objects */
3009 TRACE(" destroying ITypeLib(%p)\n",This);
3013 SysFreeString(This->Name);
3017 if (This->DocString)
3019 SysFreeString(This->DocString);
3020 This->DocString = NULL;
3025 SysFreeString(This->HelpFile);
3026 This->HelpFile = NULL;
3029 if (This->HelpStringDll)
3031 SysFreeString(This->HelpStringDll);
3032 This->HelpStringDll = NULL;
3035 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3036 HeapFree(GetProcessHeap(),0,This);
3043 /* ITypeLib::GetTypeInfoCount
3045 * Returns the number of type descriptions in the type library
3047 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3049 ICOM_THIS( ITypeLibImpl, iface);
3050 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3051 return This->TypeInfoCount;
3054 /* ITypeLib::GetTypeInfo
3056 * retrieves the specified type description in the library.
3058 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3061 ITypeInfo **ppTInfo)
3065 ICOM_THIS( ITypeLibImpl, iface);
3066 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3068 TRACE("(%p)->(index=%d) \n", This, index);
3070 if (!ppTInfo) return E_INVALIDARG;
3072 /* search element n in list */
3073 for(i=0; i < index; i++)
3075 pTypeInfo = pTypeInfo->next;
3078 TRACE("-- element not found\n");
3079 return TYPE_E_ELEMENTNOTFOUND;
3083 *ppTInfo = (ITypeInfo *) pTypeInfo;
3085 ITypeInfo_AddRef(*ppTInfo);
3086 TRACE("-- found (%p)\n",*ppTInfo);
3091 /* ITypeLibs::GetTypeInfoType
3093 * Retrieves the type of a type description.
3095 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3100 ICOM_THIS( ITypeLibImpl, iface);
3102 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3104 TRACE("(%p) index %d \n",This, index);
3106 if(!pTKind) return E_INVALIDARG;
3108 /* search element n in list */
3109 for(i=0; i < index; i++)
3113 TRACE("-- element not found\n");
3114 return TYPE_E_ELEMENTNOTFOUND;
3116 pTInfo = pTInfo->next;
3119 *pTKind = pTInfo->TypeAttr.typekind;
3120 TRACE("-- found Type (%d)\n", *pTKind);
3124 /* ITypeLib::GetTypeInfoOfGuid
3126 * Retrieves the type description that corresponds to the specified GUID.
3129 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3132 ITypeInfo **ppTInfo)
3134 ICOM_THIS( ITypeLibImpl, iface);
3135 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3137 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3139 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3141 /* search linked list for guid */
3142 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3144 pTypeInfo = pTypeInfo->next;
3148 /* end of list reached */
3149 TRACE("-- element not found\n");
3150 return TYPE_E_ELEMENTNOTFOUND;
3154 TRACE("-- found (%p, %s)\n",
3156 debugstr_w(pTypeInfo->Name));
3158 *ppTInfo = (ITypeInfo*)pTypeInfo;
3159 ITypeInfo_AddRef(*ppTInfo);
3163 /* ITypeLib::GetLibAttr
3165 * Retrieves the structure that contains the library's attributes.
3168 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3170 LPTLIBATTR *ppTLibAttr)
3172 ICOM_THIS( ITypeLibImpl, iface);
3173 TRACE("(%p)\n",This);
3174 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3175 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3179 /* ITypeLib::GetTypeComp
3181 * Enables a client compiler to bind to a library's types, variables,
3182 * constants, and global functions.
3185 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3187 ITypeComp **ppTComp)
3189 ICOM_THIS( ITypeLibImpl, iface);
3190 FIXME("(%p): stub!\n",This);
3194 /* ITypeLib::GetDocumentation
3196 * Retrieves the library's documentation string, the complete Help file name
3197 * and path, and the context identifier for the library Help topic in the Help
3200 * On a successful return all non-null BSTR pointers will have been set,
3203 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3207 BSTR *pBstrDocString,
3208 DWORD *pdwHelpContext,
3209 BSTR *pBstrHelpFile)
3211 ICOM_THIS( ITypeLibImpl, iface);
3213 HRESULT result = E_INVALIDARG;
3218 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3220 pBstrName, pBstrDocString,
3221 pdwHelpContext, pBstrHelpFile);
3225 /* documentation for the typelib */
3229 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3235 if (This->DocString)
3236 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3237 else if (This->Name)
3238 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3240 *pBstrDocString = NULL;
3244 *pdwHelpContext = This->dwHelpContext;
3249 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3251 *pBstrHelpFile = NULL;
3258 /* for a typeinfo */
3259 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3261 if(SUCCEEDED(result))
3263 result = ITypeInfo_GetDocumentation(pTInfo,
3267 pdwHelpContext, pBstrHelpFile);
3269 ITypeInfo_Release(pTInfo);
3274 if (pBstrDocString) SysFreeString (*pBstrDocString);
3276 if (pBstrName) SysFreeString (*pBstrName);
3278 return STG_E_INSUFFICIENTMEMORY;
3283 * Indicates whether a passed-in string contains the name of a type or member
3284 * described in the library.
3287 static HRESULT WINAPI ITypeLib2_fnIsName(
3293 ICOM_THIS( ITypeLibImpl, iface);
3294 ITypeInfoImpl *pTInfo;
3295 TLBFuncDesc *pFInfo;
3298 UINT nNameBufLen = SysStringLen(szNameBuf);
3300 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3304 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3305 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3306 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3307 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3308 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3309 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3310 goto ITypeLib2_fnIsName_exit;
3312 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3313 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3318 ITypeLib2_fnIsName_exit:
3319 TRACE("(%p)slow! search for %s: %s found!\n", This,
3320 debugstr_w(szNameBuf), *pfName?"NOT":"");
3325 /* ITypeLib::FindName
3327 * Finds occurrences of a type description in a type library. This may be used
3328 * to quickly verify that a name exists in a type library.
3331 static HRESULT WINAPI ITypeLib2_fnFindName(
3335 ITypeInfo **ppTInfo,
3339 ICOM_THIS( ITypeLibImpl, iface);
3340 ITypeInfoImpl *pTInfo;
3341 TLBFuncDesc *pFInfo;
3345 UINT nNameBufLen = SysStringLen(szNameBuf);
3347 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3348 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3349 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3350 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3351 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3352 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3353 goto ITypeLib2_fnFindName_exit;
3355 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3356 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3358 ITypeLib2_fnFindName_exit:
3359 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3360 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3363 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3364 This, *pcFound, debugstr_w(szNameBuf), j);
3371 /* ITypeLib::ReleaseTLibAttr
3373 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3376 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3378 TLIBATTR *pTLibAttr)
3380 ICOM_THIS( ITypeLibImpl, iface);
3381 TRACE("freeing (%p)\n",This);
3382 HeapFree(GetProcessHeap(),0,pTLibAttr);
3386 /* ITypeLib2::GetCustData
3388 * gets the custom data
3390 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3395 ICOM_THIS( ITypeLibImpl, iface);
3396 TLBCustData *pCData;
3398 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3400 if( IsEqualIID(guid, &pCData->guid)) break;
3403 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3407 VariantInit( pVarVal);
3408 VariantCopy( pVarVal, &pCData->data);
3411 return E_INVALIDARG; /* FIXME: correct? */
3414 /* ITypeLib2::GetLibStatistics
3416 * Returns statistics about a type library that are required for efficient
3417 * sizing of hash tables.
3420 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3422 ULONG *pcUniqueNames,
3423 ULONG *pcchUniqueNames)
3425 ICOM_THIS( ITypeLibImpl, iface);
3427 FIXME("(%p): stub!\n", This);
3429 if(pcUniqueNames) *pcUniqueNames=1;
3430 if(pcchUniqueNames) *pcchUniqueNames=1;
3434 /* ITypeLib2::GetDocumentation2
3436 * Retrieves the library's documentation string, the complete Help file name
3437 * and path, the localization context to use, and the context ID for the
3438 * library Help topic in the Help file.
3441 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3445 BSTR *pbstrHelpString,
3446 DWORD *pdwHelpStringContext,
3447 BSTR *pbstrHelpStringDll)
3449 ICOM_THIS( ITypeLibImpl, iface);
3453 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3455 /* the help string should be obtained from the helpstringdll,
3456 * using the _DLLGetDocumentation function, based on the supplied
3457 * lcid. Nice to do sometime...
3461 /* documentation for the typelib */
3463 *pbstrHelpString=SysAllocString(This->DocString);
3464 if(pdwHelpStringContext)
3465 *pdwHelpStringContext=This->dwHelpContext;
3466 if(pbstrHelpStringDll)
3467 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3473 /* for a typeinfo */
3474 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3476 if(SUCCEEDED(result))
3478 ITypeInfo2 * pTInfo2;
3479 result = ITypeInfo_QueryInterface(pTInfo,
3481 (LPVOID*) &pTInfo2);
3483 if(SUCCEEDED(result))
3485 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3489 pdwHelpStringContext,
3490 pbstrHelpStringDll);
3492 ITypeInfo2_Release(pTInfo2);
3495 ITypeInfo_Release(pTInfo);
3501 /* ITypeLib2::GetAllCustData
3503 * Gets all custom data items for the library.
3506 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3508 CUSTDATA *pCustData)
3510 ICOM_THIS( ITypeLibImpl, iface);
3511 TLBCustData *pCData;
3513 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3514 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3515 if(pCustData->prgCustData ){
3516 pCustData->cCustData=This->ctCustData;
3517 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3518 pCustData->prgCustData[i].guid=pCData->guid;
3519 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3522 ERR(" OUT OF MEMORY! \n");
3523 return E_OUTOFMEMORY;
3528 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3529 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3530 ITypeLib2_fnQueryInterface,
3532 ITypeLib2_fnRelease,
3533 ITypeLib2_fnGetTypeInfoCount,
3534 ITypeLib2_fnGetTypeInfo,
3535 ITypeLib2_fnGetTypeInfoType,
3536 ITypeLib2_fnGetTypeInfoOfGuid,
3537 ITypeLib2_fnGetLibAttr,
3538 ITypeLib2_fnGetTypeComp,
3539 ITypeLib2_fnGetDocumentation,
3541 ITypeLib2_fnFindName,
3542 ITypeLib2_fnReleaseTLibAttr,
3544 ITypeLib2_fnGetCustData,
3545 ITypeLib2_fnGetLibStatistics,
3546 ITypeLib2_fnGetDocumentation2,
3547 ITypeLib2_fnGetAllCustData
3550 /*================== ITypeInfo(2) Methods ===================================*/
3551 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3553 ITypeInfoImpl * pTypeInfoImpl;
3555 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3558 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3559 pTypeInfoImpl->ref=1;
3561 TRACE("(%p)\n", pTypeInfoImpl);
3562 return (ITypeInfo2*) pTypeInfoImpl;
3565 /* ITypeInfo::QueryInterface
3567 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3572 ICOM_THIS( ITypeLibImpl, iface);
3574 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3577 if(IsEqualIID(riid, &IID_IUnknown) ||
3578 IsEqualIID(riid,&IID_ITypeInfo)||
3579 IsEqualIID(riid,&IID_ITypeInfo2))
3583 ITypeInfo_AddRef(iface);
3584 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3587 TRACE("-- Interface: E_NOINTERFACE\n");
3588 return E_NOINTERFACE;
3591 /* ITypeInfo::AddRef
3593 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3595 ICOM_THIS( ITypeInfoImpl, iface);
3599 TRACE("(%p)->ref is %u\n",This, This->ref);
3603 /* ITypeInfo::Release
3605 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3607 ICOM_THIS( ITypeInfoImpl, iface);
3611 TRACE("(%p)->(%u)\n",This, This->ref);
3615 FIXME("destroy child objects\n");
3617 TRACE("destroying ITypeInfo(%p)\n",This);
3620 SysFreeString(This->Name);
3624 if (This->DocString)
3626 SysFreeString(This->DocString);
3627 This->DocString = 0;
3632 ITypeInfo_Release((ITypeInfo*)This->next);
3635 HeapFree(GetProcessHeap(),0,This);
3641 /* ITypeInfo::GetTypeAttr
3643 * Retrieves a TYPEATTR structure that contains the attributes of the type
3647 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3648 LPTYPEATTR *ppTypeAttr)
3650 ICOM_THIS( ITypeInfoImpl, iface);
3651 TRACE("(%p)\n",This);
3652 /* FIXME: must do a copy here */
3653 *ppTypeAttr=&This->TypeAttr;
3657 /* ITypeInfo::GetTypeComp
3659 * Retrieves the ITypeComp interface for the type description, which enables a
3660 * client compiler to bind to the type description's members.
3663 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3664 ITypeComp * *ppTComp)
3666 ICOM_THIS( ITypeInfoImpl, iface);
3667 FIXME("(%p) stub!\n", This);
3671 /* ITypeInfo::GetFuncDesc
3673 * Retrieves the FUNCDESC structure that contains information about a
3674 * specified function.
3677 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3678 LPFUNCDESC *ppFuncDesc)
3680 ICOM_THIS( ITypeInfoImpl, iface);
3682 TLBFuncDesc * pFDesc;
3683 TRACE("(%p) index %d\n", This, index);
3684 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3687 /* FIXME: must do a copy here */
3688 *ppFuncDesc=&pFDesc->funcdesc;
3691 return E_INVALIDARG;
3694 /* ITypeInfo::GetVarDesc
3696 * Retrieves a VARDESC structure that describes the specified variable.
3699 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3700 LPVARDESC *ppVarDesc)
3702 ICOM_THIS( ITypeInfoImpl, iface);
3704 TLBVarDesc * pVDesc;
3705 TRACE("(%p) index %d\n", This, index);
3706 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3709 /* FIXME: must do a copy here */
3710 *ppVarDesc=&pVDesc->vardesc;
3713 return E_INVALIDARG;
3716 /* ITypeInfo_GetNames
3718 * Retrieves the variable with the specified member ID (or the name of the
3719 * property or method and its parameters) that correspond to the specified
3722 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3723 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3725 ICOM_THIS( ITypeInfoImpl, iface);
3726 TLBFuncDesc * pFDesc;
3727 TLBVarDesc * pVDesc;
3729 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3730 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3733 /* function found, now return function and parameter names */
3734 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3737 *rgBstrNames=SysAllocString(pFDesc->Name);
3739 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3745 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3748 *rgBstrNames=SysAllocString(pVDesc->Name);
3753 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3755 /* recursive search */
3758 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3760 if(SUCCEEDED(result))
3762 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3763 ITypeInfo_Release(pTInfo);
3766 WARN("Could not search inherited interface!\n");
3770 WARN("no names found\n");
3773 return TYPE_E_ELEMENTNOTFOUND;
3780 /* ITypeInfo::GetRefTypeOfImplType
3782 * If a type description describes a COM class, it retrieves the type
3783 * description of the implemented interface types. For an interface,
3784 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3788 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3793 ICOM_THIS( ITypeInfoImpl, iface);
3795 TLBImplType *pImpl = This->impltypelist;
3797 TRACE("(%p) index %d\n", This, index);
3798 dump_TypeInfo(This);
3802 /* only valid on dual interfaces;
3803 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3805 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3807 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3808 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3814 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3815 *pRefType = pImpl->hRef;
3820 /* get element n from linked list */
3821 for(i=0; pImpl && i<index; i++)
3823 pImpl = pImpl->next;
3826 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3828 *pRefType = pImpl->hRef;
3830 TRACE("-- 0x%08lx\n", pImpl->hRef );
3837 /* ITypeInfo::GetImplTypeFlags
3839 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3840 * or base interface in a type description.
3842 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3843 UINT index, INT *pImplTypeFlags)
3845 ICOM_THIS( ITypeInfoImpl, iface);
3849 TRACE("(%p) index %d\n", This, index);
3850 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3851 i++, pImpl=pImpl->next)
3853 if(i==index && pImpl){
3854 *pImplTypeFlags=pImpl->implflags;
3858 return TYPE_E_ELEMENTNOTFOUND;
3862 * Maps between member names and member IDs, and parameter names and
3865 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3866 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3868 ICOM_THIS( ITypeInfoImpl, iface);
3869 TLBFuncDesc * pFDesc;
3870 TLBVarDesc * pVDesc;
3873 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3875 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3877 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3878 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3879 for(i=1; i < cNames; i++){
3880 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3881 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3883 if( j<pFDesc->funcdesc.cParams)
3886 ret=DISP_E_UNKNOWNNAME;
3891 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3892 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3893 if(cNames) *pMemId=pVDesc->vardesc.memid;
3897 /* not found, see if this is and interface with an inheritance */
3898 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3899 This->TypeAttr.cImplTypes ){
3900 /* recursive search */
3902 ret=ITypeInfo_GetRefTypeInfo(iface,
3903 This->impltypelist->hRef, &pTInfo);
3905 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3906 ITypeInfo_Release(pTInfo);
3909 WARN("Could not search inherited interface!\n");
3911 WARN("no names found\n");
3912 return DISP_E_UNKNOWNNAME;
3915 /* ITypeInfo::Invoke
3917 * Invokes a method, or accesses a property of an object, that implements the
3918 * interface described by the type description.
3921 _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3924 if (TRACE_ON(ole)) {
3926 MESSAGE("Calling %p(",func);
3927 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3936 DWORD (WINAPI *xfunc)() = func;
3941 DWORD (WINAPI *xfunc)(DWORD) = func;
3942 res = xfunc(args[0]);
3946 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3947 res = xfunc(args[0],args[1]);
3951 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3952 res = xfunc(args[0],args[1],args[2]);
3956 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD) = func;
3957 res = xfunc(args[0],args[1],args[2],args[3]);
3961 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD) = func;
3962 res = xfunc(args[0],args[1],args[2],args[3],args[4]);
3966 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
3967 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5]);
3971 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD) = func;
3972 res = xfunc(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
3976 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
3982 FIXME("unsupported calling convention %d\n",callconv);
3986 TRACE("returns %08lx\n",res);
3990 static HRESULT WINAPI ITypeInfo_fnInvoke(
3995 DISPPARAMS *pDispParams,
3996 VARIANT *pVarResult,
3997 EXCEPINFO *pExcepInfo,
4000 ICOM_THIS( ITypeInfoImpl, iface);
4001 TLBFuncDesc * pFDesc;
4002 TLBVarDesc * pVDesc;
4005 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4006 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4008 dump_DispParms(pDispParams);
4010 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4011 if (pFDesc->funcdesc.memid == memid) {
4012 if (pFDesc->funcdesc.invkind & dwFlags)
4016 dump_TLBFuncDescOne(pFDesc);
4017 switch (pFDesc->funcdesc.funckind) {
4018 case FUNC_PUREVIRTUAL:
4019 case FUNC_VIRTUAL: {
4021 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
4022 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
4023 args[0] = (DWORD)pIUnk;
4025 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4026 if (i<pDispParams->cArgs) {
4027 TRACE("set %d to disparg type %d vs %d\n",i,
4028 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
4029 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
4031 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
4033 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4034 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4035 /*FIXME: give pointers for the rest, so propertyget works*/
4036 args[i+1] = (DWORD)&args2[i];
4038 /* If pointer to variant, pass reference to variant
4039 * in result variant array.
4041 if ((tdesc->vt == VT_PTR) &&
4042 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4045 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
4048 if (pFDesc->funcdesc.cParamsOpt)
4049 FIXME("Does not support optional parameters (%d)\n",
4050 pFDesc->funcdesc.cParamsOpt
4053 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4054 pFDesc->funcdesc.callconv,
4055 pFDesc->funcdesc.cParams+1,
4058 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4059 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4060 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4061 /* If we are a pointer to a variant, we are done already */
4062 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4065 VariantInit(&pVarResult[i]);
4066 V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
4068 if (tdesc->vt == VT_PTR)
4069 tdesc = tdesc->u.lptdesc;
4070 V_VT(pVarResult+i) = tdesc->vt;
4072 /* HACK: VB5 likes this.
4073 * I do not know why. There is 1 example in MSDN which uses
4074 * this which appears broken (mixes int vals and
4077 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4078 V_VT(pVarResult+i) = VT_DISPATCH;
4079 TRACE("storing into variant: [%d]\n", i);
4080 dump_Variant(pVarResult+i);
4083 HeapFree(GetProcessHeap(),0,args2);
4084 HeapFree(GetProcessHeap(),0,args);
4087 case FUNC_DISPATCH: {
4091 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4093 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4096 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4097 hr = IDispatch_Invoke(
4098 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4099 pVarResult,pExcepInfo,pArgErr
4102 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4103 IDispatch_Release(disp);
4107 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4111 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4112 if (pVDesc->vardesc.memid == memid) {
4113 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4114 dump_TLBVarDesc(pVDesc);
4119 /* not found, look for it in inherited interfaces */
4120 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4121 /* recursive search */
4124 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4126 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4127 ITypeInfo_Release(pTInfo);
4130 WARN("Could not search inherited interface!\n");
4132 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4133 return DISP_E_MEMBERNOTFOUND;
4136 /* ITypeInfo::GetDocumentation
4138 * Retrieves the documentation string, the complete Help file name and path,
4139 * and the context ID for the Help topic for a specified type description.
4141 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4142 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4143 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4145 ICOM_THIS( ITypeInfoImpl, iface);
4146 TLBFuncDesc * pFDesc;
4147 TLBVarDesc * pVDesc;
4148 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4149 " HelpContext(%p) HelpFile(%p)\n",
4150 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4151 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4153 *pBstrName=SysAllocString(This->Name);
4155 *pBstrDocString=SysAllocString(This->DocString);
4157 *pdwHelpContext=This->dwHelpContext;
4159 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4161 }else {/* for a member */
4162 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4163 if(pFDesc->funcdesc.memid==memid){
4165 *pBstrName = SysAllocString(pFDesc->Name);
4167 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4169 *pdwHelpContext=pFDesc->helpcontext;
4172 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4173 if(pVDesc->vardesc.memid==memid){
4174 FIXME("Not implemented\n");
4178 return TYPE_E_ELEMENTNOTFOUND;
4181 /* ITypeInfo::GetDllEntry
4183 * Retrieves a description or specification of an entry point for a function
4186 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4187 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4190 ICOM_THIS( ITypeInfoImpl, iface);
4191 FIXME("(%p) stub!\n", This);
4195 /* ITypeInfo::GetRefTypeInfo
4197 * If a type description references other type descriptions, it retrieves
4198 * the referenced type descriptions.
4200 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4203 ITypeInfo **ppTInfo)
4205 ICOM_THIS( ITypeInfoImpl, iface);
4206 HRESULT result = E_FAIL;
4209 if (hRefType == -1 &&
4210 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4211 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4213 /* when we meet a DUAL dispinterface, we must create the interface
4216 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4219 /* the interface version contains the same information as the dispinterface
4220 * copy the contents of the structs.
4222 *pTypeInfoImpl = *This;
4223 pTypeInfoImpl->ref = 1;
4225 /* change the type to interface */
4226 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4228 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4230 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4235 TLBRefType *pRefType;
4236 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4237 if(pRefType->reference == hRefType)
4241 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4242 if(pRefType && hRefType != -1) {
4243 ITypeLib *pTLib = NULL;
4245 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4247 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4249 if(pRefType->pImpTLInfo->pImpTypeLib) {
4250 TRACE("typeinfo in imported typelib that is already loaded\n");
4251 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4252 ITypeLib2_AddRef((ITypeLib*) pTLib);
4255 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4256 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4257 pRefType->pImpTLInfo->wVersionMajor,
4258 pRefType->pImpTLInfo->wVersionMinor,
4259 pRefType->pImpTLInfo->lcid,
4262 if(!SUCCEEDED(result)) {
4263 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4264 result=LoadTypeLib(libnam, &pTLib);
4265 SysFreeString(libnam);
4267 if(SUCCEEDED(result)) {
4268 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4269 ITypeLib2_AddRef(pTLib);
4273 if(SUCCEEDED(result)) {
4274 if(pRefType->index == TLB_REF_USE_GUID)
4275 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4279 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4283 ITypeLib2_Release(pTLib);
4287 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4288 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4292 /* ITypeInfo::AddressOfMember
4294 * Retrieves the addresses of static functions or variables, such as those
4297 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4298 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4300 ICOM_THIS( ITypeInfoImpl, iface);
4301 FIXME("(%p) stub!\n", This);
4305 /* ITypeInfo::CreateInstance
4307 * Creates a new instance of a type that describes a component object class
4310 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4311 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4313 ICOM_THIS( ITypeInfoImpl, iface);
4314 FIXME("(%p) stub!\n", This);
4318 /* ITypeInfo::GetMops
4320 * Retrieves marshaling information.
4322 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4325 ICOM_THIS( ITypeInfoImpl, iface);
4326 FIXME("(%p) stub!\n", This);
4330 /* ITypeInfo::GetContainingTypeLib
4332 * Retrieves the containing type library and the index of the type description
4333 * within that type library.
4335 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4336 ITypeLib * *ppTLib, UINT *pIndex)
4338 ICOM_THIS( ITypeInfoImpl, iface);
4340 return E_INVALIDARG;
4341 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4342 *pIndex=This->index;
4343 ITypeLib2_AddRef(*ppTLib);
4344 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4348 /* ITypeInfo::ReleaseTypeAttr
4350 * Releases a TYPEATTR previously returned by GetTypeAttr.
4353 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4354 TYPEATTR* pTypeAttr)
4356 ICOM_THIS( ITypeInfoImpl, iface);
4357 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4361 /* ITypeInfo::ReleaseFuncDesc
4363 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4365 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4367 FUNCDESC *pFuncDesc)
4369 ICOM_THIS( ITypeInfoImpl, iface);
4370 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4374 /* ITypeInfo::ReleaseVarDesc
4376 * Releases a VARDESC previously returned by GetVarDesc.
4378 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4381 ICOM_THIS( ITypeInfoImpl, iface);
4382 TRACE("(%p)->(%p)\n", This, pVarDesc);
4386 /* ITypeInfo2::GetTypeKind
4388 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4391 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4392 TYPEKIND *pTypeKind)
4394 ICOM_THIS( ITypeInfoImpl, iface);
4395 *pTypeKind=This->TypeAttr.typekind;
4396 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4400 /* ITypeInfo2::GetTypeFlags
4402 * Returns the type flags without any allocations. This returns a DWORD type
4403 * flag, which expands the type flags without growing the TYPEATTR (type
4407 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4410 ICOM_THIS( ITypeInfoImpl, iface);
4411 *pTypeFlags=This->TypeAttr.wTypeFlags;
4412 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4416 /* ITypeInfo2::GetFuncIndexOfMemId
4417 * Binds to a specific member based on a known DISPID, where the member name
4418 * is not known (for example, when binding to a default member).
4421 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4422 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4424 ICOM_THIS( ITypeInfoImpl, iface);
4425 TLBFuncDesc *pFuncInfo;
4428 /* FIXME: should check for invKind??? */
4429 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4430 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4436 result=E_INVALIDARG;
4438 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4439 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4443 /* TypeInfo2::GetVarIndexOfMemId
4445 * Binds to a specific member based on a known DISPID, where the member name
4446 * is not known (for example, when binding to a default member).
4449 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4450 MEMBERID memid, UINT *pVarIndex)
4452 ICOM_THIS( ITypeInfoImpl, iface);
4453 TLBVarDesc *pVarInfo;
4456 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4457 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4464 result=E_INVALIDARG;
4466 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4467 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4471 /* ITypeInfo2::GetCustData
4473 * Gets the custom data
4475 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4480 ICOM_THIS( ITypeInfoImpl, iface);
4481 TLBCustData *pCData;
4483 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4484 if( IsEqualIID(guid, &pCData->guid)) break;
4486 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4490 VariantInit( pVarVal);
4491 VariantCopy( pVarVal, &pCData->data);
4494 return E_INVALIDARG; /* FIXME: correct? */
4497 /* ITypeInfo2::GetFuncCustData
4499 * Gets the custom data
4501 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4507 ICOM_THIS( ITypeInfoImpl, iface);
4508 TLBCustData *pCData=NULL;
4509 TLBFuncDesc * pFDesc;
4511 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4512 pFDesc=pFDesc->next);
4515 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4516 if( IsEqualIID(guid, &pCData->guid)) break;
4518 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4521 VariantInit( pVarVal);
4522 VariantCopy( pVarVal, &pCData->data);
4525 return E_INVALIDARG; /* FIXME: correct? */
4528 /* ITypeInfo2::GetParamCustData
4530 * Gets the custom data
4532 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4539 ICOM_THIS( ITypeInfoImpl, iface);
4540 TLBCustData *pCData=NULL;
4541 TLBFuncDesc * pFDesc;
4544 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4546 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4547 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4548 pCData = pCData->next)
4549 if( IsEqualIID(guid, &pCData->guid)) break;
4551 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4555 VariantInit( pVarVal);
4556 VariantCopy( pVarVal, &pCData->data);
4559 return E_INVALIDARG; /* FIXME: correct? */
4562 /* ITypeInfo2::GetVarCustData
4564 * Gets the custom data
4566 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4572 ICOM_THIS( ITypeInfoImpl, iface);
4573 TLBCustData *pCData=NULL;
4574 TLBVarDesc * pVDesc;
4577 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4581 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4583 if( IsEqualIID(guid, &pCData->guid)) break;
4587 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4591 VariantInit( pVarVal);
4592 VariantCopy( pVarVal, &pCData->data);
4595 return E_INVALIDARG; /* FIXME: correct? */
4598 /* ITypeInfo2::GetImplCustData
4600 * Gets the custom data
4602 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4608 ICOM_THIS( ITypeInfoImpl, iface);
4609 TLBCustData *pCData=NULL;
4610 TLBImplType * pRDesc;
4613 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4617 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4619 if( IsEqualIID(guid, &pCData->guid)) break;
4623 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4627 VariantInit( pVarVal);
4628 VariantCopy( pVarVal, &pCData->data);
4631 return E_INVALIDARG; /* FIXME: correct? */
4634 /* ITypeInfo2::GetDocumentation2
4636 * Retrieves the documentation string, the complete Help file name and path,
4637 * the localization context to use, and the context ID for the library Help
4638 * topic in the Help file.
4641 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4645 BSTR *pbstrHelpString,
4646 DWORD *pdwHelpStringContext,
4647 BSTR *pbstrHelpStringDll)
4649 ICOM_THIS( ITypeInfoImpl, iface);
4650 TLBFuncDesc * pFDesc;
4651 TLBVarDesc * pVDesc;
4652 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4653 "HelpStringContext(%p) HelpStringDll(%p)\n",
4654 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4655 pbstrHelpStringDll );
4656 /* the help string should be obtained from the helpstringdll,
4657 * using the _DLLGetDocumentation function, based on the supplied
4658 * lcid. Nice to do sometime...
4660 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4662 *pbstrHelpString=SysAllocString(This->Name);
4663 if(pdwHelpStringContext)
4664 *pdwHelpStringContext=This->dwHelpStringContext;
4665 if(pbstrHelpStringDll)
4666 *pbstrHelpStringDll=
4667 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4669 }else {/* for a member */
4670 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4671 if(pFDesc->funcdesc.memid==memid){
4673 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4674 if(pdwHelpStringContext)
4675 *pdwHelpStringContext=pFDesc->HelpStringContext;
4676 if(pbstrHelpStringDll)
4677 *pbstrHelpStringDll=
4678 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4681 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4682 if(pVDesc->vardesc.memid==memid){
4684 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4685 if(pdwHelpStringContext)
4686 *pdwHelpStringContext=pVDesc->HelpStringContext;
4687 if(pbstrHelpStringDll)
4688 *pbstrHelpStringDll=
4689 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4693 return TYPE_E_ELEMENTNOTFOUND;
4696 /* ITypeInfo2::GetAllCustData
4698 * Gets all custom data items for the Type info.
4701 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4703 CUSTDATA *pCustData)
4705 ICOM_THIS( ITypeInfoImpl, iface);
4706 TLBCustData *pCData;
4709 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4711 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4712 if(pCustData->prgCustData ){
4713 pCustData->cCustData=This->ctCustData;
4714 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4715 pCustData->prgCustData[i].guid=pCData->guid;
4716 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4719 ERR(" OUT OF MEMORY! \n");
4720 return E_OUTOFMEMORY;
4725 /* ITypeInfo2::GetAllFuncCustData
4727 * Gets all custom data items for the specified Function
4730 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4733 CUSTDATA *pCustData)
4735 ICOM_THIS( ITypeInfoImpl, iface);
4736 TLBCustData *pCData;
4737 TLBFuncDesc * pFDesc;
4739 TRACE("(%p) index %d\n", This, index);
4740 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4741 pFDesc=pFDesc->next)
4744 pCustData->prgCustData =
4745 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4746 if(pCustData->prgCustData ){
4747 pCustData->cCustData=pFDesc->ctCustData;
4748 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4749 pCData = pCData->next){
4750 pCustData->prgCustData[i].guid=pCData->guid;
4751 VariantCopy(& pCustData->prgCustData[i].varValue,
4755 ERR(" OUT OF MEMORY! \n");
4756 return E_OUTOFMEMORY;
4760 return TYPE_E_ELEMENTNOTFOUND;
4763 /* ITypeInfo2::GetAllParamCustData
4765 * Gets all custom data items for the Functions
4768 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4769 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4771 ICOM_THIS( ITypeInfoImpl, iface);
4772 TLBCustData *pCData=NULL;
4773 TLBFuncDesc * pFDesc;
4775 TRACE("(%p) index %d\n", This, indexFunc);
4776 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4777 pFDesc=pFDesc->next)
4779 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4780 pCustData->prgCustData =
4781 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4782 sizeof(CUSTDATAITEM));
4783 if(pCustData->prgCustData ){
4784 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4785 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4786 pCData; i++, pCData = pCData->next){
4787 pCustData->prgCustData[i].guid=pCData->guid;
4788 VariantCopy(& pCustData->prgCustData[i].varValue,
4792 ERR(" OUT OF MEMORY! \n");
4793 return E_OUTOFMEMORY;
4797 return TYPE_E_ELEMENTNOTFOUND;
4800 /* ITypeInfo2::GetAllVarCustData
4802 * Gets all custom data items for the specified Variable
4805 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4806 UINT index, CUSTDATA *pCustData)
4808 ICOM_THIS( ITypeInfoImpl, iface);
4809 TLBCustData *pCData;
4810 TLBVarDesc * pVDesc;
4812 TRACE("(%p) index %d\n", This, index);
4813 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4814 pVDesc=pVDesc->next)
4817 pCustData->prgCustData =
4818 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4819 if(pCustData->prgCustData ){
4820 pCustData->cCustData=pVDesc->ctCustData;
4821 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4822 pCData = pCData->next){
4823 pCustData->prgCustData[i].guid=pCData->guid;
4824 VariantCopy(& pCustData->prgCustData[i].varValue,
4828 ERR(" OUT OF MEMORY! \n");
4829 return E_OUTOFMEMORY;
4833 return TYPE_E_ELEMENTNOTFOUND;
4836 /* ITypeInfo2::GetAllImplCustData
4838 * Gets all custom data items for the specified implementation type
4841 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4844 CUSTDATA *pCustData)
4846 ICOM_THIS( ITypeInfoImpl, iface);
4847 TLBCustData *pCData;
4848 TLBImplType * pRDesc;
4850 TRACE("(%p) index %d\n", This, index);
4851 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4852 pRDesc=pRDesc->next)
4855 pCustData->prgCustData =
4856 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4857 if(pCustData->prgCustData ){
4858 pCustData->cCustData=pRDesc->ctCustData;
4859 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4860 pCData = pCData->next){
4861 pCustData->prgCustData[i].guid=pCData->guid;
4862 VariantCopy(& pCustData->prgCustData[i].varValue,
4866 ERR(" OUT OF MEMORY! \n");
4867 return E_OUTOFMEMORY;
4871 return TYPE_E_ELEMENTNOTFOUND;
4874 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4876 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4878 ITypeInfo_fnQueryInterface,
4880 ITypeInfo_fnRelease,
4882 ITypeInfo_fnGetTypeAttr,
4883 ITypeInfo_fnGetTypeComp,
4884 ITypeInfo_fnGetFuncDesc,
4885 ITypeInfo_fnGetVarDesc,
4886 ITypeInfo_fnGetNames,
4887 ITypeInfo_fnGetRefTypeOfImplType,
4888 ITypeInfo_fnGetImplTypeFlags,
4889 ITypeInfo_fnGetIDsOfNames,
4891 ITypeInfo_fnGetDocumentation,
4892 ITypeInfo_fnGetDllEntry,
4893 ITypeInfo_fnGetRefTypeInfo,
4894 ITypeInfo_fnAddressOfMember,
4895 ITypeInfo_fnCreateInstance,
4896 ITypeInfo_fnGetMops,
4897 ITypeInfo_fnGetContainingTypeLib,
4898 ITypeInfo_fnReleaseTypeAttr,
4899 ITypeInfo_fnReleaseFuncDesc,
4900 ITypeInfo_fnReleaseVarDesc,
4902 ITypeInfo2_fnGetTypeKind,
4903 ITypeInfo2_fnGetTypeFlags,
4904 ITypeInfo2_fnGetFuncIndexOfMemId,
4905 ITypeInfo2_fnGetVarIndexOfMemId,
4906 ITypeInfo2_fnGetCustData,
4907 ITypeInfo2_fnGetFuncCustData,
4908 ITypeInfo2_fnGetParamCustData,
4909 ITypeInfo2_fnGetVarCustData,
4910 ITypeInfo2_fnGetImplTypeCustData,
4911 ITypeInfo2_fnGetDocumentation2,
4912 ITypeInfo2_fnGetAllCustData,
4913 ITypeInfo2_fnGetAllFuncCustData,
4914 ITypeInfo2_fnGetAllParamCustData,
4915 ITypeInfo2_fnGetAllVarCustData,
4916 ITypeInfo2_fnGetAllImplTypeCustData,