4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * --------------------------------------------------------------------------------------
10 * Known problems (2000, Francois Jacques)
12 * - Tested using OLEVIEW (Platform SDK tool) only.
14 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
15 * creating by doing a straight copy of the dispinterface instance and just changing
16 * its typekind. Pointed structures aren't copied - only the address of the pointers.
17 * So when you release the dispinterface, you delete the vtable-interface structures
18 * as well... fortunately, clean up of structures is not implemented.
20 * - locale stuff is partially implemented but hasn't been tested.
22 * - typelib file is still read in its entirety, but it is released now.
23 * - some garbage is read from function names on some very rare occasions.
25 * --------------------------------------------------------------------------------------
26 * Known problems left from previous implementation (1999, Rein Klazes) :
28 * -. Data structures are straightforward, but slow for look-ups.
29 * -. (related) nothing is hashed
30 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
31 * of them I don't know yet how to implement them.
32 * -. Most error return values are just guessed not checked with windows
34 * -. didn't bother with a c++ interface
35 * -. lousy fatal error handling
36 * -. some methods just return pointers to internal data structures, this is
37 * partly laziness, partly I want to check how windows does it.
49 #include "winnls.h" /* for PRIMARYLANGID */
50 #include "winreg.h" /* for HKEY_LOCAL_MACHINE */
53 #include "wine/unicode.h"
54 #include "wine/obj_base.h"
58 #include "debugtools.h"
61 DEFAULT_DEBUG_CHANNEL(ole);
62 DECLARE_DEBUG_CHANNEL(typelib);
64 /****************************************************************************
65 * QueryPathOfRegTypeLib [TYPELIB.14]
67 * the path is "Classes\Typelib\<guid>\<major>.<minor>\<lcid>\win16\"
72 QueryPathOfRegTypeLib16(
73 REFGUID guid, /* [in] referenced guid */
74 WORD wMaj, /* [in] major version */
75 WORD wMin, /* [in] minor version */
76 LCID lcid, /* [in] locale id */
77 LPBSTR16 path /* [out] path of typelib */
80 char typelibkey[100],pathname[260];
86 sprintf( typelibkey, "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win16",
87 guid->Data1, guid->Data2, guid->Data3,
88 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
89 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
92 sprintf(xguid,"<guid 0x%08lx>",(DWORD)guid);
93 FIXME("(%s,%d,%d,0x%04lx,%p),can't handle non-string guids.\n",xguid,wMaj,wMin,(DWORD)lcid,path);
96 plen = sizeof(pathname);
97 if (RegQueryValueA(HKEY_LOCAL_MACHINE,typelibkey,pathname,&plen)) {
98 /* try again without lang specific id */
100 return QueryPathOfRegTypeLib16(guid,wMaj,wMin,PRIMARYLANGID(lcid),path);
101 FIXME("key %s not found\n",typelibkey);
104 *path = SysAllocString16(pathname);
108 /****************************************************************************
109 * QueryPathOfRegTypeLib [OLEAUT32.164]
114 QueryPathOfRegTypeLib(
115 REFGUID guid, /* [in] referenced guid */
116 WORD wMaj, /* [in] major version */
117 WORD wMin, /* [in] minor version */
118 LCID lcid, /* [in] locale id */
119 LPBSTR path ) /* [out] path of typelib */
121 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
122 string termination character on output strings */
126 DWORD dwPathLen = _MAX_PATH;
130 char szTypeLibKey[100];
131 char szPath[dwPathLen];
139 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
145 sprintf(szTypeLibKey,
146 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
147 guid->Data1, guid->Data2, guid->Data3,
148 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
149 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
154 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
158 else if (myLCID == lcid)
160 /* try with sub-langid */
161 myLCID = SUBLANGID(lcid);
163 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
165 /* try with system langid */
175 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
176 BSTR bstrPath = SysAllocStringLen(NULL,len);
178 MultiByteToWideChar(CP_ACP,
190 TRACE_(typelib)("%s not found\n", szTypeLibKey);
195 /******************************************************************************
196 * CreateTypeLib [OLEAUT32.160] creates a typelib
202 HRESULT WINAPI CreateTypeLib(
203 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
205 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
208 /******************************************************************************
209 * LoadTypeLib [TYPELIB.3] Loads and registers a type library
211 * Docs: OLECHAR FAR* szFile
212 * Docs: iTypeLib FAR* FAR* pptLib
218 HRESULT WINAPI LoadTypeLib16(
219 LPOLESTR szFile, /* [in] Name of file to load from */
220 ITypeLib** pptLib) /* [out] Pointer to pointer to loaded type library */
222 FIXME("(%s,%p): stub\n",debugstr_w((LPWSTR)szFile),pptLib);
230 /******************************************************************************
231 * LoadTypeLib [OLEAUT32.161]
232 * Loads and registers a type library
234 * Docs: OLECHAR FAR* szFile
235 * Docs: iTypeLib FAR* FAR* pptLib
241 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
243 HRESULT WINAPI LoadTypeLib(
244 const OLECHAR *szFile,/* [in] Name of file to load from */
245 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
248 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
251 /******************************************************************************
252 * LoadTypeLibEx [OLEAUT32.183]
253 * Loads and optionally registers a type library
259 HRESULT WINAPI LoadTypeLibEx(
260 LPCOLESTR szFile, /* [in] Name of file to load from */
261 REGKIND regkind, /* [in] Specify kind of registration */
262 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
264 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
268 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
270 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
273 /* Look for a trailing '\\' followed by an index */
274 pIndexStr = strrchrW(szFile, '\\');
275 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
276 index = wcstol(pIndexStr, NULL, 10);
277 memcpy(szFileCopy, szFile,
278 (pIndexStr - szFile - 1) * sizeof(WCHAR));
279 szFileCopy[pIndexStr - szFile - 1] = '\0';
280 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
282 return TYPE_E_CANTLOADLIBRARY;
283 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
284 return TYPE_E_CANTLOADLIBRARY;
286 return TYPE_E_CANTLOADLIBRARY;
289 TRACE("File %s index %d\n", debugstr_w(szPath), index);
291 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
296 case REGKIND_DEFAULT:
297 /* FIXME: is this correct? */
298 if (!szFile || !szFile[0] ||
299 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
301 /* else fall-through */
302 case REGKIND_REGISTER:
303 /* FIXME: Help path? */
304 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
306 IUnknown_Release(*pptLib);
314 TRACE(" returns %08lx\n",res);
318 /******************************************************************************
319 * LoadRegTypeLib [OLEAUT32.162]
321 HRESULT WINAPI LoadRegTypeLib(
322 REFGUID rguid, /* [in] referenced guid */
323 WORD wVerMajor, /* [in] major version */
324 WORD wVerMinor, /* [in] minor version */
325 LCID lcid, /* [in] locale id */
326 ITypeLib **ppTLib) /* [out] path of typelib */
329 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
333 res= LoadTypeLib(bstr, ppTLib);
337 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
343 /******************************************************************************
344 * RegisterTypeLib [OLEAUT32.163]
345 * Adds information about a type library to the System Registry
347 * Docs: ITypeLib FAR * ptlib
348 * Docs: OLECHAR FAR* szFullPath
349 * Docs: OLECHAR FAR* szHelpDir
355 HRESULT WINAPI RegisterTypeLib(
356 ITypeLib * ptlib, /* [in] Pointer to the library*/
357 OLECHAR * szFullPath, /* [in] full Path of the library*/
358 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
369 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
371 if (ptlib == NULL || szFullPath == NULL)
374 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
377 StringFromGUID2(&attr->guid, guid, 80);
378 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
379 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
380 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
381 HeapFree(GetProcessHeap(), 0, guidA);
384 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
385 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
389 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
391 if (RegSetValueExW(key, NULL, 0, REG_SZ,
392 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
400 /* FIXME: This *seems* to be 0 always, not sure though */
401 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
402 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
404 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
405 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
413 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
414 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
417 /* FIXME: is %u correct? */
418 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
419 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
420 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
428 /* register OLE Automation-compatible interfaces for this typelib */
429 types = ITypeLib_GetTypeInfoCount(ptlib);
430 for (tidx=0; tidx<types; tidx++) {
431 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
432 LPOLESTR name = NULL;
433 ITypeInfo *tinfo = NULL;
435 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
437 case TKIND_INTERFACE:
438 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
439 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
442 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
443 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
446 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
447 /* coclasses should probably not be registered? */
450 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
454 TYPEATTR *tattr = NULL;
455 ITypeInfo_GetTypeAttr(tinfo, &tattr);
457 TRACE_(typelib)("guid=%s, flags=%04x\n",
458 debugstr_guid(&tattr->guid),
460 if (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION) {
461 /* register interface<->typelib coupling */
462 StringFromGUID2(&tattr->guid, guid, 80);
463 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
464 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
465 HeapFree(GetProcessHeap(), 0, guidA);
467 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
468 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
470 RegSetValueExW(key, NULL, 0, REG_SZ,
471 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
473 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
474 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
475 RegSetValueExA(subKey, NULL, 0, REG_SZ,
479 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
480 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
481 RegSetValueExA(subKey, NULL, 0, REG_SZ,
486 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
487 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
489 StringFromGUID2(&attr->guid, guid, 80);
490 snprintf(ver, sizeof(ver), "%x.%x",
491 attr->wMajorVerNum, attr->wMinorVerNum);
492 RegSetValueExW(subKey, NULL, 0, REG_SZ,
493 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
494 RegSetValueExA(subKey, "Version", 0, REG_SZ,
501 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
503 ITypeInfo_Release(tinfo);
510 ITypeLib_ReleaseTLibAttr(ptlib, attr);
516 /******************************************************************************
517 * UnRegisterTypeLib [OLEAUT32.186]
518 * Removes information about a type library from the System Registry
525 HRESULT WINAPI UnRegisterTypeLib(
526 REFGUID libid, /* [in] Guid of the library */
527 WORD wVerMajor, /* [in] major version */
528 WORD wVerMinor, /* [in] minor version */
529 LCID lcid, /* [in] locale id */
532 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
533 return S_OK; /* FIXME: pretend everything is OK */
536 /****************************************************************************
537 * OaBuildVersion (TYPELIB.15)
539 * known TYPELIB.DLL versions:
541 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
542 * OLE 2.02 1993-94 02 3002
545 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
546 * OLE 2.1 NT 1993-95 ?? ???
547 * OLE 2.3.1 W95 23 700
548 * OLE2 4.0 NT4SP6 1993-98 40 4277
550 DWORD WINAPI OaBuildVersion16(void)
552 /* FIXME: I'd like to return the highest currently known version value
553 * in case the user didn't force a --winver, but I don't know how
554 * to retrieve the "versionForced" info from misc/version.c :(
555 * (this would be useful in other places, too) */
556 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
557 switch(GetVersion() & 0x8000ffff) /* mask off build number */
559 case 0x80000a03: /* WIN31 */
560 return MAKELONG(3027, 3); /* WfW 3.11 */
561 case 0x80000004: /* WIN95 */
562 return MAKELONG(700, 23); /* Win95A */
563 case 0x80000a04: /* WIN98 */
564 return MAKELONG(3024, 10); /* W98 SE */
565 case 0x00000004: /* NT4 */
566 return MAKELONG(4277, 40); /* NT4 SP6 */
568 FIXME("Version value not known yet. Please investigate it!\n");
573 /* for better debugging info leave the static out for the time being */
576 /*======================= ITypeLib implementation =======================*/
578 typedef struct tagTLBCustData
582 struct tagTLBCustData* next;
585 /* data structure for import typelibs */
586 typedef struct tagTLBImpLib
588 int offset; /* offset in the file (MSFT)
589 offset in nametable (SLTG)
590 just used to identify library while reading
592 GUID guid; /* libid */
593 BSTR name; /* name */
595 LCID lcid; /* lcid of imported typelib */
597 WORD wVersionMajor; /* major version number */
598 WORD wVersionMinor; /* minor version number */
600 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
601 NULL if not yet loaded */
602 struct tagTLBImpLib * next;
605 /* internal ITypeLib data */
606 typedef struct tagITypeLibImpl
608 ICOM_VFIELD(ITypeLib2);
610 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
612 /* strings can be stored in tlb as multibyte strings BUT they are *always*
613 * exported to the application as a UNICODE string.
619 unsigned long dwHelpContext;
620 int TypeInfoCount; /* nr of typeinfo's in librarry */
621 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
622 int ctCustData; /* number of items in cust data list */
623 TLBCustData * pCustData; /* linked list to cust data */
624 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
625 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
626 libary. Only used while read MSFT
630 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
632 /* ITypeLib methods */
633 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
634 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
636 /*======================= ITypeInfo implementation =======================*/
638 /* data for refernced types */
639 typedef struct tagTLBRefType
641 INT index; /* Type index for internal ref or for external ref
642 it the format is SLTG. -2 indicates to
645 GUID guid; /* guid of the referenced type */
646 /* if index == TLB_REF_USE_GUID */
648 HREFTYPE reference; /* The href of this ref */
649 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
650 TLB_REF_INTERNAL for internal refs
651 TLB_REF_NOT_FOUND for broken refs */
653 struct tagTLBRefType * next;
656 #define TLB_REF_USE_GUID -2
658 #define TLB_REF_INTERNAL (void*)-2
659 #define TLB_REF_NOT_FOUND (void*)-1
661 /* internal Parameter data */
662 typedef struct tagTLBParDesc
666 TLBCustData * pCustData; /* linked list to cust data */
669 /* internal Function data */
670 typedef struct tagTLBFuncDesc
672 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
673 BSTR Name; /* the name of this function */
674 TLBParDesc *pParamDesc; /* array with param names and custom data */
676 int HelpStringContext;
678 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
680 TLBCustData * pCustData; /* linked list to cust data; */
681 struct tagTLBFuncDesc * next;
684 /* internal Variable data */
685 typedef struct tagTLBVarDesc
687 VARDESC vardesc; /* lots of info on the variable and its attributes. */
688 BSTR Name; /* the name of this variable */
690 int HelpStringContext; /* FIXME: where? */
693 TLBCustData * pCustData;/* linked list to cust data; */
694 struct tagTLBVarDesc * next;
697 /* internal implemented interface data */
698 typedef struct tagTLBImplType
700 HREFTYPE hRef; /* hRef of interface */
701 int implflags; /* IMPLFLAG_*s */
703 TLBCustData * pCustData;/* linked list to custom data; */
704 struct tagTLBImplType *next;
707 /* internal TypeInfo data */
708 typedef struct tagITypeInfoImpl
710 ICOM_VFIELD(ITypeInfo2);
712 TYPEATTR TypeAttr ; /* _lots_ of type information. */
713 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
714 int index; /* index in this typelib; */
715 /* type libs seem to store the doc strings in ascii
716 * so why should we do it in unicode?
720 unsigned long dwHelpContext;
721 unsigned long dwHelpStringContext;
724 TLBFuncDesc * funclist; /* linked list with function descriptions */
727 TLBVarDesc * varlist; /* linked list with variable descriptions */
729 /* Implemented Interfaces */
730 TLBImplType * impltypelist;
732 TLBRefType * reflist;
734 TLBCustData * pCustData; /* linked list to cust data; */
735 struct tagITypeInfoImpl * next;
738 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
740 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
742 typedef struct tagTLBContext
744 unsigned int oStart; /* start of TLB in file */
745 unsigned int pos; /* current pos */
746 unsigned int length; /* total length */
747 void *mapping; /* memory mapping */
748 MSFT_SegDir * pTblDir;
749 ITypeLibImpl* pLibInfo;
753 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
758 static void dump_VarType(VARTYPE vt,char *szVarType) {
759 /* FIXME : we could have better trace here, depending on the VARTYPE
762 if (vt & VT_RESERVED)
763 szVarType += strlen(strcpy(szVarType, "reserved | "));
765 szVarType += strlen(strcpy(szVarType, "ref to "));
767 szVarType += strlen(strcpy(szVarType, "array of "));
769 szVarType += strlen(strcpy(szVarType, "vector of "));
770 switch(vt & VT_TYPEMASK) {
771 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
772 case VT_I2: sprintf(szVarType, "VT_I2"); break;
773 case VT_I4: sprintf(szVarType, "VT_I4"); break;
774 case VT_R4: sprintf(szVarType, "VT_R4"); break;
775 case VT_R8: sprintf(szVarType, "VT_R8"); break;
776 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
777 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
778 case VT_CY: sprintf(szVarType, "VT_CY"); break;
779 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
780 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
781 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
782 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
783 case VT_I1: sprintf(szVarType, "VT_I1"); break;
784 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
785 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
786 case VT_INT: sprintf(szVarType, "VT_INT"); break;
787 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
788 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
789 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
790 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
791 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
795 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
796 if (pTD->vt & VT_RESERVED)
797 szVarType += strlen(strcpy(szVarType, "reserved | "));
798 if (pTD->vt & VT_BYREF)
799 szVarType += strlen(strcpy(szVarType, "ref to "));
800 if (pTD->vt & VT_ARRAY)
801 szVarType += strlen(strcpy(szVarType, "array of "));
802 if (pTD->vt & VT_VECTOR)
803 szVarType += strlen(strcpy(szVarType, "vector of "));
804 switch(pTD->vt & VT_TYPEMASK) {
805 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
806 case VT_I2: sprintf(szVarType, "VT_I2"); break;
807 case VT_I4: sprintf(szVarType, "VT_I4"); break;
808 case VT_R4: sprintf(szVarType, "VT_R4"); break;
809 case VT_R8: sprintf(szVarType, "VT_R8"); break;
810 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
811 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
812 case VT_CY: sprintf(szVarType, "VT_CY"); break;
813 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
814 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
815 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
816 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
817 case VT_I1: sprintf(szVarType, "VT_I1"); break;
818 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
819 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
820 case VT_INT: sprintf(szVarType, "VT_INT"); break;
821 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
822 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
823 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
824 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
825 pTD->u.hreftype); break;
826 case VT_PTR: sprintf(szVarType, "ptr to ");
827 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
829 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
830 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
832 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
833 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
834 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
837 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
841 static void dump_ELEMDESC(ELEMDESC *edesc) {
843 dump_TypeDesc(&edesc->tdesc,buf);
844 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
845 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
846 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
848 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
850 MESSAGE("memid is %08lx\n",funcdesc->memid);
851 for (i=0;i<funcdesc->cParams;i++) {
852 MESSAGE("Param %d:\n",i);
853 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
855 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
856 switch (funcdesc->funckind) {
857 case FUNC_VIRTUAL: MESSAGE("virtual");break;
858 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
859 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
860 case FUNC_STATIC: MESSAGE("static");break;
861 case FUNC_DISPATCH: MESSAGE("dispatch");break;
862 default: MESSAGE("unknown");break;
864 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
865 switch (funcdesc->invkind) {
866 case INVOKE_FUNC: MESSAGE("func");break;
867 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
868 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
869 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
871 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
872 switch (funcdesc->callconv) {
873 case CC_CDECL: MESSAGE("cdecl");break;
874 case CC_PASCAL: MESSAGE("pascal");break;
875 case CC_STDCALL: MESSAGE("stdcall");break;
876 case CC_SYSCALL: MESSAGE("syscall");break;
879 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
880 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
881 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
883 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
886 if (!TRACE_ON(typelib))
888 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
889 for (i=0;i<pfd->funcdesc.cParams;i++)
890 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
893 dump_FUNCDESC(&(pfd->funcdesc));
895 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
896 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
898 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
902 dump_TLBFuncDescOne(pfd);
906 static void dump_TLBVarDesc(TLBVarDesc * pvd)
910 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
915 static void dump_TLBImpLib(TLBImpLib *import)
917 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
918 debugstr_w(import->name));
919 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
920 import->wVersionMinor, import->lcid, import->offset);
923 static void dump_TLBRefType(TLBRefType * prt)
927 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
929 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
931 TRACE_(typelib)("type no: %d\n", prt->index);
933 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
934 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
935 TRACE_(typelib)("in lib\n");
936 dump_TLBImpLib(prt->pImpTLInfo);
942 static void dump_TLBImplType(TLBImplType * impl)
946 "implementing/inheriting interface hRef = %lx implflags %x\n",
947 impl->hRef, impl->implflags);
952 static void dump_Variant(VARIANT * pvar)
957 TRACE("(%p)\n", pvar);
961 ZeroMemory(szVarType, sizeof(szVarType));
963 /* FIXME : we could have better trace here, depending on the VARTYPE
966 dump_VarType(V_VT(pvar),szVarType);
968 TRACE("VARTYPE: %s\n", szVarType);
970 if (V_VT(pvar) & VT_BYREF) {
971 ref = V_UNION(pvar, byref);
974 else ref = &V_UNION(pvar, cVal);
976 if (V_VT(pvar) & VT_ARRAY) {
980 if (V_VT(pvar) & VT_VECTOR) {
988 TRACE("%d\n", *(short*)ref);
992 TRACE("%d\n", *(INT*)ref);
996 TRACE("%3.3e\n", *(float*)ref);
1000 TRACE("%3.3e\n", *(double*)ref);
1004 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1008 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1013 TRACE("%p\n", *(LPVOID*)ref);
1017 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1021 TRACE("(?)%ld\n", *(long*)ref);
1026 static void dump_DispParms(DISPPARAMS * pdp)
1030 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1032 while (index < pdp->cArgs)
1034 dump_Variant( &pdp->rgvarg[index] );
1039 static char * typekind_desc[] =
1052 static void dump_TypeInfo(ITypeInfoImpl * pty)
1054 TRACE("%p ref=%u\n", pty, pty->ref);
1055 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1056 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1057 TRACE("fct:%u var:%u impl:%u\n",
1058 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1059 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1060 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1061 dump_TLBFuncDesc(pty->funclist);
1062 dump_TLBVarDesc(pty->varlist);
1063 dump_TLBImplType(pty->impltypelist);
1066 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1068 /* VT_LPWSTR is largest type that */
1069 /* may appear in type description*/
1070 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1071 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1072 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1073 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1074 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1075 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1079 static void TLB_abort()
1083 static void * TLB_Alloc(unsigned size)
1086 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1088 ERR("cannot allocate memory\n");
1093 static void TLB_Free(void * ptr)
1095 HeapFree(GetProcessHeap(), 0, ptr);
1099 /**********************************************************************
1101 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1104 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1106 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1107 pcx->pos, count, pcx->oStart, pcx->length, where);
1109 if (where != DO_NOT_SEEK)
1111 where += pcx->oStart;
1112 if (where > pcx->length)
1115 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1120 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1121 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1126 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1128 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1130 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1131 memset(pGuid,0, sizeof(GUID));
1134 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1137 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1140 MSFT_NameIntro niName;
1142 WCHAR* pwstring = NULL;
1143 BSTR bstrName = NULL;
1145 MSFT_Read(&niName, sizeof(niName), pcx,
1146 pcx->pTblDir->pNametab.offset+offset);
1147 niName.namelen &= 0xFF; /* FIXME: correct ? */
1148 name=TLB_Alloc((niName.namelen & 0xff) +1);
1149 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1150 name[niName.namelen & 0xff]='\0';
1152 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1155 /* no invalid characters in string */
1158 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1160 /* don't check for invalid character since this has been done previously */
1161 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1163 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1164 lengthInChars = SysStringLen(bstrName);
1165 HeapFree(GetProcessHeap(), 0, pwstring);
1168 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1172 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1179 if(offset<0) return NULL;
1180 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1181 if(length <= 0) return 0;
1182 string=TLB_Alloc(length +1);
1183 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1184 string[length]='\0';
1186 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1187 string, -1, NULL, 0);
1189 /* no invalid characters in string */
1192 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1194 /* don't check for invalid character since this has been done previously */
1195 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1197 bstr = SysAllocStringLen(pwstring, lengthInChars);
1198 lengthInChars = SysStringLen(bstr);
1199 HeapFree(GetProcessHeap(), 0, pwstring);
1202 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1206 * read a value and fill a VARIANT structure
1208 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1212 TRACE_(typelib)("\n");
1214 if(offset <0) { /* data are packed in here */
1215 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1216 V_UNION(pVar, iVal) = offset & 0xffff;
1219 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1220 pcx->pTblDir->pCustData.offset + offset );
1221 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1222 switch (V_VT(pVar)){
1223 case VT_EMPTY: /* FIXME: is this right? */
1224 case VT_NULL: /* FIXME: is this right? */
1225 case VT_I2 : /* this should not happen */
1236 case VT_VOID : /* FIXME: is this right? */
1244 case VT_DECIMAL : /* FIXME: is this right? */
1247 /* pointer types with known behaviour */
1250 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1252 FIXME("BSTR length = %d?\n", size);
1254 ptr=TLB_Alloc(size);/* allocate temp buffer */
1255 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1256 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1257 /* FIXME: do we need a AtoW conversion here? */
1258 V_UNION(pVar, bstrVal[size])=L'\0';
1259 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1264 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1271 case VT_USERDEFINED :
1277 case VT_STREAMED_OBJECT :
1278 case VT_STORED_OBJECT :
1279 case VT_BLOB_OBJECT :
1284 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1288 if(size>0) /* (big|small) endian correct? */
1289 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1293 * create a linked list with custom data
1295 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1301 TRACE_(typelib)("\n");
1305 pNew=TLB_Alloc(sizeof(TLBCustData));
1306 MSFT_Read(&entry, sizeof(entry), pcx,
1307 pcx->pTblDir->pCDGuids.offset+offset);
1308 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1309 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1310 /* add new custom data at head of the list */
1311 pNew->next=*ppCustData;
1313 offset = entry.next;
1318 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1322 pTd->vt=type & VT_TYPEMASK;
1324 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1326 if(pTd->vt == VT_USERDEFINED)
1327 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1329 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1333 MSFT_DoFuncs(TLBContext* pcx,
1338 TLBFuncDesc** pptfd)
1341 * member information is stored in a data structure at offset
1342 * indicated by the memoffset field of the typeinfo structure
1343 * There are several distinctive parts.
1344 * the first part starts with a field that holds the total length
1345 * of this (first) part excluding this field. Then follow the records,
1346 * for each member there is one record.
1348 * First entry is always the length of the record (excluding this
1350 * Rest of the record depends on the type of the member. If there is
1351 * a field indicating the member type (function variable intereface etc)
1352 * I have not found it yet. At this time we depend on the information
1353 * in the type info and the usual order how things are stored.
1355 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1358 * Third is a equal sized array with file offsets to the name entry
1361 * Forth and last (?) part is an array with offsets to the records in the
1362 * first part of this file segment.
1365 int infolen, nameoffset, reclength, nrattributes, i;
1366 int recoffset = offset + sizeof(INT);
1369 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1371 TRACE_(typelib)("\n");
1373 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1375 for ( i = 0; i < cFuncs ; i++ )
1377 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1379 /* name, eventually add to a hash table */
1380 MSFT_Read(&nameoffset,
1383 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1385 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1387 /* read the function information record */
1388 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1392 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1394 /* do the attributes */
1395 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1398 if ( nrattributes > 0 )
1400 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1402 if ( nrattributes > 1 )
1404 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1405 pFuncRec->OptAttr[1]) ;
1407 if ( nrattributes > 2 )
1409 if ( pFuncRec->FKCCIC & 0x2000 )
1411 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1415 (*pptfd)->Entry = MSFT_ReadString(pcx,
1416 pFuncRec->OptAttr[2]);
1418 if( nrattributes > 5 )
1420 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1422 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1425 pFuncRec->OptAttr[6],
1426 &(*pptfd)->pCustData);
1433 /* fill the FuncDesc Structure */
1434 MSFT_Read( & (*pptfd)->funcdesc.memid,
1436 offset + infolen + ( i + 1) * sizeof(INT));
1438 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1439 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1440 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1441 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1442 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1443 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1444 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1448 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1451 /* do the parameters/arguments */
1452 if(pFuncRec->nrargs)
1455 MSFT_ParameterInfo paraminfo;
1457 (*pptfd)->funcdesc.lprgelemdescParam =
1458 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1460 (*pptfd)->pParamDesc =
1461 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1463 MSFT_Read(¶minfo,
1466 recoffset + reclength -
1467 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1469 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1471 TYPEDESC* lpArgTypeDesc = 0;
1475 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1478 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1480 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1482 /* SEEK value = jump to offset,
1483 * from there jump to the end of record,
1484 * go back by (j-1) arguments
1486 MSFT_Read( ¶minfo ,
1487 sizeof(MSFT_ParameterInfo), pcx,
1488 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1489 * sizeof(MSFT_ParameterInfo)));
1491 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1493 while ( lpArgTypeDesc != NULL )
1495 switch ( lpArgTypeDesc->vt )
1498 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1502 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1505 case VT_USERDEFINED:
1506 MSFT_DoRefType(pcx, pTI,
1507 lpArgTypeDesc->u.hreftype);
1509 lpArgTypeDesc = NULL;
1513 lpArgTypeDesc = NULL;
1519 /* parameter is the return value! */
1520 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1522 TYPEDESC* lpArgTypeDesc;
1524 (*pptfd)->funcdesc.elemdescFunc =
1525 (*pptfd)->funcdesc.lprgelemdescParam[j];
1527 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1529 while ( lpArgTypeDesc != NULL )
1531 switch ( lpArgTypeDesc->vt )
1534 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1538 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1542 case VT_USERDEFINED:
1545 lpArgTypeDesc->u.hreftype);
1547 lpArgTypeDesc = NULL;
1551 lpArgTypeDesc = NULL;
1556 /* second time around */
1557 for(j=0;j<pFuncRec->nrargs;j++)
1560 (*pptfd)->pParamDesc[j].Name =
1561 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1564 if ( (PARAMFLAG_FHASDEFAULT &
1565 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1566 ((pFuncRec->FKCCIC) & 0x1000) )
1568 INT* pInt = (INT *)((char *)pFuncRec +
1570 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1572 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1574 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1575 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1577 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1581 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1584 pFuncRec->OptAttr[7+j],
1585 &(*pptfd)->pParamDesc[j].pCustData);
1590 /* scode is not used: archaic win16 stuff FIXME: right? */
1591 (*pptfd)->funcdesc.cScodes = 0 ;
1592 (*pptfd)->funcdesc.lprgscode = NULL ;
1594 pptfd = & ((*pptfd)->next);
1595 recoffset += reclength;
1598 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1599 int cVars, int offset, TLBVarDesc ** pptvd)
1601 int infolen, nameoffset, reclength;
1603 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1607 TRACE_(typelib)("\n");
1609 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1610 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1611 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1612 recoffset += offset+sizeof(INT);
1613 for(i=0;i<cVars;i++){
1614 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1615 /* name, eventually add to a hash table */
1616 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1617 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1618 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1619 /* read the variable information record */
1620 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1622 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1624 if(reclength >(6*sizeof(INT)) )
1625 (*pptvd)->HelpContext=pVarRec->HelpContext;
1626 if(reclength >(7*sizeof(INT)) )
1627 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1628 if(reclength >(8*sizeof(INT)) )
1629 if(reclength >(9*sizeof(INT)) )
1630 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1631 /* fill the VarDesc Structure */
1632 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1633 offset + infolen + ( i + 1) * sizeof(INT));
1634 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1635 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1636 MSFT_GetTdesc(pcx, pVarRec->DataType,
1637 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1638 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1639 if(pVarRec->VarKind == VAR_CONST ){
1640 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1641 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1642 pVarRec->OffsValue, pcx);
1644 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1645 pptvd=&((*pptvd)->next);
1646 recoffset += reclength;
1649 /* fill in data for a hreftype (offset). When the refernced type is contained
1650 * in the typelib, it's just an (file) offset in the type info base dir.
1651 * If comes from import, it's an offset+1 in the ImpInfo table
1653 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1657 TLBRefType **ppRefType = &pTI->reflist;
1659 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1662 if((*ppRefType)->reference == offset)
1664 ppRefType = &(*ppRefType)->next;
1667 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1668 sizeof(**ppRefType));
1670 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1671 /* external typelib */
1672 MSFT_ImpInfo impinfo;
1673 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1675 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1677 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1678 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1679 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1680 if(pImpLib->offset==impinfo.oImpFile) break;
1681 pImpLib=pImpLib->next;
1684 (*ppRefType)->reference=offset;
1685 (*ppRefType)->pImpTLInfo = pImpLib;
1686 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1687 (*ppRefType)->index = TLB_REF_USE_GUID;
1689 ERR("Cannot find a reference\n");
1690 (*ppRefType)->reference=-1;
1691 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1694 /* in this typelib */
1695 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1696 (*ppRefType)->reference=offset;
1697 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1701 /* process Implemented Interfaces of a com class */
1702 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1706 MSFT_RefRecord refrec;
1707 TLBImplType **ppImpl = &pTI->impltypelist;
1709 TRACE_(typelib)("\n");
1711 for(i=0;i<count;i++){
1712 if(offset<0) break; /* paranoia */
1713 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1714 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1715 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1716 (*ppImpl)->hRef = refrec.reftype;
1717 (*ppImpl)->implflags=refrec.flags;
1718 (*ppImpl)->ctCustData=
1719 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1720 offset=refrec.onext;
1721 ppImpl=&((*ppImpl)->next);
1725 * process a typeinfo record
1727 ITypeInfoImpl * MSFT_DoTypeInfo(
1730 ITypeLibImpl * pLibInfo)
1732 MSFT_TypeInfoBase tiBase;
1733 ITypeInfoImpl *ptiRet;
1735 TRACE_(typelib)("count=%u\n", count);
1737 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1738 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1739 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1740 /* this is where we are coming from */
1741 ptiRet->pTypeLib = pLibInfo;
1742 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 %ld\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);
2013 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2014 /* Windows seems to have zero here, is this correct? */
2015 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2016 pTypeLibImpl->LibAttr.lcid = PRIMARYLANGID(tlbHeader.lcid);
2018 pTypeLibImpl->LibAttr.lcid = 0;
2020 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2021 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2022 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2023 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2025 /* name, eventually add to a hash table */
2026 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2029 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2030 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2032 if( tlbHeader.varflags & HELPDLLFLAG)
2035 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2036 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2039 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2042 if(tlbHeader.CustomDataOffset >= 0)
2044 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2047 /* fill in typedescriptions */
2048 if(tlbSegDir.pTypdescTab.length > 0)
2050 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2052 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2053 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2056 /* FIXME: add several sanity checks here */
2057 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2058 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2060 /* FIXME: check safearray */
2062 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2064 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2066 else if(td[0] == VT_CARRAY)
2068 /* array descr table here */
2069 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2071 else if(td[0] == VT_USERDEFINED)
2073 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2075 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2078 /* second time around to fill the array subscript info */
2081 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2082 if(tlbSegDir.pArrayDescriptions.offset>0)
2084 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2085 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2088 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2090 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2092 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2094 for(j = 0; j<td[2]; j++)
2096 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2097 sizeof(INT), &cx, DO_NOT_SEEK);
2098 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2099 sizeof(INT), &cx, DO_NOT_SEEK);
2104 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2105 ERR("didn't find array description data\n");
2110 /* imported type libs */
2111 if(tlbSegDir.pImpFiles.offset>0)
2113 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2114 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2117 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2119 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2120 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2121 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2123 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2124 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2125 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2126 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2129 (*ppImpLib)->name = TLB_Alloc(size+1);
2130 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2131 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2132 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2134 ppImpLib = &(*ppImpLib)->next;
2139 if(tlbHeader.nrtypeinfos >= 0 )
2141 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2142 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2145 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2147 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2149 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2150 ppTI = &((*ppTI)->next);
2151 (pTypeLibImpl->TypeInfoCount)++;
2155 TRACE("(%p)\n", pTypeLibImpl);
2156 return (ITypeLib2*) pTypeLibImpl;
2160 static BSTR TLB_MultiByteToBSTR(char *ptr)
2166 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2167 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2168 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2169 ret = SysAllocString(nameW);
2170 HeapFree(GetProcessHeap(), 0, nameW);
2174 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2180 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2181 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2185 guid->Data4[0] = s >> 8;
2186 guid->Data4[1] = s & 0xff;
2189 for(i = 0; i < 6; i++) {
2190 memcpy(b, str + 24 + 2 * i, 2);
2191 guid->Data4[i + 2] = strtol(b, NULL, 16);
2196 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2203 bytelen = *(WORD*)ptr;
2204 if(bytelen == 0xffff) return 2;
2205 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2206 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2207 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2208 *pBstr = SysAllocStringLen(nameW, len);
2209 HeapFree(GetProcessHeap(), 0, nameW);
2213 static WORD SLTG_ReadStringA(char *ptr, char **str)
2218 bytelen = *(WORD*)ptr;
2219 if(bytelen == 0xffff) return 2;
2220 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2221 memcpy(*str, ptr + 2, bytelen);
2222 (*str)[bytelen] = '\0';
2226 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2228 char *ptr = pLibBlk;
2231 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2232 FIXME("libblk magic = %04x\n", w);
2237 if((w = *(WORD*)ptr) != 0xffff) {
2238 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2243 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2245 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2247 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2250 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2253 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2256 ptr += 4; /* skip res12 */
2258 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2261 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2264 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2267 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2268 ptr += sizeof(GUID);
2270 return ptr - (char*)pLibBlk;
2273 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2276 TYPEDESC *pTD = &pElem->tdesc;
2278 /* Handle [in/out] first */
2279 if((*pType & 0xc000) == 0xc000)
2280 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2281 else if(*pType & 0x8000)
2282 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2283 else if(*pType & 0x4000)
2284 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2286 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2289 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2292 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2295 if((*pType & 0xe00) == 0xe00) {
2297 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2299 pTD = pTD->u.lptdesc;
2301 switch(*pType & 0x7f) {
2304 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2306 pTD = pTD->u.lptdesc;
2309 case VT_USERDEFINED:
2310 pTD->vt = VT_USERDEFINED;
2311 pTD->u.hreftype = *(++pType) / 4;
2317 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2320 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2322 pTD->vt = VT_CARRAY;
2323 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2325 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2326 pTD->u.lpadesc->cDims = pSA->cDims;
2327 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2328 pSA->cDims * sizeof(SAFEARRAYBOUND));
2330 pTD = &pTD->u.lpadesc->tdescElem;
2336 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2340 pTD->vt = VT_SAFEARRAY;
2341 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2343 pTD = pTD->u.lptdesc;
2347 pTD->vt = *pType & 0x7f;
2357 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2362 TLBRefType **ppRefType;
2364 if(pRef->magic != SLTG_REF_MAGIC) {
2365 FIXME("Ref magic = %x\n", pRef->magic);
2368 name = ( (char*)(&pRef->names) + pRef->number);
2370 ppRefType = &pTI->reflist;
2371 for(ref = 0; ref < pRef->number >> 3; ref++) {
2373 unsigned int lib_offs, type_num;
2375 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2376 sizeof(**ppRefType));
2378 name += SLTG_ReadStringA(name, &refname);
2379 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2380 FIXME("Can't sscanf ref\n");
2381 if(lib_offs != 0xffff) {
2382 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2385 if((*import)->offset == lib_offs)
2387 import = &(*import)->next;
2390 char fname[MAX_PATH+1];
2393 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2395 (*import)->offset = lib_offs;
2396 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2398 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2399 &(*import)->wVersionMajor,
2400 &(*import)->wVersionMinor,
2401 &(*import)->lcid, fname) != 4) {
2402 FIXME("can't sscanf ref %s\n",
2403 pNameTable + lib_offs + 40);
2405 len = strlen(fname);
2406 if(fname[len-1] != '#')
2407 FIXME("fname = %s\n", fname);
2408 fname[len-1] = '\0';
2409 (*import)->name = TLB_MultiByteToBSTR(fname);
2411 (*ppRefType)->pImpTLInfo = *import;
2412 } else { /* internal ref */
2413 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2415 (*ppRefType)->reference = ref;
2416 (*ppRefType)->index = type_num;
2418 HeapFree(GetProcessHeap(), 0, refname);
2419 ppRefType = &(*ppRefType)->next;
2421 if((BYTE)*name != SLTG_REF_MAGIC)
2422 FIXME("End of ref block magic = %x\n", *name);
2423 dump_TLBRefType(pTI->reflist);
2426 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2429 SLTG_ImplInfo *info;
2430 TLBImplType **ppImplType = &pTI->impltypelist;
2431 /* I don't really get this structure, usually it's 0x16 bytes
2432 long, but iuser.tlb contains some that are 0x18 bytes long.
2433 That's ok because we can use the next ptr to jump to the next
2434 one. But how do we know the length of the last one? The WORD
2435 at offs 0x8 might be the clue. For now I'm just assuming that
2436 the last one is the regular 0x16 bytes. */
2438 info = (SLTG_ImplInfo*)pBlk;
2440 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2441 sizeof(**ppImplType));
2442 (*ppImplType)->hRef = info->ref;
2443 (*ppImplType)->implflags = info->impltypeflags;
2444 pTI->TypeAttr.cImplTypes++;
2445 ppImplType = &(*ppImplType)->next;
2447 if(info->next == 0xffff)
2450 FIXME("Interface inheriting more than one interface\n");
2451 info = (SLTG_ImplInfo*)(pBlk + info->next);
2453 info++; /* see comment at top of function */
2457 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2460 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2461 SLTG_MemberHeader *pMemHeader;
2462 char *pFirstItem, *pNextItem;
2464 if(pTIHeader->href_table != 0xffffffff) {
2465 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2470 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2472 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2474 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2475 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2478 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2482 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2485 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2486 SLTG_MemberHeader *pMemHeader;
2487 SLTG_Function *pFunc;
2488 char *pFirstItem, *pNextItem;
2489 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2492 if(pTIHeader->href_table != 0xffffffff) {
2493 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2497 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2499 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2501 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2502 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2505 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2506 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2511 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2512 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2513 FIXME("func magic = %02x\n", pFunc->magic);
2516 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2517 sizeof(**ppFuncDesc));
2518 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2520 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2521 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2522 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2523 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2524 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2525 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2527 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2528 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2530 if(pFunc->retnextopt & 0x80)
2531 pType = &pFunc->rettype;
2533 pType = (WORD*)(pFirstItem + pFunc->rettype);
2536 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2538 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2539 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2540 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2541 (*ppFuncDesc)->pParamDesc =
2542 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2543 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2545 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2547 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2548 char *paramName = pNameTable + *pArg;
2550 /* If arg type follows then paramName points to the 2nd
2551 letter of the name, else the next WORD is an offset to
2552 the arg type and paramName points to the first letter.
2553 So let's take one char off paramName and see if we're
2554 pointing at an alpha-numeric char. However if *pArg is
2555 0xffff or 0xfffe then the param has no name, the former
2556 meaning that the next WORD is the type, the latter
2557 meaning the the next WORD is an offset to the type. */
2562 else if(*pArg == 0xfffe) {
2566 else if(!isalnum(*(paramName-1)))
2571 if(HaveOffs) { /* the next word is an offset to type */
2572 pType = (WORD*)(pFirstItem + *pArg);
2573 SLTG_DoType(pType, pFirstItem,
2574 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2579 pArg = SLTG_DoType(pArg, pFirstItem,
2580 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2583 /* Are we an optional param ? */
2584 if((*ppFuncDesc)->funcdesc.cParams - param <=
2585 (*ppFuncDesc)->funcdesc.cParamsOpt)
2586 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2589 (*ppFuncDesc)->pParamDesc[param].Name =
2590 TLB_MultiByteToBSTR(paramName);
2594 ppFuncDesc = &((*ppFuncDesc)->next);
2595 if(pFunc->next == 0xffff) break;
2597 pTI->TypeAttr.cFuncs = num;
2598 dump_TLBFuncDesc(pTI->funclist);
2599 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2602 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2605 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2606 SLTG_MemberHeader *pMemHeader;
2607 SLTG_RecordItem *pItem;
2609 TLBVarDesc **ppVarDesc = &pTI->varlist;
2614 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2616 pFirstItem = (char*)(pMemHeader + 1);
2617 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2618 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2619 if(pItem->magic != SLTG_RECORD_MAGIC) {
2620 FIXME("record magic = %02x\n", pItem->magic);
2623 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2624 sizeof(**ppVarDesc));
2625 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2626 (*ppVarDesc)->vardesc.memid = pItem->memid;
2627 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2628 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2630 if(pItem->typepos == 0x02)
2631 pType = &pItem->type;
2632 else if(pItem->typepos == 0x00)
2633 pType = (WORD*)(pFirstItem + pItem->type);
2635 FIXME("typepos = %02x\n", pItem->typepos);
2639 SLTG_DoType(pType, pFirstItem,
2640 &(*ppVarDesc)->vardesc.elemdescVar);
2642 /* FIXME("helpcontext, helpstring\n"); */
2644 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2646 ppVarDesc = &((*ppVarDesc)->next);
2647 if(pItem->next == 0xffff) break;
2649 pTI->TypeAttr.cVars = num;
2650 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2653 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2656 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2657 SLTG_MemberHeader *pMemHeader;
2658 SLTG_EnumItem *pItem;
2660 TLBVarDesc **ppVarDesc = &pTI->varlist;
2663 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2665 pFirstItem = (char*)(pMemHeader + 1);
2666 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2667 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2668 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2669 FIXME("enumitem magic = %04x\n", pItem->magic);
2672 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2673 sizeof(**ppVarDesc));
2674 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2675 (*ppVarDesc)->vardesc.memid = pItem->memid;
2676 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2678 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2679 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2680 *(INT*)(pItem->value + pFirstItem);
2681 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2682 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2683 /* FIXME("helpcontext, helpstring\n"); */
2685 ppVarDesc = &((*ppVarDesc)->next);
2686 if(pItem->next == 0xffff) break;
2688 pTI->TypeAttr.cVars = num;
2689 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2692 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2693 managable copy of it into this */
2706 } SLTG_InternalOtherTypeInfo;
2708 /****************************************************************************
2709 * ITypeLib2_Constructor_SLTG
2711 * loading a SLTG typelib from an in-memory image
2713 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2715 ITypeLibImpl *pTypeLibImpl;
2716 SLTG_Header *pHeader;
2717 SLTG_BlkEntry *pBlkEntry;
2721 LPVOID pBlk, pFirstBlk;
2722 SLTG_LibBlk *pLibBlk;
2723 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2724 char *pAfterOTIBlks = NULL;
2725 char *pNameTable, *ptr;
2728 ITypeInfoImpl **ppTypeInfoImpl;
2730 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2732 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2733 if (!pTypeLibImpl) return NULL;
2735 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2736 pTypeLibImpl->ref = 1;
2741 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2742 pHeader->nrOfFileBlks );
2743 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2744 FIXME("Header type magic 0x%08lx not supported.\n",
2745 pHeader->SLTG_magic);
2749 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2750 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2752 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2753 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2755 /* Next we have a magic block */
2756 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2758 /* Let's see if we're still in sync */
2759 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2760 sizeof(SLTG_COMPOBJ_MAGIC))) {
2761 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2764 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2765 sizeof(SLTG_DIR_MAGIC))) {
2766 FIXME("dir magic = %s\n", pMagic->dir_magic);
2770 pIndex = (SLTG_Index*)(pMagic+1);
2772 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2774 pFirstBlk = (LPVOID)(pPad9 + 1);
2776 /* We'll set up a ptr to the main library block, which is the last one. */
2778 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2779 pBlkEntry[order].next != 0;
2780 order = pBlkEntry[order].next - 1, i++) {
2781 pBlk += pBlkEntry[order].len;
2785 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2787 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2792 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2794 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2795 sizeof(*pOtherTypeInfoBlks) *
2796 pTypeLibImpl->TypeInfoCount);
2799 ptr = (char*)pLibBlk + len;
2801 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2805 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2807 w = *(WORD*)(ptr + 2);
2810 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2812 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2813 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2815 w = *(WORD*)(ptr + 4 + len);
2817 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2819 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2821 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2822 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2824 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2825 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2826 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2828 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2830 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2833 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2834 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2835 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2836 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2837 len += sizeof(SLTG_OtherTypeInfo);
2841 pAfterOTIBlks = ptr;
2843 /* Skip this WORD and get the next DWORD */
2844 len = *(DWORD*)(pAfterOTIBlks + 2);
2846 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2847 magic dust and we should be pointing at the beginning of the name
2850 pNameTable = (char*)pLibBlk + len + 0x216;
2854 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2856 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2859 /* Hopefully we now have enough ptrs set up to actually read in
2860 some TypeInfos. It's not clear which order to do them in, so
2861 I'll just follow the links along the BlkEntry chain and read
2862 them in in the order in which they're in the file */
2864 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2866 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2867 pBlkEntry[order].next != 0;
2868 order = pBlkEntry[order].next - 1, i++) {
2870 SLTG_TypeInfoHeader *pTIHeader;
2871 SLTG_TypeInfoTail *pTITail;
2873 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2874 pOtherTypeInfoBlks[i].index_name)) {
2875 FIXME("Index strings don't match\n");
2880 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2881 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2884 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2885 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2886 (*ppTypeInfoImpl)->index = i;
2887 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2888 pOtherTypeInfoBlks[i].name_offs +
2890 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2891 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2893 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2894 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2895 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2896 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2897 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2899 if((pTIHeader->typeflags1 & 7) != 2)
2900 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2901 if(pTIHeader->typeflags3 != 2)
2902 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2904 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2905 debugstr_w((*ppTypeInfoImpl)->Name),
2906 typekind_desc[pTIHeader->typekind],
2907 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2908 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2910 switch(pTIHeader->typekind) {
2912 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2916 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2919 case TKIND_INTERFACE:
2920 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2924 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2928 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2934 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2935 but we've already set those */
2936 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2937 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2938 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2940 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2941 pBlk += pBlkEntry[order].len;
2944 if(i != pTypeLibImpl->TypeInfoCount) {
2945 FIXME("Somehow processed %d TypeInfos\n", i);
2949 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2950 return (ITypeLib2*)pTypeLibImpl;
2953 /* ITypeLib::QueryInterface
2955 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2960 ICOM_THIS( ITypeLibImpl, iface);
2962 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2965 if(IsEqualIID(riid, &IID_IUnknown) ||
2966 IsEqualIID(riid,&IID_ITypeLib)||
2967 IsEqualIID(riid,&IID_ITypeLib2))
2974 ITypeLib2_AddRef(iface);
2975 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2978 TRACE("-- Interface: E_NOINTERFACE\n");
2979 return E_NOINTERFACE;
2984 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
2986 ICOM_THIS( ITypeLibImpl, iface);
2988 TRACE("(%p)->ref is %u\n",This, This->ref);
2990 return ++(This->ref);
2993 /* ITypeLib::Release
2995 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
2997 ICOM_THIS( ITypeLibImpl, iface);
3001 TRACE("(%p)->(%u)\n",This, This->ref);
3005 /* FIXME destroy child objects */
3007 TRACE(" destroying ITypeLib(%p)\n",This);
3011 SysFreeString(This->Name);
3015 if (This->DocString)
3017 SysFreeString(This->DocString);
3018 This->DocString = NULL;
3023 SysFreeString(This->HelpFile);
3024 This->HelpFile = NULL;
3027 if (This->HelpStringDll)
3029 SysFreeString(This->HelpStringDll);
3030 This->HelpStringDll = NULL;
3033 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3034 HeapFree(GetProcessHeap(),0,This);
3041 /* ITypeLib::GetTypeInfoCount
3043 * Returns the number of type descriptions in the type library
3045 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3047 ICOM_THIS( ITypeLibImpl, iface);
3048 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3049 return This->TypeInfoCount;
3052 /* ITypeLib::GetTypeInfo
3054 * retrieves the specified type description in the library.
3056 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3059 ITypeInfo **ppTInfo)
3063 ICOM_THIS( ITypeLibImpl, iface);
3064 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3066 TRACE("(%p)->(index=%d) \n", This, index);
3068 if (!ppTInfo) return E_INVALIDARG;
3070 /* search element n in list */
3071 for(i=0; i < index; i++)
3073 pTypeInfo = pTypeInfo->next;
3076 TRACE("-- element not found\n");
3077 return TYPE_E_ELEMENTNOTFOUND;
3081 *ppTInfo = (ITypeInfo *) pTypeInfo;
3083 ITypeInfo_AddRef(*ppTInfo);
3084 TRACE("-- found (%p)\n",*ppTInfo);
3089 /* ITypeLibs::GetTypeInfoType
3091 * Retrieves the type of a type description.
3093 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3098 ICOM_THIS( ITypeLibImpl, iface);
3100 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3102 TRACE("(%p) index %d \n",This, index);
3104 if(!pTKind) return E_INVALIDARG;
3106 /* search element n in list */
3107 for(i=0; i < index; i++)
3111 TRACE("-- element not found\n");
3112 return TYPE_E_ELEMENTNOTFOUND;
3114 pTInfo = pTInfo->next;
3117 *pTKind = pTInfo->TypeAttr.typekind;
3118 TRACE("-- found Type (%d)\n", *pTKind);
3122 /* ITypeLib::GetTypeInfoOfGuid
3124 * Retrieves the type description that corresponds to the specified GUID.
3127 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3130 ITypeInfo **ppTInfo)
3132 ICOM_THIS( ITypeLibImpl, iface);
3133 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3135 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3137 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3139 /* search linked list for guid */
3140 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3142 pTypeInfo = pTypeInfo->next;
3146 /* end of list reached */
3147 TRACE("-- element not found\n");
3148 return TYPE_E_ELEMENTNOTFOUND;
3152 TRACE("-- found (%p, %s)\n",
3154 debugstr_w(pTypeInfo->Name));
3156 *ppTInfo = (ITypeInfo*)pTypeInfo;
3157 ITypeInfo_AddRef(*ppTInfo);
3161 /* ITypeLib::GetLibAttr
3163 * Retrieves the structure that contains the library's attributes.
3166 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3168 LPTLIBATTR *ppTLibAttr)
3170 ICOM_THIS( ITypeLibImpl, iface);
3171 TRACE("(%p)\n",This);
3172 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3173 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3177 /* ITypeLib::GetTypeComp
3179 * Enables a client compiler to bind to a library's types, variables,
3180 * constants, and global functions.
3183 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3185 ITypeComp **ppTComp)
3187 ICOM_THIS( ITypeLibImpl, iface);
3188 FIXME("(%p): stub!\n",This);
3192 /* ITypeLib::GetDocumentation
3194 * Retrieves the library's documentation string, the complete Help file name
3195 * and path, and the context identifier for the library Help topic in the Help
3198 * On a successful return all non-null BSTR pointers will have been set,
3201 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3205 BSTR *pBstrDocString,
3206 DWORD *pdwHelpContext,
3207 BSTR *pBstrHelpFile)
3209 ICOM_THIS( ITypeLibImpl, iface);
3211 HRESULT result = E_INVALIDARG;
3216 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3218 pBstrName, pBstrDocString,
3219 pdwHelpContext, pBstrHelpFile);
3223 /* documentation for the typelib */
3227 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3233 if (This->DocString)
3234 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3235 else if (This->Name)
3236 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3238 *pBstrDocString = NULL;
3242 *pdwHelpContext = This->dwHelpContext;
3247 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3249 *pBstrHelpFile = NULL;
3256 /* for a typeinfo */
3257 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3259 if(SUCCEEDED(result))
3261 result = ITypeInfo_GetDocumentation(pTInfo,
3265 pdwHelpContext, pBstrHelpFile);
3267 ITypeInfo_Release(pTInfo);
3272 if (pBstrDocString) SysFreeString (*pBstrDocString);
3274 if (pBstrName) SysFreeString (*pBstrName);
3276 return STG_E_INSUFFICIENTMEMORY;
3281 * Indicates whether a passed-in string contains the name of a type or member
3282 * described in the library.
3285 static HRESULT WINAPI ITypeLib2_fnIsName(
3291 ICOM_THIS( ITypeLibImpl, iface);
3292 ITypeInfoImpl *pTInfo;
3293 TLBFuncDesc *pFInfo;
3296 UINT nNameBufLen = SysStringLen(szNameBuf);
3298 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3302 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3303 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3304 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3305 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3306 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3307 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3308 goto ITypeLib2_fnIsName_exit;
3310 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3311 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3316 ITypeLib2_fnIsName_exit:
3317 TRACE("(%p)slow! search for %s: %s found!\n", This,
3318 debugstr_w(szNameBuf), *pfName?"NOT":"");
3323 /* ITypeLib::FindName
3325 * Finds occurrences of a type description in a type library. This may be used
3326 * to quickly verify that a name exists in a type library.
3329 static HRESULT WINAPI ITypeLib2_fnFindName(
3333 ITypeInfo **ppTInfo,
3337 ICOM_THIS( ITypeLibImpl, iface);
3338 ITypeInfoImpl *pTInfo;
3339 TLBFuncDesc *pFInfo;
3343 UINT nNameBufLen = SysStringLen(szNameBuf);
3345 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3346 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3347 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3348 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3349 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3350 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3351 goto ITypeLib2_fnFindName_exit;
3353 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3354 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3356 ITypeLib2_fnFindName_exit:
3357 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3358 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3361 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3362 This, *pcFound, debugstr_w(szNameBuf), j);
3369 /* ITypeLib::ReleaseTLibAttr
3371 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3374 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3376 TLIBATTR *pTLibAttr)
3378 ICOM_THIS( ITypeLibImpl, iface);
3379 TRACE("freeing (%p)\n",This);
3380 HeapFree(GetProcessHeap(),0,pTLibAttr);
3384 /* ITypeLib2::GetCustData
3386 * gets the custom data
3388 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3393 ICOM_THIS( ITypeLibImpl, iface);
3394 TLBCustData *pCData;
3396 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3398 if( IsEqualIID(guid, &pCData->guid)) break;
3401 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3405 VariantInit( pVarVal);
3406 VariantCopy( pVarVal, &pCData->data);
3409 return E_INVALIDARG; /* FIXME: correct? */
3412 /* ITypeLib2::GetLibStatistics
3414 * Returns statistics about a type library that are required for efficient
3415 * sizing of hash tables.
3418 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3420 ULONG *pcUniqueNames,
3421 ULONG *pcchUniqueNames)
3423 ICOM_THIS( ITypeLibImpl, iface);
3425 FIXME("(%p): stub!\n", This);
3427 if(pcUniqueNames) *pcUniqueNames=1;
3428 if(pcchUniqueNames) *pcchUniqueNames=1;
3432 /* ITypeLib2::GetDocumentation2
3434 * Retrieves the library's documentation string, the complete Help file name
3435 * and path, the localization context to use, and the context ID for the
3436 * library Help topic in the Help file.
3439 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3443 BSTR *pbstrHelpString,
3444 DWORD *pdwHelpStringContext,
3445 BSTR *pbstrHelpStringDll)
3447 ICOM_THIS( ITypeLibImpl, iface);
3451 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3453 /* the help string should be obtained from the helpstringdll,
3454 * using the _DLLGetDocumentation function, based on the supplied
3455 * lcid. Nice to do sometime...
3459 /* documentation for the typelib */
3461 *pbstrHelpString=SysAllocString(This->DocString);
3462 if(pdwHelpStringContext)
3463 *pdwHelpStringContext=This->dwHelpContext;
3464 if(pbstrHelpStringDll)
3465 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3471 /* for a typeinfo */
3472 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3474 if(SUCCEEDED(result))
3476 ITypeInfo2 * pTInfo2;
3477 result = ITypeInfo_QueryInterface(pTInfo,
3479 (LPVOID*) &pTInfo2);
3481 if(SUCCEEDED(result))
3483 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3487 pdwHelpStringContext,
3488 pbstrHelpStringDll);
3490 ITypeInfo2_Release(pTInfo2);
3493 ITypeInfo_Release(pTInfo);
3499 /* ITypeLib2::GetAllCustData
3501 * Gets all custom data items for the library.
3504 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3506 CUSTDATA *pCustData)
3508 ICOM_THIS( ITypeLibImpl, iface);
3509 TLBCustData *pCData;
3511 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3512 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3513 if(pCustData->prgCustData ){
3514 pCustData->cCustData=This->ctCustData;
3515 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3516 pCustData->prgCustData[i].guid=pCData->guid;
3517 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3520 ERR(" OUT OF MEMORY! \n");
3521 return E_OUTOFMEMORY;
3526 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3527 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3528 ITypeLib2_fnQueryInterface,
3530 ITypeLib2_fnRelease,
3531 ITypeLib2_fnGetTypeInfoCount,
3532 ITypeLib2_fnGetTypeInfo,
3533 ITypeLib2_fnGetTypeInfoType,
3534 ITypeLib2_fnGetTypeInfoOfGuid,
3535 ITypeLib2_fnGetLibAttr,
3536 ITypeLib2_fnGetTypeComp,
3537 ITypeLib2_fnGetDocumentation,
3539 ITypeLib2_fnFindName,
3540 ITypeLib2_fnReleaseTLibAttr,
3542 ITypeLib2_fnGetCustData,
3543 ITypeLib2_fnGetLibStatistics,
3544 ITypeLib2_fnGetDocumentation2,
3545 ITypeLib2_fnGetAllCustData
3548 /*================== ITypeInfo(2) Methods ===================================*/
3549 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3551 ITypeInfoImpl * pTypeInfoImpl;
3553 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3556 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3557 pTypeInfoImpl->ref=1;
3559 TRACE("(%p)\n", pTypeInfoImpl);
3560 return (ITypeInfo2*) pTypeInfoImpl;
3563 /* ITypeInfo::QueryInterface
3565 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3570 ICOM_THIS( ITypeLibImpl, iface);
3572 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3575 if(IsEqualIID(riid, &IID_IUnknown) ||
3576 IsEqualIID(riid,&IID_ITypeInfo)||
3577 IsEqualIID(riid,&IID_ITypeInfo2))
3581 ITypeInfo_AddRef(iface);
3582 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3585 TRACE("-- Interface: E_NOINTERFACE\n");
3586 return E_NOINTERFACE;
3589 /* ITypeInfo::AddRef
3591 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3593 ICOM_THIS( ITypeInfoImpl, iface);
3597 TRACE("(%p)->ref is %u\n",This, This->ref);
3601 /* ITypeInfo::Release
3603 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3605 ICOM_THIS( ITypeInfoImpl, iface);
3609 TRACE("(%p)->(%u)\n",This, This->ref);
3613 FIXME("destroy child objects\n");
3615 TRACE("destroying ITypeInfo(%p)\n",This);
3618 SysFreeString(This->Name);
3622 if (This->DocString)
3624 SysFreeString(This->DocString);
3625 This->DocString = 0;
3630 ITypeInfo_Release((ITypeInfo*)This->next);
3633 HeapFree(GetProcessHeap(),0,This);
3639 /* ITypeInfo::GetTypeAttr
3641 * Retrieves a TYPEATTR structure that contains the attributes of the type
3645 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3646 LPTYPEATTR *ppTypeAttr)
3648 ICOM_THIS( ITypeInfoImpl, iface);
3649 TRACE("(%p)\n",This);
3650 /* FIXME: must do a copy here */
3651 *ppTypeAttr=&This->TypeAttr;
3655 /* ITypeInfo::GetTypeComp
3657 * Retrieves the ITypeComp interface for the type description, which enables a
3658 * client compiler to bind to the type description's members.
3661 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3662 ITypeComp * *ppTComp)
3664 ICOM_THIS( ITypeInfoImpl, iface);
3665 FIXME("(%p) stub!\n", This);
3669 /* ITypeInfo::GetFuncDesc
3671 * Retrieves the FUNCDESC structure that contains information about a
3672 * specified function.
3675 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3676 LPFUNCDESC *ppFuncDesc)
3678 ICOM_THIS( ITypeInfoImpl, iface);
3680 TLBFuncDesc * pFDesc;
3681 TRACE("(%p) index %d\n", This, index);
3682 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3685 /* FIXME: must do a copy here */
3686 *ppFuncDesc=&pFDesc->funcdesc;
3689 return E_INVALIDARG;
3692 /* ITypeInfo::GetVarDesc
3694 * Retrieves a VARDESC structure that describes the specified variable.
3697 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3698 LPVARDESC *ppVarDesc)
3700 ICOM_THIS( ITypeInfoImpl, iface);
3702 TLBVarDesc * pVDesc;
3703 TRACE("(%p) index %d\n", This, index);
3704 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3707 /* FIXME: must do a copy here */
3708 *ppVarDesc=&pVDesc->vardesc;
3711 return E_INVALIDARG;
3714 /* ITypeInfo_GetNames
3716 * Retrieves the variable with the specified member ID (or the name of the
3717 * property or method and its parameters) that correspond to the specified
3720 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3721 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3723 ICOM_THIS( ITypeInfoImpl, iface);
3724 TLBFuncDesc * pFDesc;
3725 TLBVarDesc * pVDesc;
3727 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3728 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3731 /* function found, now return function and parameter names */
3732 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3735 *rgBstrNames=SysAllocString(pFDesc->Name);
3737 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3743 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3746 *rgBstrNames=SysAllocString(pVDesc->Name);
3751 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3753 /* recursive search */
3756 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3758 if(SUCCEEDED(result))
3760 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3761 ITypeInfo_Release(pTInfo);
3764 WARN("Could not search inherited interface!\n");
3768 WARN("no names found\n");
3771 return TYPE_E_ELEMENTNOTFOUND;
3778 /* ITypeInfo::GetRefTypeOfImplType
3780 * If a type description describes a COM class, it retrieves the type
3781 * description of the implemented interface types. For an interface,
3782 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3786 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3791 ICOM_THIS( ITypeInfoImpl, iface);
3793 TLBImplType *pImpl = This->impltypelist;
3795 TRACE("(%p) index %d\n", This, index);
3796 dump_TypeInfo(This);
3800 /* only valid on dual interfaces;
3801 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3803 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3805 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3806 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3812 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3813 *pRefType = pImpl->hRef;
3818 /* get element n from linked list */
3819 for(i=0; pImpl && i<index; i++)
3821 pImpl = pImpl->next;
3824 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3826 *pRefType = pImpl->hRef;
3828 TRACE("-- 0x%08lx\n", pImpl->hRef );
3835 /* ITypeInfo::GetImplTypeFlags
3837 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3838 * or base interface in a type description.
3840 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3841 UINT index, INT *pImplTypeFlags)
3843 ICOM_THIS( ITypeInfoImpl, iface);
3847 TRACE("(%p) index %d\n", This, index);
3848 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3849 i++, pImpl=pImpl->next)
3851 if(i==index && pImpl){
3852 *pImplTypeFlags=pImpl->implflags;
3856 return TYPE_E_ELEMENTNOTFOUND;
3860 * Maps between member names and member IDs, and parameter names and
3863 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3864 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3866 ICOM_THIS( ITypeInfoImpl, iface);
3867 TLBFuncDesc * pFDesc;
3868 TLBVarDesc * pVDesc;
3871 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3873 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3875 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3876 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3877 for(i=1; i < cNames; i++){
3878 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3879 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3881 if( j<pFDesc->funcdesc.cParams)
3884 ret=DISP_E_UNKNOWNNAME;
3889 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3890 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3891 if(cNames) *pMemId=pVDesc->vardesc.memid;
3895 /* not found, see if this is and interface with an inheritance */
3896 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3897 This->TypeAttr.cImplTypes ){
3898 /* recursive search */
3900 ret=ITypeInfo_GetRefTypeInfo(iface,
3901 This->impltypelist->hRef, &pTInfo);
3903 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3904 ITypeInfo_Release(pTInfo);
3907 WARN("Could not search inherited interface!\n");
3909 WARN("no names found\n");
3910 return DISP_E_UNKNOWNNAME;
3913 /* ITypeInfo::Invoke
3915 * Invokes a method, or accesses a property of an object, that implements the
3916 * interface described by the type description.
3918 static DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3921 if (TRACE_ON(ole)) {
3923 MESSAGE("Calling %p(",func);
3924 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3933 DWORD (WINAPI *xfunc)() = func;
3938 DWORD (WINAPI *xfunc)(DWORD) = func;
3939 res = xfunc(args[0]);
3943 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3944 res = xfunc(args[0],args[1]);
3948 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3949 res = xfunc(args[0],args[1],args[2]);
3953 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
3959 FIXME("unsupported calling convention %d\n",callconv);
3963 TRACE("returns %08lx\n",res);
3967 static HRESULT WINAPI ITypeInfo_fnInvoke(
3972 DISPPARAMS *pDispParams,
3973 VARIANT *pVarResult,
3974 EXCEPINFO *pExcepInfo,
3977 ICOM_THIS( ITypeInfoImpl, iface);
3978 TLBFuncDesc * pFDesc;
3979 TLBVarDesc * pVDesc;
3982 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
3983 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
3985 dump_DispParms(pDispParams);
3987 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3988 if (pFDesc->funcdesc.memid == memid) {
3989 if (pFDesc->funcdesc.invkind & dwFlags)
3993 dump_TLBFuncDescOne(pFDesc);
3994 switch (pFDesc->funcdesc.funckind) {
3995 case FUNC_PUREVIRTUAL:
3996 case FUNC_VIRTUAL: {
3998 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
3999 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
4000 args[0] = (DWORD)pIUnk;
4002 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4003 if (i<pDispParams->cArgs) {
4004 TRACE("set %d to disparg type %d vs %d\n",i,
4005 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
4006 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
4008 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
4010 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4011 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4012 /*FIXME: give pointers for the rest, so propertyget works*/
4013 args[i+1] = (DWORD)&args2[i];
4015 /* If pointer to variant, pass reference to variant
4016 * in result variant array.
4018 if ((tdesc->vt == VT_PTR) &&
4019 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4022 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
4025 if (pFDesc->funcdesc.cParamsOpt)
4026 FIXME("Does not support optional parameters (%d)\n",
4027 pFDesc->funcdesc.cParamsOpt
4030 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4031 pFDesc->funcdesc.callconv,
4032 pFDesc->funcdesc.cParams+1,
4035 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4036 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4037 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4038 /* If we are a pointer to a variant, we are done already */
4039 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4042 VariantInit(&pVarResult[i]);
4043 V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
4045 if (tdesc->vt == VT_PTR)
4046 tdesc = tdesc->u.lptdesc;
4047 V_VT(pVarResult+i) = tdesc->vt;
4049 /* HACK: VB5 likes this.
4050 * I do not know why. There is 1 example in MSDN which uses
4051 * this which appears broken (mixes int vals and
4054 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4055 V_VT(pVarResult+i) = VT_DISPATCH;
4056 TRACE("storing into variant: [%d]\n", i);
4057 dump_Variant(pVarResult+i);
4060 HeapFree(GetProcessHeap(),0,args2);
4061 HeapFree(GetProcessHeap(),0,args);
4064 case FUNC_DISPATCH: {
4068 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4070 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4073 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4074 hr = IDispatch_Invoke(
4075 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4076 pVarResult,pExcepInfo,pArgErr
4079 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4080 IDispatch_Release(disp);
4084 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4088 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4089 if (pVDesc->vardesc.memid == memid) {
4090 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4091 dump_TLBVarDesc(pVDesc);
4096 /* not found, look for it in inherited interfaces */
4097 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4098 /* recursive search */
4101 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4103 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4104 ITypeInfo_Release(pTInfo);
4107 WARN("Could not search inherited interface!\n");
4109 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4110 return DISP_E_MEMBERNOTFOUND;
4113 /* ITypeInfo::GetDocumentation
4115 * Retrieves the documentation string, the complete Help file name and path,
4116 * and the context ID for the Help topic for a specified type description.
4118 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4119 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4120 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4122 ICOM_THIS( ITypeInfoImpl, iface);
4123 TLBFuncDesc * pFDesc;
4124 TLBVarDesc * pVDesc;
4125 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4126 " HelpContext(%p) HelpFile(%p)\n",
4127 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4128 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4130 *pBstrName=SysAllocString(This->Name);
4132 *pBstrDocString=SysAllocString(This->DocString);
4134 *pdwHelpContext=This->dwHelpContext;
4136 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4138 }else {/* for a member */
4139 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4140 if(pFDesc->funcdesc.memid==memid){
4142 *pBstrName = SysAllocString(pFDesc->Name);
4144 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4146 *pdwHelpContext=pFDesc->helpcontext;
4149 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4150 if(pVDesc->vardesc.memid==memid){
4151 FIXME("Not implemented\n");
4155 return TYPE_E_ELEMENTNOTFOUND;
4158 /* ITypeInfo::GetDllEntry
4160 * Retrieves a description or specification of an entry point for a function
4163 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4164 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4167 ICOM_THIS( ITypeInfoImpl, iface);
4168 FIXME("(%p) stub!\n", This);
4172 /* ITypeInfo::GetRefTypeInfo
4174 * If a type description references other type descriptions, it retrieves
4175 * the referenced type descriptions.
4177 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4180 ITypeInfo **ppTInfo)
4182 ICOM_THIS( ITypeInfoImpl, iface);
4183 HRESULT result = E_FAIL;
4186 if (hRefType == -1 &&
4187 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4188 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4190 /* when we meet a DUAL dispinterface, we must create the interface
4193 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4196 /* the interface version contains the same information as the dispinterface
4197 * copy the contents of the structs.
4199 *pTypeInfoImpl = *This;
4200 pTypeInfoImpl->ref = 1;
4202 /* change the type to interface */
4203 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4205 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4207 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4212 TLBRefType *pRefType;
4213 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4214 if(pRefType->reference == hRefType)
4218 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4219 if(pRefType && hRefType != -1) {
4222 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4224 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4226 if(pRefType->pImpTLInfo->pImpTypeLib) {
4227 TRACE("typeinfo in imported typelib that is already loaded\n");
4228 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4229 ITypeLib2_AddRef((ITypeLib*) pTLib);
4232 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4233 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4234 pRefType->pImpTLInfo->wVersionMajor,
4235 pRefType->pImpTLInfo->wVersionMinor,
4236 pRefType->pImpTLInfo->lcid,
4239 if(!SUCCEEDED(result)) {
4240 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4241 result=LoadTypeLib(libnam, &pTLib);
4242 SysFreeString(libnam);
4244 if(SUCCEEDED(result)) {
4245 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4246 ITypeLib2_AddRef(pTLib);
4250 if(SUCCEEDED(result)) {
4251 if(pRefType->index == TLB_REF_USE_GUID)
4252 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4256 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4262 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4263 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4267 /* ITypeInfo::AddressOfMember
4269 * Retrieves the addresses of static functions or variables, such as those
4272 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4273 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4275 ICOM_THIS( ITypeInfoImpl, iface);
4276 FIXME("(%p) stub!\n", This);
4280 /* ITypeInfo::CreateInstance
4282 * Creates a new instance of a type that describes a component object class
4285 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4286 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4288 ICOM_THIS( ITypeInfoImpl, iface);
4289 FIXME("(%p) stub!\n", This);
4293 /* ITypeInfo::GetMops
4295 * Retrieves marshaling information.
4297 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4300 ICOM_THIS( ITypeInfoImpl, iface);
4301 FIXME("(%p) stub!\n", This);
4305 /* ITypeInfo::GetContainingTypeLib
4307 * Retrieves the containing type library and the index of the type description
4308 * within that type library.
4310 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4311 ITypeLib * *ppTLib, UINT *pIndex)
4313 ICOM_THIS( ITypeInfoImpl, iface);
4315 return E_INVALIDARG;
4316 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4317 *pIndex=This->index;
4318 ITypeLib2_AddRef(*ppTLib);
4319 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4323 /* ITypeInfo::ReleaseTypeAttr
4325 * Releases a TYPEATTR previously returned by GetTypeAttr.
4328 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4329 TYPEATTR* pTypeAttr)
4331 ICOM_THIS( ITypeInfoImpl, iface);
4332 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4336 /* ITypeInfo::ReleaseFuncDesc
4338 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4340 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4342 FUNCDESC *pFuncDesc)
4344 ICOM_THIS( ITypeInfoImpl, iface);
4345 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4349 /* ITypeInfo::ReleaseVarDesc
4351 * Releases a VARDESC previously returned by GetVarDesc.
4353 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4356 ICOM_THIS( ITypeInfoImpl, iface);
4357 TRACE("(%p)->(%p)\n", This, pVarDesc);
4361 /* ITypeInfo2::GetTypeKind
4363 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4366 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4367 TYPEKIND *pTypeKind)
4369 ICOM_THIS( ITypeInfoImpl, iface);
4370 *pTypeKind=This->TypeAttr.typekind;
4371 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4375 /* ITypeInfo2::GetTypeFlags
4377 * Returns the type flags without any allocations. This returns a DWORD type
4378 * flag, which expands the type flags without growing the TYPEATTR (type
4382 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4385 ICOM_THIS( ITypeInfoImpl, iface);
4386 *pTypeFlags=This->TypeAttr.wTypeFlags;
4387 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4391 /* ITypeInfo2::GetFuncIndexOfMemId
4392 * Binds to a specific member based on a known DISPID, where the member name
4393 * is not known (for example, when binding to a default member).
4396 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4397 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4399 ICOM_THIS( ITypeInfoImpl, iface);
4400 TLBFuncDesc *pFuncInfo;
4403 /* FIXME: should check for invKind??? */
4404 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4405 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4411 result=E_INVALIDARG;
4413 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4414 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4418 /* TypeInfo2::GetVarIndexOfMemId
4420 * Binds to a specific member based on a known DISPID, where the member name
4421 * is not known (for example, when binding to a default member).
4424 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4425 MEMBERID memid, UINT *pVarIndex)
4427 ICOM_THIS( ITypeInfoImpl, iface);
4428 TLBVarDesc *pVarInfo;
4431 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4432 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4439 result=E_INVALIDARG;
4441 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4442 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4446 /* ITypeInfo2::GetCustData
4448 * Gets the custom data
4450 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4455 ICOM_THIS( ITypeInfoImpl, iface);
4456 TLBCustData *pCData;
4458 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4459 if( IsEqualIID(guid, &pCData->guid)) break;
4461 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4465 VariantInit( pVarVal);
4466 VariantCopy( pVarVal, &pCData->data);
4469 return E_INVALIDARG; /* FIXME: correct? */
4472 /* ITypeInfo2::GetFuncCustData
4474 * Gets the custom data
4476 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4482 ICOM_THIS( ITypeInfoImpl, iface);
4483 TLBCustData *pCData=NULL;
4484 TLBFuncDesc * pFDesc;
4486 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4487 pFDesc=pFDesc->next);
4490 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4491 if( IsEqualIID(guid, &pCData->guid)) break;
4493 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4496 VariantInit( pVarVal);
4497 VariantCopy( pVarVal, &pCData->data);
4500 return E_INVALIDARG; /* FIXME: correct? */
4503 /* ITypeInfo2::GetParamCustData
4505 * Gets the custom data
4507 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4514 ICOM_THIS( ITypeInfoImpl, iface);
4515 TLBCustData *pCData=NULL;
4516 TLBFuncDesc * pFDesc;
4519 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4521 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4522 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4523 pCData = pCData->next)
4524 if( IsEqualIID(guid, &pCData->guid)) break;
4526 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4530 VariantInit( pVarVal);
4531 VariantCopy( pVarVal, &pCData->data);
4534 return E_INVALIDARG; /* FIXME: correct? */
4537 /* ITypeInfo2::GetVarCustData
4539 * Gets the custom data
4541 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4547 ICOM_THIS( ITypeInfoImpl, iface);
4548 TLBCustData *pCData=NULL;
4549 TLBVarDesc * pVDesc;
4552 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4556 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4558 if( IsEqualIID(guid, &pCData->guid)) break;
4562 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4566 VariantInit( pVarVal);
4567 VariantCopy( pVarVal, &pCData->data);
4570 return E_INVALIDARG; /* FIXME: correct? */
4573 /* ITypeInfo2::GetImplCustData
4575 * Gets the custom data
4577 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4583 ICOM_THIS( ITypeInfoImpl, iface);
4584 TLBCustData *pCData=NULL;
4585 TLBImplType * pRDesc;
4588 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4592 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4594 if( IsEqualIID(guid, &pCData->guid)) break;
4598 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4602 VariantInit( pVarVal);
4603 VariantCopy( pVarVal, &pCData->data);
4606 return E_INVALIDARG; /* FIXME: correct? */
4609 /* ITypeInfo2::GetDocumentation2
4611 * Retrieves the documentation string, the complete Help file name and path,
4612 * the localization context to use, and the context ID for the library Help
4613 * topic in the Help file.
4616 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4620 BSTR *pbstrHelpString,
4621 DWORD *pdwHelpStringContext,
4622 BSTR *pbstrHelpStringDll)
4624 ICOM_THIS( ITypeInfoImpl, iface);
4625 TLBFuncDesc * pFDesc;
4626 TLBVarDesc * pVDesc;
4627 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4628 "HelpStringContext(%p) HelpStringDll(%p)\n",
4629 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4630 pbstrHelpStringDll );
4631 /* the help string should be obtained from the helpstringdll,
4632 * using the _DLLGetDocumentation function, based on the supplied
4633 * lcid. Nice to do sometime...
4635 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4637 *pbstrHelpString=SysAllocString(This->Name);
4638 if(pdwHelpStringContext)
4639 *pdwHelpStringContext=This->dwHelpStringContext;
4640 if(pbstrHelpStringDll)
4641 *pbstrHelpStringDll=
4642 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4644 }else {/* for a member */
4645 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4646 if(pFDesc->funcdesc.memid==memid){
4648 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4649 if(pdwHelpStringContext)
4650 *pdwHelpStringContext=pFDesc->HelpStringContext;
4651 if(pbstrHelpStringDll)
4652 *pbstrHelpStringDll=
4653 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4656 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4657 if(pVDesc->vardesc.memid==memid){
4659 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4660 if(pdwHelpStringContext)
4661 *pdwHelpStringContext=pVDesc->HelpStringContext;
4662 if(pbstrHelpStringDll)
4663 *pbstrHelpStringDll=
4664 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4668 return TYPE_E_ELEMENTNOTFOUND;
4671 /* ITypeInfo2::GetAllCustData
4673 * Gets all custom data items for the Type info.
4676 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4678 CUSTDATA *pCustData)
4680 ICOM_THIS( ITypeInfoImpl, iface);
4681 TLBCustData *pCData;
4684 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4686 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4687 if(pCustData->prgCustData ){
4688 pCustData->cCustData=This->ctCustData;
4689 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4690 pCustData->prgCustData[i].guid=pCData->guid;
4691 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4694 ERR(" OUT OF MEMORY! \n");
4695 return E_OUTOFMEMORY;
4700 /* ITypeInfo2::GetAllFuncCustData
4702 * Gets all custom data items for the specified Function
4705 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4708 CUSTDATA *pCustData)
4710 ICOM_THIS( ITypeInfoImpl, iface);
4711 TLBCustData *pCData;
4712 TLBFuncDesc * pFDesc;
4714 TRACE("(%p) index %d\n", This, index);
4715 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4716 pFDesc=pFDesc->next)
4719 pCustData->prgCustData =
4720 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4721 if(pCustData->prgCustData ){
4722 pCustData->cCustData=pFDesc->ctCustData;
4723 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4724 pCData = pCData->next){
4725 pCustData->prgCustData[i].guid=pCData->guid;
4726 VariantCopy(& pCustData->prgCustData[i].varValue,
4730 ERR(" OUT OF MEMORY! \n");
4731 return E_OUTOFMEMORY;
4735 return TYPE_E_ELEMENTNOTFOUND;
4738 /* ITypeInfo2::GetAllParamCustData
4740 * Gets all custom data items for the Functions
4743 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4744 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4746 ICOM_THIS( ITypeInfoImpl, iface);
4747 TLBCustData *pCData=NULL;
4748 TLBFuncDesc * pFDesc;
4750 TRACE("(%p) index %d\n", This, indexFunc);
4751 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4752 pFDesc=pFDesc->next)
4754 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4755 pCustData->prgCustData =
4756 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4757 sizeof(CUSTDATAITEM));
4758 if(pCustData->prgCustData ){
4759 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4760 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4761 pCData; i++, pCData = pCData->next){
4762 pCustData->prgCustData[i].guid=pCData->guid;
4763 VariantCopy(& pCustData->prgCustData[i].varValue,
4767 ERR(" OUT OF MEMORY! \n");
4768 return E_OUTOFMEMORY;
4772 return TYPE_E_ELEMENTNOTFOUND;
4775 /* ITypeInfo2::GetAllVarCustData
4777 * Gets all custom data items for the specified Variable
4780 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4781 UINT index, CUSTDATA *pCustData)
4783 ICOM_THIS( ITypeInfoImpl, iface);
4784 TLBCustData *pCData;
4785 TLBVarDesc * pVDesc;
4787 TRACE("(%p) index %d\n", This, index);
4788 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4789 pVDesc=pVDesc->next)
4792 pCustData->prgCustData =
4793 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4794 if(pCustData->prgCustData ){
4795 pCustData->cCustData=pVDesc->ctCustData;
4796 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4797 pCData = pCData->next){
4798 pCustData->prgCustData[i].guid=pCData->guid;
4799 VariantCopy(& pCustData->prgCustData[i].varValue,
4803 ERR(" OUT OF MEMORY! \n");
4804 return E_OUTOFMEMORY;
4808 return TYPE_E_ELEMENTNOTFOUND;
4811 /* ITypeInfo2::GetAllImplCustData
4813 * Gets all custom data items for the specified implementation type
4816 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4819 CUSTDATA *pCustData)
4821 ICOM_THIS( ITypeInfoImpl, iface);
4822 TLBCustData *pCData;
4823 TLBImplType * pRDesc;
4825 TRACE("(%p) index %d\n", This, index);
4826 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4827 pRDesc=pRDesc->next)
4830 pCustData->prgCustData =
4831 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4832 if(pCustData->prgCustData ){
4833 pCustData->cCustData=pRDesc->ctCustData;
4834 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4835 pCData = pCData->next){
4836 pCustData->prgCustData[i].guid=pCData->guid;
4837 VariantCopy(& pCustData->prgCustData[i].varValue,
4841 ERR(" OUT OF MEMORY! \n");
4842 return E_OUTOFMEMORY;
4846 return TYPE_E_ELEMENTNOTFOUND;
4849 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4851 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4853 ITypeInfo_fnQueryInterface,
4855 ITypeInfo_fnRelease,
4857 ITypeInfo_fnGetTypeAttr,
4858 ITypeInfo_fnGetTypeComp,
4859 ITypeInfo_fnGetFuncDesc,
4860 ITypeInfo_fnGetVarDesc,
4861 ITypeInfo_fnGetNames,
4862 ITypeInfo_fnGetRefTypeOfImplType,
4863 ITypeInfo_fnGetImplTypeFlags,
4864 ITypeInfo_fnGetIDsOfNames,
4866 ITypeInfo_fnGetDocumentation,
4867 ITypeInfo_fnGetDllEntry,
4868 ITypeInfo_fnGetRefTypeInfo,
4869 ITypeInfo_fnAddressOfMember,
4870 ITypeInfo_fnCreateInstance,
4871 ITypeInfo_fnGetMops,
4872 ITypeInfo_fnGetContainingTypeLib,
4873 ITypeInfo_fnReleaseTypeAttr,
4874 ITypeInfo_fnReleaseFuncDesc,
4875 ITypeInfo_fnReleaseVarDesc,
4877 ITypeInfo2_fnGetTypeKind,
4878 ITypeInfo2_fnGetTypeFlags,
4879 ITypeInfo2_fnGetFuncIndexOfMemId,
4880 ITypeInfo2_fnGetVarIndexOfMemId,
4881 ITypeInfo2_fnGetCustData,
4882 ITypeInfo2_fnGetFuncCustData,
4883 ITypeInfo2_fnGetParamCustData,
4884 ITypeInfo2_fnGetVarCustData,
4885 ITypeInfo2_fnGetImplTypeCustData,
4886 ITypeInfo2_fnGetDocumentation2,
4887 ITypeInfo2_fnGetAllCustData,
4888 ITypeInfo2_fnGetAllFuncCustData,
4889 ITypeInfo2_fnGetAllParamCustData,
4890 ITypeInfo2_fnGetAllVarCustData,
4891 ITypeInfo2_fnGetAllImplTypeCustData,