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];
265 const WCHAR *pFile, *pIndexStr;
268 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
271 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
274 /* Look for a trailing '\\' followed by an index */
275 pIndexStr = strrchrW(szFile, '\\');
276 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
277 index = wcstol(pIndexStr, NULL, 10);
278 memcpy(szFileCopy, szFile,
279 (pIndexStr - szFile - 1) * sizeof(WCHAR));
280 szFileCopy[pIndexStr - szFile - 1] = '\0';
282 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
284 return TYPE_E_CANTLOADLIBRARY;
286 return TYPE_E_CANTLOADLIBRARY;
289 TRACE("File %s index %d\n", debugstr_w(pFile), index);
291 res = TLB_ReadTypeLib(pFile, 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 ptiRet->index=count;
1743 /* fill in the typeattr fields */
1744 FIXME("Assign constructor/destructor memid\n");
1746 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1747 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1748 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1749 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1750 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1751 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1752 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1753 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1754 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1755 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1756 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1757 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1758 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1759 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1760 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1761 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1762 MSFT_GetTdesc(pcx, tiBase.datatype1,
1763 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1766 /* IDLDESC idldescType; *//* never saw this one != zero */
1768 /* name, eventually add to a hash table */
1769 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1770 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1772 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1773 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1774 ptiRet->dwHelpContext=tiBase.helpcontext;
1775 /* note: InfoType's Help file and HelpStringDll come from the containing
1776 * library. Further HelpString and Docstring appear to be the same thing :(
1779 if(ptiRet->TypeAttr.cFuncs >0 )
1780 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1781 ptiRet->TypeAttr.cVars,
1782 tiBase.memoffset, & ptiRet->funclist);
1784 if(ptiRet->TypeAttr.cVars >0 )
1785 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1786 ptiRet->TypeAttr.cVars,
1787 tiBase.memoffset, & ptiRet->varlist);
1788 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1789 switch(ptiRet->TypeAttr.typekind)
1792 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1795 case TKIND_DISPATCH:
1796 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1798 if (tiBase.datatype1 != -1)
1800 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1801 ptiRet->impltypelist->hRef = tiBase.datatype1;
1804 { /* FIXME: This is a really bad hack to add IDispatch */
1805 char* szStdOle = "stdole2.tlb\0";
1806 int nStdOleLen = strlen(szStdOle);
1807 TLBRefType **ppRef = &ptiRet->reflist;
1810 if((*ppRef)->reference == -1)
1812 ppRef = &(*ppRef)->next;
1815 *ppRef = TLB_Alloc(sizeof(**ppRef));
1816 (*ppRef)->guid = IID_IDispatch;
1817 (*ppRef)->reference = -1;
1818 (*ppRef)->index = TLB_REF_USE_GUID;
1819 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1820 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1821 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1824 MultiByteToWideChar(CP_ACP,
1828 (*ppRef)->pImpTLInfo->name,
1829 SysStringLen((*ppRef)->pImpTLInfo->name));
1831 (*ppRef)->pImpTLInfo->lcid = 0;
1832 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1833 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1838 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1839 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1840 ptiRet->impltypelist->hRef = tiBase.datatype1;
1845 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1847 TRACE_(typelib)("%s guid: %s kind:%s\n",
1848 debugstr_w(ptiRet->Name),
1849 debugstr_guid(&ptiRet->TypeAttr.guid),
1850 typekind_desc[ptiRet->TypeAttr.typekind]);
1855 /****************************************************************************
1858 * find the type of the typelib file and map the typelib resource into
1861 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1862 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1863 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1865 int ret = TYPE_E_CANTLOADLIBRARY;
1866 DWORD dwSignature = 0;
1869 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1873 /* check the signature of the file */
1874 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1875 if (INVALID_HANDLE_VALUE != hFile)
1877 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1880 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1883 /* retrieve file size */
1884 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1886 /* first try to load as *.tlb */
1887 dwSignature = *((DWORD*) pBase);
1888 if ( dwSignature == MSFT_SIGNATURE)
1890 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1892 else if ( dwSignature == SLTG_SIGNATURE)
1894 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1896 UnmapViewOfFile(pBase);
1898 CloseHandle(hMapping);
1903 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1905 /* find the typelibrary resource*/
1906 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1907 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1910 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1914 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1917 LPVOID pBase = LockResource(hGlobal);
1918 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1922 /* try to load as incore resource */
1923 dwSignature = *((DWORD*) pBase);
1924 if ( dwSignature == MSFT_SIGNATURE)
1926 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1928 else if ( dwSignature == SLTG_SIGNATURE)
1930 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1934 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1937 FreeResource( hGlobal );
1940 FreeLibrary(hinstDLL);
1947 ERR("Loading of typelib %s failed with error 0x%08lx\n",
1948 debugstr_w(pszFileName), GetLastError());
1953 /*================== ITypeLib(2) Methods ===================================*/
1955 /****************************************************************************
1956 * ITypeLib2_Constructor_MSFT
1958 * loading an MSFT typelib from an in-memory image
1960 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
1964 MSFT_Header tlbHeader;
1965 MSFT_SegDir tlbSegDir;
1966 ITypeLibImpl * pTypeLibImpl;
1968 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1970 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1971 if (!pTypeLibImpl) return NULL;
1973 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1974 pTypeLibImpl->ref = 1;
1976 /* get pointer to beginning of typelib data */
1980 cx.pLibInfo = pTypeLibImpl;
1981 cx.length = dwTLBLength;
1984 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1986 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
1987 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
1988 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
1991 /* there is a small amount of information here until the next important
1993 * the segment directory . Try to calculate the amount of data */
1994 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
1996 /* now read the segment directory */
1997 TRACE("read segment directory (at %ld)\n",lPSegDir);
1998 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
1999 cx.pTblDir = &tlbSegDir;
2001 /* just check two entries */
2002 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2004 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2005 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2009 /* now fill our internal data */
2010 /* TLIBATTR fields */
2011 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2012 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
2013 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2014 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2015 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2016 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2018 /* name, eventually add to a hash table */
2019 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2022 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2023 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2025 if( tlbHeader.varflags & HELPDLLFLAG)
2028 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2029 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2032 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2035 if(tlbHeader.CustomDataOffset >= 0)
2037 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2040 /* fill in typedescriptions */
2041 if(tlbSegDir.pTypdescTab.length > 0)
2043 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2045 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2046 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2049 /* FIXME: add several sanity checks here */
2050 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2051 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2053 /* FIXME: check safearray */
2055 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2057 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2059 else if(td[0] == VT_CARRAY)
2061 /* array descr table here */
2062 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2064 else if(td[0] == VT_USERDEFINED)
2066 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2068 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2071 /* second time around to fill the array subscript info */
2074 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2075 if(tlbSegDir.pArrayDescriptions.offset>0)
2077 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2078 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2081 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2083 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2085 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2087 for(j = 0; j<td[2]; j++)
2089 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2090 sizeof(INT), &cx, DO_NOT_SEEK);
2091 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2092 sizeof(INT), &cx, DO_NOT_SEEK);
2097 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2098 ERR("didn't find array description data\n");
2103 /* imported type libs */
2104 if(tlbSegDir.pImpFiles.offset>0)
2106 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2107 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2110 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2112 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2113 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2114 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2116 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2117 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2118 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2119 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2122 (*ppImpLib)->name = TLB_Alloc(size+1);
2123 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2124 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2125 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2127 ppImpLib = &(*ppImpLib)->next;
2132 if(tlbHeader.nrtypeinfos >= 0 )
2134 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2135 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2138 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2140 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2142 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2143 ppTI = &((*ppTI)->next);
2144 (pTypeLibImpl->TypeInfoCount)++;
2148 TRACE("(%p)\n", pTypeLibImpl);
2149 return (ITypeLib2*) pTypeLibImpl;
2153 static BSTR TLB_MultiByteToBSTR(char *ptr)
2159 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2160 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2161 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2162 ret = SysAllocString(nameW);
2163 HeapFree(GetProcessHeap(), 0, nameW);
2167 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2173 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2174 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2178 guid->Data4[0] = s >> 8;
2179 guid->Data4[1] = s & 0xff;
2182 for(i = 0; i < 6; i++) {
2183 memcpy(b, str + 24 + 2 * i, 2);
2184 guid->Data4[i + 2] = strtol(b, NULL, 16);
2189 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2196 bytelen = *(WORD*)ptr;
2197 if(bytelen == 0xffff) return 2;
2198 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2199 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2200 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2201 *pBstr = SysAllocStringLen(nameW, len);
2202 HeapFree(GetProcessHeap(), 0, nameW);
2206 static WORD SLTG_ReadStringA(char *ptr, char **str)
2211 bytelen = *(WORD*)ptr;
2212 if(bytelen == 0xffff) return 2;
2213 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2214 memcpy(*str, ptr + 2, bytelen);
2215 (*str)[bytelen] = '\0';
2219 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2221 char *ptr = pLibBlk;
2224 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2225 FIXME("libblk magic = %04x\n", w);
2230 if((w = *(WORD*)ptr) != 0xffff) {
2231 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2236 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2238 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2240 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2243 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2246 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2249 ptr += 4; /* skip res12 */
2251 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2254 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2257 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2260 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2261 ptr += sizeof(GUID);
2263 return ptr - (char*)pLibBlk;
2266 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2269 TYPEDESC *pTD = &pElem->tdesc;
2271 /* Handle [in/out] first */
2272 if((*pType & 0xc000) == 0xc000)
2273 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2274 else if(*pType & 0x8000)
2275 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2276 else if(*pType & 0x4000)
2277 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2279 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2282 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2285 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2288 if((*pType & 0xe00) == 0xe00) {
2290 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2292 pTD = pTD->u.lptdesc;
2294 switch(*pType & 0x7f) {
2297 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2299 pTD = pTD->u.lptdesc;
2302 case VT_USERDEFINED:
2303 pTD->vt = VT_USERDEFINED;
2304 pTD->u.hreftype = *(++pType) / 4;
2310 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2313 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2315 pTD->vt = VT_CARRAY;
2316 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2318 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2319 pTD->u.lpadesc->cDims = pSA->cDims;
2320 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2321 pSA->cDims * sizeof(SAFEARRAYBOUND));
2323 pTD = &pTD->u.lpadesc->tdescElem;
2329 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2333 pTD->vt = VT_SAFEARRAY;
2334 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2336 pTD = pTD->u.lptdesc;
2340 pTD->vt = *pType & 0x7f;
2350 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2355 TLBRefType **ppRefType;
2357 if(pRef->magic != SLTG_REF_MAGIC) {
2358 FIXME("Ref magic = %x\n", pRef->magic);
2361 name = ( (char*)(&pRef->names) + pRef->number);
2363 ppRefType = &pTI->reflist;
2364 for(ref = 0; ref < pRef->number >> 3; ref++) {
2366 unsigned int lib_offs, type_num;
2368 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2369 sizeof(**ppRefType));
2371 name += SLTG_ReadStringA(name, &refname);
2372 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2373 FIXME("Can't sscanf ref\n");
2374 if(lib_offs != 0xffff) {
2375 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2378 if((*import)->offset == lib_offs)
2380 import = &(*import)->next;
2383 char fname[MAX_PATH+1];
2386 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2388 (*import)->offset = lib_offs;
2389 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2391 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2392 &(*import)->wVersionMajor,
2393 &(*import)->wVersionMinor,
2394 &(*import)->lcid, fname) != 4) {
2395 FIXME("can't sscanf ref %s\n",
2396 pNameTable + lib_offs + 40);
2398 len = strlen(fname);
2399 if(fname[len-1] != '#')
2400 FIXME("fname = %s\n", fname);
2401 fname[len-1] = '\0';
2402 (*import)->name = TLB_MultiByteToBSTR(fname);
2404 (*ppRefType)->pImpTLInfo = *import;
2405 } else { /* internal ref */
2406 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2408 (*ppRefType)->reference = ref;
2409 (*ppRefType)->index = type_num;
2411 HeapFree(GetProcessHeap(), 0, refname);
2412 ppRefType = &(*ppRefType)->next;
2414 if((BYTE)*name != SLTG_REF_MAGIC)
2415 FIXME("End of ref block magic = %x\n", *name);
2416 dump_TLBRefType(pTI->reflist);
2419 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2422 SLTG_ImplInfo *info;
2423 TLBImplType **ppImplType = &pTI->impltypelist;
2424 /* I don't really get this structure, usually it's 0x16 bytes
2425 long, but iuser.tlb contains some that are 0x18 bytes long.
2426 That's ok because we can use the next ptr to jump to the next
2427 one. But how do we know the length of the last one? The WORD
2428 at offs 0x8 might be the clue. For now I'm just assuming that
2429 the last one is the regular 0x16 bytes. */
2431 info = (SLTG_ImplInfo*)pBlk;
2433 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2434 sizeof(**ppImplType));
2435 (*ppImplType)->hRef = info->ref;
2436 (*ppImplType)->implflags = info->impltypeflags;
2437 pTI->TypeAttr.cImplTypes++;
2438 ppImplType = &(*ppImplType)->next;
2440 if(info->next == 0xffff)
2443 FIXME("Interface inheriting more than one interface\n");
2444 info = (SLTG_ImplInfo*)(pBlk + info->next);
2446 info++; /* see comment at top of function */
2450 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2453 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2454 SLTG_MemberHeader *pMemHeader;
2455 char *pFirstItem, *pNextItem;
2457 if(pTIHeader->href_table != 0xffffffff) {
2458 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2463 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2465 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2467 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2468 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2471 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2475 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2478 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2479 SLTG_MemberHeader *pMemHeader;
2480 SLTG_Function *pFunc;
2481 char *pFirstItem, *pNextItem;
2482 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2485 if(pTIHeader->href_table != 0xffffffff) {
2486 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2490 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2492 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2494 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2495 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2498 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2499 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2504 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2505 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2506 FIXME("func magic = %02x\n", pFunc->magic);
2509 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2510 sizeof(**ppFuncDesc));
2511 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2513 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2514 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2515 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2516 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2517 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2518 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2520 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2521 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2523 if(pFunc->retnextopt & 0x80)
2524 pType = &pFunc->rettype;
2526 pType = (WORD*)(pFirstItem + pFunc->rettype);
2529 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2531 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2532 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2533 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2534 (*ppFuncDesc)->pParamDesc =
2535 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2536 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2538 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2540 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2541 char *paramName = pNameTable + *pArg;
2543 /* If arg type follows then paramName points to the 2nd
2544 letter of the name, else the next WORD is an offset to
2545 the arg type and paramName points to the first letter.
2546 So let's take one char off paramName and see if we're
2547 pointing at an alpha-numeric char. However if *pArg is
2548 0xffff or 0xfffe then the param has no name, the former
2549 meaning that the next WORD is the type, the latter
2550 meaning the the next WORD is an offset to the type. */
2555 else if(*pArg == 0xfffe) {
2559 else if(!isalnum(*(paramName-1)))
2564 if(HaveOffs) { /* the next word is an offset to type */
2565 pType = (WORD*)(pFirstItem + *pArg);
2566 SLTG_DoType(pType, pFirstItem,
2567 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2572 pArg = SLTG_DoType(pArg, pFirstItem,
2573 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2576 /* Are we an optional param ? */
2577 if((*ppFuncDesc)->funcdesc.cParams - param <=
2578 (*ppFuncDesc)->funcdesc.cParamsOpt)
2579 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2582 (*ppFuncDesc)->pParamDesc[param].Name =
2583 TLB_MultiByteToBSTR(paramName);
2587 ppFuncDesc = &((*ppFuncDesc)->next);
2588 if(pFunc->next == 0xffff) break;
2590 pTI->TypeAttr.cFuncs = num;
2591 dump_TLBFuncDesc(pTI->funclist);
2592 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2595 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2598 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2599 SLTG_MemberHeader *pMemHeader;
2600 SLTG_RecordItem *pItem;
2602 TLBVarDesc **ppVarDesc = &pTI->varlist;
2607 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2609 pFirstItem = (char*)(pMemHeader + 1);
2610 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2611 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2612 if(pItem->magic != SLTG_RECORD_MAGIC) {
2613 FIXME("record magic = %02x\n", pItem->magic);
2616 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2617 sizeof(**ppVarDesc));
2618 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2619 (*ppVarDesc)->vardesc.memid = pItem->memid;
2620 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2621 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2623 if(pItem->typepos == 0x02)
2624 pType = &pItem->type;
2625 else if(pItem->typepos == 0x00)
2626 pType = (WORD*)(pFirstItem + pItem->type);
2628 FIXME("typepos = %02x\n", pItem->typepos);
2632 SLTG_DoType(pType, pFirstItem,
2633 &(*ppVarDesc)->vardesc.elemdescVar);
2635 /* FIXME("helpcontext, helpstring\n"); */
2637 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2639 ppVarDesc = &((*ppVarDesc)->next);
2640 if(pItem->next == 0xffff) break;
2642 pTI->TypeAttr.cVars = num;
2643 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2646 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2649 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2650 SLTG_MemberHeader *pMemHeader;
2651 SLTG_EnumItem *pItem;
2653 TLBVarDesc **ppVarDesc = &pTI->varlist;
2656 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2658 pFirstItem = (char*)(pMemHeader + 1);
2659 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2660 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2661 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2662 FIXME("enumitem magic = %04x\n", pItem->magic);
2665 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2666 sizeof(**ppVarDesc));
2667 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2668 (*ppVarDesc)->vardesc.memid = pItem->memid;
2669 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2671 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2672 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2673 *(INT*)(pItem->value + pFirstItem);
2674 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2675 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2676 /* FIXME("helpcontext, helpstring\n"); */
2678 ppVarDesc = &((*ppVarDesc)->next);
2679 if(pItem->next == 0xffff) break;
2681 pTI->TypeAttr.cVars = num;
2682 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2685 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2686 managable copy of it into this */
2699 } SLTG_InternalOtherTypeInfo;
2701 /****************************************************************************
2702 * ITypeLib2_Constructor_SLTG
2704 * loading a SLTG typelib from an in-memory image
2706 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2708 ITypeLibImpl *pTypeLibImpl;
2709 SLTG_Header *pHeader;
2710 SLTG_BlkEntry *pBlkEntry;
2714 LPVOID pBlk, pFirstBlk;
2715 SLTG_LibBlk *pLibBlk;
2716 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2717 char *pAfterOTIBlks = NULL;
2718 char *pNameTable, *ptr;
2721 ITypeInfoImpl **ppTypeInfoImpl;
2723 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2725 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2726 if (!pTypeLibImpl) return NULL;
2728 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2729 pTypeLibImpl->ref = 1;
2734 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2735 pHeader->nrOfFileBlks );
2736 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2737 FIXME("Header type magic 0x%08lx not supported.\n",
2738 pHeader->SLTG_magic);
2742 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2743 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2745 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2746 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2748 /* Next we have a magic block */
2749 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2751 /* Let's see if we're still in sync */
2752 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2753 sizeof(SLTG_COMPOBJ_MAGIC))) {
2754 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2757 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2758 sizeof(SLTG_DIR_MAGIC))) {
2759 FIXME("dir magic = %s\n", pMagic->dir_magic);
2763 pIndex = (SLTG_Index*)(pMagic+1);
2765 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2767 pFirstBlk = (LPVOID)(pPad9 + 1);
2769 /* We'll set up a ptr to the main library block, which is the last one. */
2771 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2772 pBlkEntry[order].next != 0;
2773 order = pBlkEntry[order].next - 1, i++) {
2774 pBlk += pBlkEntry[order].len;
2778 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2780 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2785 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2787 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2788 sizeof(*pOtherTypeInfoBlks) *
2789 pTypeLibImpl->TypeInfoCount);
2792 ptr = (char*)pLibBlk + len;
2794 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2798 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2800 w = *(WORD*)(ptr + 2);
2803 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2805 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2806 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2808 w = *(WORD*)(ptr + 4 + len);
2810 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2812 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2814 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2815 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2817 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2818 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2819 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2821 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2823 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2826 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2827 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2828 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2829 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2830 len += sizeof(SLTG_OtherTypeInfo);
2834 pAfterOTIBlks = ptr;
2836 /* Skip this WORD and get the next DWORD */
2837 len = *(DWORD*)(pAfterOTIBlks + 2);
2839 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2840 magic dust and we should be pointing at the beginning of the name
2843 pNameTable = (char*)pLibBlk + len + 0x216;
2847 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2849 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2852 /* Hopefully we now have enough ptrs set up to actually read in
2853 some TypeInfos. It's not clear which order to do them in, so
2854 I'll just follow the links along the BlkEntry chain and read
2855 them in in the order in which they're in the file */
2857 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2859 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2860 pBlkEntry[order].next != 0;
2861 order = pBlkEntry[order].next - 1, i++) {
2863 SLTG_TypeInfoHeader *pTIHeader;
2864 SLTG_TypeInfoTail *pTITail;
2866 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2867 pOtherTypeInfoBlks[i].index_name)) {
2868 FIXME("Index strings don't match\n");
2873 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2874 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2877 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2878 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2879 (*ppTypeInfoImpl)->index = i;
2880 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2881 pOtherTypeInfoBlks[i].name_offs +
2883 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2884 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2886 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2887 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2888 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2889 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2890 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2892 if((pTIHeader->typeflags1 & 7) != 2)
2893 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2894 if(pTIHeader->typeflags3 != 2)
2895 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2897 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2898 debugstr_w((*ppTypeInfoImpl)->Name),
2899 typekind_desc[pTIHeader->typekind],
2900 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2901 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2903 switch(pTIHeader->typekind) {
2905 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2909 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2912 case TKIND_INTERFACE:
2913 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2917 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2921 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2927 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2928 but we've already set those */
2929 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2930 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2931 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2933 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2934 pBlk += pBlkEntry[order].len;
2937 if(i != pTypeLibImpl->TypeInfoCount) {
2938 FIXME("Somehow processed %d TypeInfos\n", i);
2942 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2943 return (ITypeLib2*)pTypeLibImpl;
2946 /* ITypeLib::QueryInterface
2948 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2953 ICOM_THIS( ITypeLibImpl, iface);
2955 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2958 if(IsEqualIID(riid, &IID_IUnknown) ||
2959 IsEqualIID(riid,&IID_ITypeLib)||
2960 IsEqualIID(riid,&IID_ITypeLib2))
2967 ITypeLib2_AddRef(iface);
2968 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2971 TRACE("-- Interface: E_NOINTERFACE\n");
2972 return E_NOINTERFACE;
2977 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
2979 ICOM_THIS( ITypeLibImpl, iface);
2981 TRACE("(%p)->ref is %u\n",This, This->ref);
2983 return ++(This->ref);
2986 /* ITypeLib::Release
2988 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
2990 ICOM_THIS( ITypeLibImpl, iface);
2994 TRACE("(%p)->(%u)\n",This, This->ref);
2998 /* fixme destroy child objects */
3000 TRACE(" destroying ITypeLib(%p)\n",This);
3004 SysFreeString(This->Name);
3008 if (This->DocString)
3010 SysFreeString(This->DocString);
3011 This->DocString = NULL;
3016 SysFreeString(This->HelpFile);
3017 This->HelpFile = NULL;
3020 if (This->HelpStringDll)
3022 SysFreeString(This->HelpStringDll);
3023 This->HelpStringDll = NULL;
3026 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3027 HeapFree(GetProcessHeap(),0,This);
3034 /* ITypeLib::GetTypeInfoCount
3036 * Returns the number of type descriptions in the type library
3038 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3040 ICOM_THIS( ITypeLibImpl, iface);
3041 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3042 return This->TypeInfoCount;
3045 /* ITypeLib::GetTypeInfo
3047 * retrieves the specified type description in the library.
3049 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3052 ITypeInfo **ppTInfo)
3056 ICOM_THIS( ITypeLibImpl, iface);
3057 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3059 TRACE("(%p)->(index=%d) \n", This, index);
3061 if (!ppTInfo) return E_INVALIDARG;
3063 /* search element n in list */
3064 for(i=0; i < index; i++)
3066 pTypeInfo = pTypeInfo->next;
3069 TRACE("-- element not found\n");
3070 return TYPE_E_ELEMENTNOTFOUND;
3074 *ppTInfo = (ITypeInfo *) pTypeInfo;
3076 ITypeInfo_AddRef(*ppTInfo);
3077 TRACE("-- found (%p)\n",*ppTInfo);
3082 /* ITypeLibs::GetTypeInfoType
3084 * Retrieves the type of a type description.
3086 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3091 ICOM_THIS( ITypeLibImpl, iface);
3093 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3095 TRACE("(%p) index %d \n",This, index);
3097 if(!pTKind) return E_INVALIDARG;
3099 /* search element n in list */
3100 for(i=0; i < index; i++)
3104 TRACE("-- element not found\n");
3105 return TYPE_E_ELEMENTNOTFOUND;
3107 pTInfo = pTInfo->next;
3110 *pTKind = pTInfo->TypeAttr.typekind;
3111 TRACE("-- found Type (%d)\n", *pTKind);
3115 /* ITypeLib::GetTypeInfoOfGuid
3117 * Retrieves the type description that corresponds to the specified GUID.
3120 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3123 ITypeInfo **ppTInfo)
3125 ICOM_THIS( ITypeLibImpl, iface);
3126 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3128 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3130 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3132 /* search linked list for guid */
3133 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3135 pTypeInfo = pTypeInfo->next;
3139 /* end of list reached */
3140 TRACE("-- element not found\n");
3141 return TYPE_E_ELEMENTNOTFOUND;
3145 TRACE("-- found (%p, %s)\n",
3147 debugstr_w(pTypeInfo->Name));
3149 *ppTInfo = (ITypeInfo*)pTypeInfo;
3150 ITypeInfo_AddRef(*ppTInfo);
3154 /* ITypeLib::GetLibAttr
3156 * Retrieves the structure that contains the library's attributes.
3159 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3161 LPTLIBATTR *ppTLibAttr)
3163 ICOM_THIS( ITypeLibImpl, iface);
3164 TRACE("(%p)\n",This);
3165 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3166 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3170 /* ITypeLib::GetTypeComp
3172 * Enables a client compiler to bind to a library's types, variables,
3173 * constants, and global functions.
3176 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3178 ITypeComp **ppTComp)
3180 ICOM_THIS( ITypeLibImpl, iface);
3181 FIXME("(%p): stub!\n",This);
3185 /* ITypeLib::GetDocumentation
3187 * Retrieves the library's documentation string, the complete Help file name
3188 * and path, and the context identifier for the library Help topic in the Help
3192 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3196 BSTR *pBstrDocString,
3197 DWORD *pdwHelpContext,
3198 BSTR *pBstrHelpFile)
3200 ICOM_THIS( ITypeLibImpl, iface);
3202 HRESULT result = E_INVALIDARG;
3207 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3209 pBstrName, pBstrDocString,
3210 pdwHelpContext, pBstrHelpFile);
3214 /* documentation for the typelib */
3215 if(pBstrName && This->Name)
3217 *pBstrName = SysAllocString(This->Name);
3219 if (!(*pBstrName)) return STG_E_INSUFFICIENTMEMORY;
3221 if(pBstrDocString && This->DocString)
3223 *pBstrDocString = SysAllocString(This->DocString);
3225 if (!(*pBstrDocString)) return STG_E_INSUFFICIENTMEMORY;
3230 *pdwHelpContext = This->dwHelpContext;
3232 if(pBstrHelpFile && This->HelpFile)
3234 *pBstrHelpFile = SysAllocString(This->HelpFile);
3236 if (!(*pBstrHelpFile)) return STG_E_INSUFFICIENTMEMORY;
3243 /* for a typeinfo */
3244 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3246 if(SUCCEEDED(result))
3248 result = ITypeInfo_GetDocumentation(pTInfo,
3252 pdwHelpContext, pBstrHelpFile);
3254 ITypeInfo_Release(pTInfo);
3262 * Indicates whether a passed-in string contains the name of a type or member
3263 * described in the library.
3266 static HRESULT WINAPI ITypeLib2_fnIsName(
3272 ICOM_THIS( ITypeLibImpl, iface);
3273 ITypeInfoImpl *pTInfo;
3274 TLBFuncDesc *pFInfo;
3277 UINT nNameBufLen = SysStringLen(szNameBuf);
3279 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3283 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3284 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3285 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3286 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3287 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3288 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3289 goto ITypeLib2_fnIsName_exit;
3291 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3292 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3297 ITypeLib2_fnIsName_exit:
3298 TRACE("(%p)slow! search for %s: %s found!\n", This,
3299 debugstr_w(szNameBuf), *pfName?"NOT":"");
3304 /* ITypeLib::FindName
3306 * Finds occurrences of a type description in a type library. This may be used
3307 * to quickly verify that a name exists in a type library.
3310 static HRESULT WINAPI ITypeLib2_fnFindName(
3314 ITypeInfo **ppTInfo,
3318 ICOM_THIS( ITypeLibImpl, iface);
3319 ITypeInfoImpl *pTInfo;
3320 TLBFuncDesc *pFInfo;
3324 UINT nNameBufLen = SysStringLen(szNameBuf);
3326 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3327 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3328 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3329 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3330 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3331 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3332 goto ITypeLib2_fnFindName_exit;
3334 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3335 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3337 ITypeLib2_fnFindName_exit:
3338 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3339 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3342 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3343 This, *pcFound, debugstr_w(szNameBuf), j);
3350 /* ITypeLib::ReleaseTLibAttr
3352 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3355 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3357 TLIBATTR *pTLibAttr)
3359 ICOM_THIS( ITypeLibImpl, iface);
3360 TRACE("freeing (%p)\n",This);
3361 HeapFree(GetProcessHeap(),0,pTLibAttr);
3365 /* ITypeLib2::GetCustData
3367 * gets the custom data
3369 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3374 ICOM_THIS( ITypeLibImpl, iface);
3375 TLBCustData *pCData;
3377 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3379 if( IsEqualIID(guid, &pCData->guid)) break;
3382 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3386 VariantInit( pVarVal);
3387 VariantCopy( pVarVal, &pCData->data);
3390 return E_INVALIDARG; /* FIXME: correct? */
3393 /* ITypeLib2::GetLibStatistics
3395 * Returns statistics about a type library that are required for efficient
3396 * sizing of hash tables.
3399 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3401 ULONG *pcUniqueNames,
3402 ULONG *pcchUniqueNames)
3404 ICOM_THIS( ITypeLibImpl, iface);
3406 FIXME("(%p): stub!\n", This);
3408 if(pcUniqueNames) *pcUniqueNames=1;
3409 if(pcchUniqueNames) *pcchUniqueNames=1;
3413 /* ITypeLib2::GetDocumentation2
3415 * Retrieves the library's documentation string, the complete Help file name
3416 * and path, the localization context to use, and the context ID for the
3417 * library Help topic in the Help file.
3420 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3424 BSTR *pbstrHelpString,
3425 DWORD *pdwHelpStringContext,
3426 BSTR *pbstrHelpStringDll)
3428 ICOM_THIS( ITypeLibImpl, iface);
3432 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3434 /* the help string should be obtained from the helpstringdll,
3435 * using the _DLLGetDocumentation function, based on the supplied
3436 * lcid. Nice to do sometime...
3440 /* documentation for the typelib */
3442 *pbstrHelpString=SysAllocString(This->DocString);
3443 if(pdwHelpStringContext)
3444 *pdwHelpStringContext=This->dwHelpContext;
3445 if(pbstrHelpStringDll)
3446 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3452 /* for a typeinfo */
3453 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3455 if(SUCCEEDED(result))
3457 ITypeInfo2 * pTInfo2;
3458 result = ITypeInfo_QueryInterface(pTInfo,
3460 (LPVOID*) &pTInfo2);
3462 if(SUCCEEDED(result))
3464 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3468 pdwHelpStringContext,
3469 pbstrHelpStringDll);
3471 ITypeInfo2_Release(pTInfo2);
3474 ITypeInfo_Release(pTInfo);
3480 /* ITypeLib2::GetAllCustData
3482 * Gets all custom data items for the library.
3485 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3487 CUSTDATA *pCustData)
3489 ICOM_THIS( ITypeLibImpl, iface);
3490 TLBCustData *pCData;
3492 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3493 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3494 if(pCustData->prgCustData ){
3495 pCustData->cCustData=This->ctCustData;
3496 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3497 pCustData->prgCustData[i].guid=pCData->guid;
3498 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3501 ERR(" OUT OF MEMORY! \n");
3502 return E_OUTOFMEMORY;
3507 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3508 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3509 ITypeLib2_fnQueryInterface,
3511 ITypeLib2_fnRelease,
3512 ITypeLib2_fnGetTypeInfoCount,
3513 ITypeLib2_fnGetTypeInfo,
3514 ITypeLib2_fnGetTypeInfoType,
3515 ITypeLib2_fnGetTypeInfoOfGuid,
3516 ITypeLib2_fnGetLibAttr,
3517 ITypeLib2_fnGetTypeComp,
3518 ITypeLib2_fnGetDocumentation,
3520 ITypeLib2_fnFindName,
3521 ITypeLib2_fnReleaseTLibAttr,
3523 ITypeLib2_fnGetCustData,
3524 ITypeLib2_fnGetLibStatistics,
3525 ITypeLib2_fnGetDocumentation2,
3526 ITypeLib2_fnGetAllCustData
3529 /*================== ITypeInfo(2) Methods ===================================*/
3530 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3532 ITypeInfoImpl * pTypeInfoImpl;
3534 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3537 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3538 pTypeInfoImpl->ref=1;
3540 TRACE("(%p)\n", pTypeInfoImpl);
3541 return (ITypeInfo2*) pTypeInfoImpl;
3544 /* ITypeInfo::QueryInterface
3546 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3551 ICOM_THIS( ITypeLibImpl, iface);
3553 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3556 if(IsEqualIID(riid, &IID_IUnknown) ||
3557 IsEqualIID(riid,&IID_ITypeInfo)||
3558 IsEqualIID(riid,&IID_ITypeInfo2))
3562 ITypeInfo_AddRef(iface);
3563 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3566 TRACE("-- Interface: E_NOINTERFACE\n");
3567 return E_NOINTERFACE;
3570 /* ITypeInfo::AddRef
3572 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3574 ICOM_THIS( ITypeInfoImpl, iface);
3578 TRACE("(%p)->ref is %u\n",This, This->ref);
3582 /* ITypeInfo::Release
3584 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3586 ICOM_THIS( ITypeInfoImpl, iface);
3590 TRACE("(%p)->(%u)\n",This, This->ref);
3594 FIXME("destroy child objects\n");
3596 TRACE("destroying ITypeInfo(%p)\n",This);
3599 SysFreeString(This->Name);
3603 if (This->DocString)
3605 SysFreeString(This->DocString);
3606 This->DocString = 0;
3611 ITypeInfo_Release((ITypeInfo*)This->next);
3614 HeapFree(GetProcessHeap(),0,This);
3620 /* ITypeInfo::GetTypeAttr
3622 * Retrieves a TYPEATTR structure that contains the attributes of the type
3626 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3627 LPTYPEATTR *ppTypeAttr)
3629 ICOM_THIS( ITypeInfoImpl, iface);
3630 TRACE("(%p)\n",This);
3631 /* FIXME: must do a copy here */
3632 *ppTypeAttr=&This->TypeAttr;
3636 /* ITypeInfo::GetTypeComp
3638 * Retrieves the ITypeComp interface for the type description, which enables a
3639 * client compiler to bind to the type description's members.
3642 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3643 ITypeComp * *ppTComp)
3645 ICOM_THIS( ITypeInfoImpl, iface);
3646 FIXME("(%p) stub!\n", This);
3650 /* ITypeInfo::GetFuncDesc
3652 * Retrieves the FUNCDESC structure that contains information about a
3653 * specified function.
3656 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3657 LPFUNCDESC *ppFuncDesc)
3659 ICOM_THIS( ITypeInfoImpl, iface);
3661 TLBFuncDesc * pFDesc;
3662 TRACE("(%p) index %d\n", This, index);
3663 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3666 /* FIXME: must do a copy here */
3667 *ppFuncDesc=&pFDesc->funcdesc;
3670 return E_INVALIDARG;
3673 /* ITypeInfo::GetVarDesc
3675 * Retrieves a VARDESC structure that describes the specified variable.
3678 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3679 LPVARDESC *ppVarDesc)
3681 ICOM_THIS( ITypeInfoImpl, iface);
3683 TLBVarDesc * pVDesc;
3684 TRACE("(%p) index %d\n", This, index);
3685 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3688 /* FIXME: must do a copy here */
3689 *ppVarDesc=&pVDesc->vardesc;
3692 return E_INVALIDARG;
3695 /* ITypeInfo_GetNames
3697 * Retrieves the variable with the specified member ID (or the name of the
3698 * property or method and its parameters) that correspond to the specified
3701 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3702 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3704 ICOM_THIS( ITypeInfoImpl, iface);
3705 TLBFuncDesc * pFDesc;
3706 TLBVarDesc * pVDesc;
3708 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3709 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3712 /* function found, now return function and parameter names */
3713 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3716 *rgBstrNames=SysAllocString(pFDesc->Name);
3718 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3724 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3727 *rgBstrNames=SysAllocString(pVDesc->Name);
3732 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3734 /* recursive search */
3737 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3739 if(SUCCEEDED(result))
3741 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3742 ITypeInfo_Release(pTInfo);
3745 WARN("Could not search inherited interface!\n");
3749 WARN("no names found\n");
3752 return TYPE_E_ELEMENTNOTFOUND;
3759 /* ITypeInfo::GetRefTypeOfImplType
3761 * If a type description describes a COM class, it retrieves the type
3762 * description of the implemented interface types. For an interface,
3763 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3767 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3772 ICOM_THIS( ITypeInfoImpl, iface);
3774 TLBImplType *pImpl = This->impltypelist;
3776 TRACE("(%p) index %d\n", This, index);
3777 dump_TypeInfo(This);
3781 /* only valid on dual interfaces;
3782 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3784 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3786 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3787 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3793 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3794 *pRefType = pImpl->hRef;
3799 /* get element n from linked list */
3800 for(i=0; pImpl && i<index; i++)
3802 pImpl = pImpl->next;
3805 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3807 *pRefType = pImpl->hRef;
3809 TRACE("-- 0x%08lx\n", pImpl->hRef );
3816 /* ITypeInfo::GetImplTypeFlags
3818 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3819 * or base interface in a type description.
3821 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3822 UINT index, INT *pImplTypeFlags)
3824 ICOM_THIS( ITypeInfoImpl, iface);
3828 TRACE("(%p) index %d\n", This, index);
3829 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3830 i++, pImpl=pImpl->next)
3832 if(i==index && pImpl){
3833 *pImplTypeFlags=pImpl->implflags;
3837 return TYPE_E_ELEMENTNOTFOUND;
3841 * Maps between member names and member IDs, and parameter names and
3844 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3845 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3847 ICOM_THIS( ITypeInfoImpl, iface);
3848 TLBFuncDesc * pFDesc;
3849 TLBVarDesc * pVDesc;
3852 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3854 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3856 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3857 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3858 for(i=1; i < cNames; i++){
3859 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3860 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3862 if( j<pFDesc->funcdesc.cParams)
3865 ret=DISP_E_UNKNOWNNAME;
3870 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3871 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3872 if(cNames) *pMemId=pVDesc->vardesc.memid;
3876 /* not found, see if this is and interface with an inheritance */
3877 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3878 This->TypeAttr.cImplTypes ){
3879 /* recursive search */
3881 ret=ITypeInfo_GetRefTypeInfo(iface,
3882 This->impltypelist->hRef, &pTInfo);
3884 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3885 ITypeInfo_Release(pTInfo);
3888 WARN("Could not search inherited interface!\n");
3890 WARN("no names found\n");
3891 return DISP_E_UNKNOWNNAME;
3894 /* ITypeInfo::Invoke
3896 * Invokes a method, or accesses a property of an object, that implements the
3897 * interface described by the type description.
3899 static DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3902 if (TRACE_ON(ole)) {
3904 MESSAGE("Calling %p(",func);
3905 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3914 DWORD (WINAPI *xfunc)() = func;
3919 DWORD (WINAPI *xfunc)(DWORD) = func;
3920 res = xfunc(args[0]);
3924 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3925 res = xfunc(args[0],args[1]);
3929 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3930 res = xfunc(args[0],args[1],args[2]);
3934 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
3940 FIXME("unsupported calling convention %d\n",callconv);
3944 TRACE("returns %08lx\n",res);
3948 static HRESULT WINAPI ITypeInfo_fnInvoke(
3953 DISPPARAMS *pDispParams,
3954 VARIANT *pVarResult,
3955 EXCEPINFO *pExcepInfo,
3958 ICOM_THIS( ITypeInfoImpl, iface);
3959 TLBFuncDesc * pFDesc;
3960 TLBVarDesc * pVDesc;
3963 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
3964 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
3966 dump_DispParms(pDispParams);
3968 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3969 if (pFDesc->funcdesc.memid == memid) {
3970 if (pFDesc->funcdesc.invkind & dwFlags)
3974 dump_TLBFuncDescOne(pFDesc);
3975 switch (pFDesc->funcdesc.funckind) {
3976 case FUNC_PUREVIRTUAL:
3977 case FUNC_VIRTUAL: {
3979 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
3980 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
3981 args[0] = (DWORD)pIUnk;
3983 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
3984 if (i<pDispParams->cArgs) {
3985 TRACE("set %d to disparg type %d vs %d\n",i,
3986 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
3987 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
3989 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
3991 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
3992 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
3993 /*FIXME: give pointers for the rest, so propertyget works*/
3994 args[i+1] = (DWORD)&args2[i];
3996 /* If pointer to variant, pass reference to variant
3997 * in result variant array.
3999 if ((tdesc->vt == VT_PTR) &&
4000 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4003 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
4006 if (pFDesc->funcdesc.cParamsOpt)
4007 FIXME("Does not support optional parameters (%d)\n",
4008 pFDesc->funcdesc.cParamsOpt
4011 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4012 pFDesc->funcdesc.callconv,
4013 pFDesc->funcdesc.cParams+1,
4016 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4017 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4018 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4019 /* If we are a pointer to a variant, we are done already */
4020 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4023 VariantInit(&pVarResult[i]);
4024 V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
4026 if (tdesc->vt == VT_PTR)
4027 tdesc = tdesc->u.lptdesc;
4028 V_VT(pVarResult+i) = tdesc->vt;
4030 /* HACK: VB5 likes this.
4031 * I do not know why. There is 1 example in MSDN which uses
4032 * this which appears broken (mixes int vals and
4035 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4036 V_VT(pVarResult+i) = VT_DISPATCH;
4037 TRACE("storing into variant: [%d]\n", i);
4038 dump_Variant(pVarResult+i);
4041 HeapFree(GetProcessHeap(),0,args2);
4042 HeapFree(GetProcessHeap(),0,args);
4045 case FUNC_DISPATCH: {
4049 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4051 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4054 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4055 hr = IDispatch_Invoke(
4056 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4057 pVarResult,pExcepInfo,pArgErr
4060 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4061 IDispatch_Release(disp);
4065 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4069 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4070 if (pVDesc->vardesc.memid == memid) {
4071 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4072 dump_TLBVarDesc(pVDesc);
4077 /* not found, look for it in inherited interfaces */
4078 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4079 /* recursive search */
4082 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4084 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4085 ITypeInfo_Release(pTInfo);
4088 WARN("Could not search inherited interface!\n");
4090 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4091 return DISP_E_MEMBERNOTFOUND;
4094 /* ITypeInfo::GetDocumentation
4096 * Retrieves the documentation string, the complete Help file name and path,
4097 * and the context ID for the Help topic for a specified type description.
4099 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4100 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4101 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4103 ICOM_THIS( ITypeInfoImpl, iface);
4104 TLBFuncDesc * pFDesc;
4105 TLBVarDesc * pVDesc;
4106 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4107 " HelpContext(%p) HelpFile(%p)\n",
4108 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4109 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4111 *pBstrName=SysAllocString(This->Name);
4113 *pBstrDocString=SysAllocString(This->DocString);
4115 *pdwHelpContext=This->dwHelpContext;
4117 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4119 }else {/* for a member */
4120 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4121 if(pFDesc->funcdesc.memid==memid){
4123 *pBstrName = SysAllocString(pFDesc->Name);
4125 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4127 *pdwHelpContext=pFDesc->helpcontext;
4130 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4131 if(pVDesc->vardesc.memid==memid){
4132 FIXME("Not implemented\n");
4136 return TYPE_E_ELEMENTNOTFOUND;
4139 /* ITypeInfo::GetDllEntry
4141 * Retrieves a description or specification of an entry point for a function
4144 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4145 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4148 ICOM_THIS( ITypeInfoImpl, iface);
4149 FIXME("(%p) stub!\n", This);
4153 /* ITypeInfo::GetRefTypeInfo
4155 * If a type description references other type descriptions, it retrieves
4156 * the referenced type descriptions.
4158 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4161 ITypeInfo **ppTInfo)
4163 ICOM_THIS( ITypeInfoImpl, iface);
4164 HRESULT result = E_FAIL;
4167 if (hRefType == -1 &&
4168 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4169 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4171 /* when we meet a DUAL dispinterface, we must create the interface
4174 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4177 /* the interface version contains the same information as the dispinterface
4178 * copy the contents of the structs.
4180 *pTypeInfoImpl = *This;
4181 pTypeInfoImpl->ref = 1;
4183 /* change the type to interface */
4184 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4186 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4188 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4193 TLBRefType *pRefType;
4194 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4195 if(pRefType->reference == hRefType)
4199 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4200 if(pRefType && hRefType != -1) {
4203 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4205 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4207 if(pRefType->pImpTLInfo->pImpTypeLib) {
4208 TRACE("typeinfo in imported typelib that is already loaded\n");
4209 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4210 ITypeLib2_AddRef((ITypeLib*) pTLib);
4213 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4214 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4215 pRefType->pImpTLInfo->wVersionMajor,
4216 pRefType->pImpTLInfo->wVersionMinor,
4217 pRefType->pImpTLInfo->lcid,
4220 if(!SUCCEEDED(result)) {
4221 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4222 result=LoadTypeLib(libnam, &pTLib);
4223 SysFreeString(libnam);
4225 if(SUCCEEDED(result)) {
4226 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4227 ITypeLib2_AddRef(pTLib);
4231 if(SUCCEEDED(result)) {
4232 if(pRefType->index == TLB_REF_USE_GUID)
4233 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4237 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4243 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4244 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4248 /* ITypeInfo::AddressOfMember
4250 * Retrieves the addresses of static functions or variables, such as those
4253 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4254 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4256 ICOM_THIS( ITypeInfoImpl, iface);
4257 FIXME("(%p) stub!\n", This);
4261 /* ITypeInfo::CreateInstance
4263 * Creates a new instance of a type that describes a component object class
4266 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4267 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4269 ICOM_THIS( ITypeInfoImpl, iface);
4270 FIXME("(%p) stub!\n", This);
4274 /* ITypeInfo::GetMops
4276 * Retrieves marshaling information.
4278 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4281 ICOM_THIS( ITypeInfoImpl, iface);
4282 FIXME("(%p) stub!\n", This);
4286 /* ITypeInfo::GetContainingTypeLib
4288 * Retrieves the containing type library and the index of the type description
4289 * within that type library.
4291 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4292 ITypeLib * *ppTLib, UINT *pIndex)
4294 ICOM_THIS( ITypeInfoImpl, iface);
4296 return E_INVALIDARG;
4297 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4298 *pIndex=This->index;
4299 ITypeLib2_AddRef(*ppTLib);
4300 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4304 /* ITypeInfo::ReleaseTypeAttr
4306 * Releases a TYPEATTR previously returned by GetTypeAttr.
4309 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4310 TYPEATTR* pTypeAttr)
4312 ICOM_THIS( ITypeInfoImpl, iface);
4313 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4317 /* ITypeInfo::ReleaseFuncDesc
4319 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4321 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4323 FUNCDESC *pFuncDesc)
4325 ICOM_THIS( ITypeInfoImpl, iface);
4326 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4330 /* ITypeInfo::ReleaseVarDesc
4332 * Releases a VARDESC previously returned by GetVarDesc.
4334 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4337 ICOM_THIS( ITypeInfoImpl, iface);
4338 TRACE("(%p)->(%p)\n", This, pVarDesc);
4342 /* ITypeInfo2::GetTypeKind
4344 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4347 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4348 TYPEKIND *pTypeKind)
4350 ICOM_THIS( ITypeInfoImpl, iface);
4351 *pTypeKind=This->TypeAttr.typekind;
4352 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4356 /* ITypeInfo2::GetTypeFlags
4358 * Returns the type flags without any allocations. This returns a DWORD type
4359 * flag, which expands the type flags without growing the TYPEATTR (type
4363 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4366 ICOM_THIS( ITypeInfoImpl, iface);
4367 *pTypeFlags=This->TypeAttr.wTypeFlags;
4368 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4372 /* ITypeInfo2::GetFuncIndexOfMemId
4373 * Binds to a specific member based on a known DISPID, where the member name
4374 * is not known (for example, when binding to a default member).
4377 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4378 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4380 ICOM_THIS( ITypeInfoImpl, iface);
4381 TLBFuncDesc *pFuncInfo;
4384 /* FIXME: should check for invKind??? */
4385 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4386 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4392 result=E_INVALIDARG;
4394 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4395 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4399 /* TypeInfo2::GetVarIndexOfMemId
4401 * Binds to a specific member based on a known DISPID, where the member name
4402 * is not known (for example, when binding to a default member).
4405 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4406 MEMBERID memid, UINT *pVarIndex)
4408 ICOM_THIS( ITypeInfoImpl, iface);
4409 TLBVarDesc *pVarInfo;
4412 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4413 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4420 result=E_INVALIDARG;
4422 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4423 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4427 /* ITypeInfo2::GetCustData
4429 * Gets the custom data
4431 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4436 ICOM_THIS( ITypeInfoImpl, iface);
4437 TLBCustData *pCData;
4439 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4440 if( IsEqualIID(guid, &pCData->guid)) break;
4442 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4446 VariantInit( pVarVal);
4447 VariantCopy( pVarVal, &pCData->data);
4450 return E_INVALIDARG; /* FIXME: correct? */
4453 /* ITypeInfo2::GetFuncCustData
4455 * Gets the custom data
4457 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4463 ICOM_THIS( ITypeInfoImpl, iface);
4464 TLBCustData *pCData=NULL;
4465 TLBFuncDesc * pFDesc;
4467 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4468 pFDesc=pFDesc->next);
4471 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4472 if( IsEqualIID(guid, &pCData->guid)) break;
4474 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4477 VariantInit( pVarVal);
4478 VariantCopy( pVarVal, &pCData->data);
4481 return E_INVALIDARG; /* FIXME: correct? */
4484 /* ITypeInfo2::GetParamCustData
4486 * Gets the custom data
4488 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4495 ICOM_THIS( ITypeInfoImpl, iface);
4496 TLBCustData *pCData=NULL;
4497 TLBFuncDesc * pFDesc;
4500 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4502 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4503 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4504 pCData = pCData->next)
4505 if( IsEqualIID(guid, &pCData->guid)) break;
4507 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4511 VariantInit( pVarVal);
4512 VariantCopy( pVarVal, &pCData->data);
4515 return E_INVALIDARG; /* FIXME: correct? */
4518 /* ITypeInfo2::GetVarCustData
4520 * Gets the custom data
4522 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4528 ICOM_THIS( ITypeInfoImpl, iface);
4529 TLBCustData *pCData=NULL;
4530 TLBVarDesc * pVDesc;
4533 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4537 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4539 if( IsEqualIID(guid, &pCData->guid)) break;
4543 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4547 VariantInit( pVarVal);
4548 VariantCopy( pVarVal, &pCData->data);
4551 return E_INVALIDARG; /* FIXME: correct? */
4554 /* ITypeInfo2::GetImplCustData
4556 * Gets the custom data
4558 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4564 ICOM_THIS( ITypeInfoImpl, iface);
4565 TLBCustData *pCData=NULL;
4566 TLBImplType * pRDesc;
4569 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4573 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4575 if( IsEqualIID(guid, &pCData->guid)) break;
4579 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4583 VariantInit( pVarVal);
4584 VariantCopy( pVarVal, &pCData->data);
4587 return E_INVALIDARG; /* FIXME: correct? */
4590 /* ITypeInfo2::GetDocumentation2
4592 * Retrieves the documentation string, the complete Help file name and path,
4593 * the localization context to use, and the context ID for the library Help
4594 * topic in the Help file.
4597 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4601 BSTR *pbstrHelpString,
4602 DWORD *pdwHelpStringContext,
4603 BSTR *pbstrHelpStringDll)
4605 ICOM_THIS( ITypeInfoImpl, iface);
4606 TLBFuncDesc * pFDesc;
4607 TLBVarDesc * pVDesc;
4608 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4609 "HelpStringContext(%p) HelpStringDll(%p)\n",
4610 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4611 pbstrHelpStringDll );
4612 /* the help string should be obtained from the helpstringdll,
4613 * using the _DLLGetDocumentation function, based on the supplied
4614 * lcid. Nice to do sometime...
4616 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4618 *pbstrHelpString=SysAllocString(This->Name);
4619 if(pdwHelpStringContext)
4620 *pdwHelpStringContext=This->dwHelpStringContext;
4621 if(pbstrHelpStringDll)
4622 *pbstrHelpStringDll=
4623 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4625 }else {/* for a member */
4626 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4627 if(pFDesc->funcdesc.memid==memid){
4629 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4630 if(pdwHelpStringContext)
4631 *pdwHelpStringContext=pFDesc->HelpStringContext;
4632 if(pbstrHelpStringDll)
4633 *pbstrHelpStringDll=
4634 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4637 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4638 if(pVDesc->vardesc.memid==memid){
4640 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4641 if(pdwHelpStringContext)
4642 *pdwHelpStringContext=pVDesc->HelpStringContext;
4643 if(pbstrHelpStringDll)
4644 *pbstrHelpStringDll=
4645 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4649 return TYPE_E_ELEMENTNOTFOUND;
4652 /* ITypeInfo2::GetAllCustData
4654 * Gets all custom data items for the Type info.
4657 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4659 CUSTDATA *pCustData)
4661 ICOM_THIS( ITypeInfoImpl, iface);
4662 TLBCustData *pCData;
4665 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4667 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4668 if(pCustData->prgCustData ){
4669 pCustData->cCustData=This->ctCustData;
4670 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4671 pCustData->prgCustData[i].guid=pCData->guid;
4672 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4675 ERR(" OUT OF MEMORY! \n");
4676 return E_OUTOFMEMORY;
4681 /* ITypeInfo2::GetAllFuncCustData
4683 * Gets all custom data items for the specified Function
4686 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4689 CUSTDATA *pCustData)
4691 ICOM_THIS( ITypeInfoImpl, iface);
4692 TLBCustData *pCData;
4693 TLBFuncDesc * pFDesc;
4695 TRACE("(%p) index %d\n", This, index);
4696 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4697 pFDesc=pFDesc->next)
4700 pCustData->prgCustData =
4701 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4702 if(pCustData->prgCustData ){
4703 pCustData->cCustData=pFDesc->ctCustData;
4704 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4705 pCData = pCData->next){
4706 pCustData->prgCustData[i].guid=pCData->guid;
4707 VariantCopy(& pCustData->prgCustData[i].varValue,
4711 ERR(" OUT OF MEMORY! \n");
4712 return E_OUTOFMEMORY;
4716 return TYPE_E_ELEMENTNOTFOUND;
4719 /* ITypeInfo2::GetAllParamCustData
4721 * Gets all custom data items for the Functions
4724 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4725 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4727 ICOM_THIS( ITypeInfoImpl, iface);
4728 TLBCustData *pCData=NULL;
4729 TLBFuncDesc * pFDesc;
4731 TRACE("(%p) index %d\n", This, indexFunc);
4732 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4733 pFDesc=pFDesc->next)
4735 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4736 pCustData->prgCustData =
4737 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4738 sizeof(CUSTDATAITEM));
4739 if(pCustData->prgCustData ){
4740 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4741 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4742 pCData; i++, pCData = pCData->next){
4743 pCustData->prgCustData[i].guid=pCData->guid;
4744 VariantCopy(& pCustData->prgCustData[i].varValue,
4748 ERR(" OUT OF MEMORY! \n");
4749 return E_OUTOFMEMORY;
4753 return TYPE_E_ELEMENTNOTFOUND;
4756 /* ITypeInfo2::GetAllVarCustData
4758 * Gets all custom data items for the specified Variable
4761 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4762 UINT index, CUSTDATA *pCustData)
4764 ICOM_THIS( ITypeInfoImpl, iface);
4765 TLBCustData *pCData;
4766 TLBVarDesc * pVDesc;
4768 TRACE("(%p) index %d\n", This, index);
4769 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4770 pVDesc=pVDesc->next)
4773 pCustData->prgCustData =
4774 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4775 if(pCustData->prgCustData ){
4776 pCustData->cCustData=pVDesc->ctCustData;
4777 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4778 pCData = pCData->next){
4779 pCustData->prgCustData[i].guid=pCData->guid;
4780 VariantCopy(& pCustData->prgCustData[i].varValue,
4784 ERR(" OUT OF MEMORY! \n");
4785 return E_OUTOFMEMORY;
4789 return TYPE_E_ELEMENTNOTFOUND;
4792 /* ITypeInfo2::GetAllImplCustData
4794 * Gets all custom data items for the specified implementation type
4797 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4800 CUSTDATA *pCustData)
4802 ICOM_THIS( ITypeInfoImpl, iface);
4803 TLBCustData *pCData;
4804 TLBImplType * pRDesc;
4806 TRACE("(%p) index %d\n", This, index);
4807 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4808 pRDesc=pRDesc->next)
4811 pCustData->prgCustData =
4812 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4813 if(pCustData->prgCustData ){
4814 pCustData->cCustData=pRDesc->ctCustData;
4815 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4816 pCData = pCData->next){
4817 pCustData->prgCustData[i].guid=pCData->guid;
4818 VariantCopy(& pCustData->prgCustData[i].varValue,
4822 ERR(" OUT OF MEMORY! \n");
4823 return E_OUTOFMEMORY;
4827 return TYPE_E_ELEMENTNOTFOUND;
4830 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4832 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4834 ITypeInfo_fnQueryInterface,
4836 ITypeInfo_fnRelease,
4838 ITypeInfo_fnGetTypeAttr,
4839 ITypeInfo_fnGetTypeComp,
4840 ITypeInfo_fnGetFuncDesc,
4841 ITypeInfo_fnGetVarDesc,
4842 ITypeInfo_fnGetNames,
4843 ITypeInfo_fnGetRefTypeOfImplType,
4844 ITypeInfo_fnGetImplTypeFlags,
4845 ITypeInfo_fnGetIDsOfNames,
4847 ITypeInfo_fnGetDocumentation,
4848 ITypeInfo_fnGetDllEntry,
4849 ITypeInfo_fnGetRefTypeInfo,
4850 ITypeInfo_fnAddressOfMember,
4851 ITypeInfo_fnCreateInstance,
4852 ITypeInfo_fnGetMops,
4853 ITypeInfo_fnGetContainingTypeLib,
4854 ITypeInfo_fnReleaseTypeAttr,
4855 ITypeInfo_fnReleaseFuncDesc,
4856 ITypeInfo_fnReleaseVarDesc,
4858 ITypeInfo2_fnGetTypeKind,
4859 ITypeInfo2_fnGetTypeFlags,
4860 ITypeInfo2_fnGetFuncIndexOfMemId,
4861 ITypeInfo2_fnGetVarIndexOfMemId,
4862 ITypeInfo2_fnGetCustData,
4863 ITypeInfo2_fnGetFuncCustData,
4864 ITypeInfo2_fnGetParamCustData,
4865 ITypeInfo2_fnGetVarCustData,
4866 ITypeInfo2_fnGetImplTypeCustData,
4867 ITypeInfo2_fnGetDocumentation2,
4868 ITypeInfo2_fnGetAllCustData,
4869 ITypeInfo2_fnGetAllFuncCustData,
4870 ITypeInfo2_fnGetAllParamCustData,
4871 ITypeInfo2_fnGetAllVarCustData,
4872 ITypeInfo2_fnGetAllImplTypeCustData,