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;
284 return TYPE_E_CANTLOADLIBRARY;
287 TRACE("File %s index %d\n", debugstr_w(szPath), index);
289 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
294 case REGKIND_DEFAULT:
295 /* FIXME: is this correct? */
296 if (!szFile || !szFile[0] ||
297 (szFile[0] != '\\' && szFile[0] != '/' && szFile[1] != ':'))
299 /* else fall-through */
300 case REGKIND_REGISTER:
301 /* FIXME: Help path? */
302 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szFile, NULL)))
304 IUnknown_Release(*pptLib);
312 TRACE(" returns %08lx\n",res);
316 /******************************************************************************
317 * LoadRegTypeLib [OLEAUT32.162]
319 HRESULT WINAPI LoadRegTypeLib(
320 REFGUID rguid, /* [in] referenced guid */
321 WORD wVerMajor, /* [in] major version */
322 WORD wVerMinor, /* [in] minor version */
323 LCID lcid, /* [in] locale id */
324 ITypeLib **ppTLib) /* [out] path of typelib */
327 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
331 res= LoadTypeLib(bstr, ppTLib);
335 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
341 /******************************************************************************
342 * RegisterTypeLib [OLEAUT32.163]
343 * Adds information about a type library to the System Registry
345 * Docs: ITypeLib FAR * ptlib
346 * Docs: OLECHAR FAR* szFullPath
347 * Docs: OLECHAR FAR* szHelpDir
353 HRESULT WINAPI RegisterTypeLib(
354 ITypeLib * ptlib, /* [in] Pointer to the library*/
355 OLECHAR * szFullPath, /* [in] full Path of the library*/
356 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
367 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
369 if (ptlib == NULL || szFullPath == NULL)
372 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
375 StringFromGUID2(&attr->guid, guid, 80);
376 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
377 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
378 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
379 HeapFree(GetProcessHeap(), 0, guidA);
382 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
383 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
387 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
389 if (RegSetValueExW(key, NULL, 0, REG_SZ,
390 (BYTE *)doc, lstrlenW(doc) * sizeof(OLECHAR)) != ERROR_SUCCESS)
398 /* FIXME: This *seems* to be 0 always, not sure though */
399 if (res == S_OK && RegCreateKeyExA(key, "0\\win32", 0, NULL, 0,
400 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
402 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
403 (BYTE *)szFullPath, lstrlenW(szFullPath) * sizeof(OLECHAR)) != ERROR_SUCCESS)
411 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
412 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
415 /* FIXME: is %u correct? */
416 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
417 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
418 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
426 /* register OLE Automation-compatible interfaces for this typelib */
427 types = ITypeLib_GetTypeInfoCount(ptlib);
428 for (tidx=0; tidx<types; tidx++) {
429 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
430 LPOLESTR name = NULL;
431 ITypeInfo *tinfo = NULL;
433 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
435 case TKIND_INTERFACE:
436 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
437 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
440 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
441 /* ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo); */
444 TRACE_(typelib)("%d: coclass %s\n", tidx, debugstr_w(name));
445 /* coclasses should probably not be registered? */
448 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
452 TYPEATTR *tattr = NULL;
453 ITypeInfo_GetTypeAttr(tinfo, &tattr);
455 TRACE_(typelib)("guid=%s, flags=%04x\n",
456 debugstr_guid(&tattr->guid),
458 if (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION) {
459 /* register interface<->typelib coupling */
460 StringFromGUID2(&tattr->guid, guid, 80);
461 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
462 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
463 HeapFree(GetProcessHeap(), 0, guidA);
465 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
466 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
468 RegSetValueExW(key, NULL, 0, REG_SZ,
469 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
471 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
472 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
473 RegSetValueExA(subKey, NULL, 0, REG_SZ,
477 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
478 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
479 RegSetValueExA(subKey, NULL, 0, REG_SZ,
484 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
485 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
487 StringFromGUID2(&attr->guid, guid, 80);
488 snprintf(ver, sizeof(ver), "%x.%x",
489 attr->wMajorVerNum, attr->wMinorVerNum);
490 RegSetValueExW(subKey, NULL, 0, REG_SZ,
491 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
492 RegSetValueExA(subKey, "Version", 0, REG_SZ,
499 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
501 ITypeInfo_Release(tinfo);
508 ITypeLib_ReleaseTLibAttr(ptlib, attr);
514 /******************************************************************************
515 * UnRegisterTypeLib [OLEAUT32.186]
516 * Removes information about a type library from the System Registry
523 HRESULT WINAPI UnRegisterTypeLib(
524 REFGUID libid, /* [in] Guid of the library */
525 WORD wVerMajor, /* [in] major version */
526 WORD wVerMinor, /* [in] minor version */
527 LCID lcid, /* [in] locale id */
530 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
531 return S_OK; /* FIXME: pretend everything is OK */
534 /****************************************************************************
535 * OaBuildVersion (TYPELIB.15)
537 * known TYPELIB.DLL versions:
539 * OLE 2.01 no OaBuildVersion() avail 1993 -- ---
540 * OLE 2.02 1993-94 02 3002
543 * OLE 2.03 W98 SE orig. file !! 1993-95 10 3024
544 * OLE 2.1 NT 1993-95 ?? ???
545 * OLE 2.3.1 W95 23 700
546 * OLE2 4.0 NT4SP6 1993-98 40 4277
548 DWORD WINAPI OaBuildVersion16(void)
550 /* FIXME: I'd like to return the highest currently known version value
551 * in case the user didn't force a --winver, but I don't know how
552 * to retrieve the "versionForced" info from misc/version.c :(
553 * (this would be useful in other places, too) */
554 FIXME("Please report to a.mohr@mailto.de if you get version error messages !\n");
555 switch(GetVersion() & 0x8000ffff) /* mask off build number */
557 case 0x80000a03: /* WIN31 */
558 return MAKELONG(3027, 3); /* WfW 3.11 */
559 case 0x80000004: /* WIN95 */
560 return MAKELONG(700, 23); /* Win95A */
561 case 0x80000a04: /* WIN98 */
562 return MAKELONG(3024, 10); /* W98 SE */
563 case 0x00000004: /* NT4 */
564 return MAKELONG(4277, 40); /* NT4 SP6 */
566 FIXME("Version value not known yet. Please investigate it!\n");
571 /* for better debugging info leave the static out for the time being */
574 /*======================= ITypeLib implementation =======================*/
576 typedef struct tagTLBCustData
580 struct tagTLBCustData* next;
583 /* data structure for import typelibs */
584 typedef struct tagTLBImpLib
586 int offset; /* offset in the file (MSFT)
587 offset in nametable (SLTG)
588 just used to identify library while reading
590 GUID guid; /* libid */
591 BSTR name; /* name */
593 LCID lcid; /* lcid of imported typelib */
595 WORD wVersionMajor; /* major version number */
596 WORD wVersionMinor; /* minor version number */
598 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
599 NULL if not yet loaded */
600 struct tagTLBImpLib * next;
603 /* internal ITypeLib data */
604 typedef struct tagITypeLibImpl
606 ICOM_VFIELD(ITypeLib2);
608 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
610 /* strings can be stored in tlb as multibyte strings BUT they are *always*
611 * exported to the application as a UNICODE string.
617 unsigned long dwHelpContext;
618 int TypeInfoCount; /* nr of typeinfo's in librarry */
619 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
620 int ctCustData; /* number of items in cust data list */
621 TLBCustData * pCustData; /* linked list to cust data */
622 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
623 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
624 libary. Only used while read MSFT
628 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
630 /* ITypeLib methods */
631 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
632 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
634 /*======================= ITypeInfo implementation =======================*/
636 /* data for refernced types */
637 typedef struct tagTLBRefType
639 INT index; /* Type index for internal ref or for external ref
640 it the format is SLTG. -2 indicates to
643 GUID guid; /* guid of the referenced type */
644 /* if index == TLB_REF_USE_GUID */
646 HREFTYPE reference; /* The href of this ref */
647 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
648 TLB_REF_INTERNAL for internal refs
649 TLB_REF_NOT_FOUND for broken refs */
651 struct tagTLBRefType * next;
654 #define TLB_REF_USE_GUID -2
656 #define TLB_REF_INTERNAL (void*)-2
657 #define TLB_REF_NOT_FOUND (void*)-1
659 /* internal Parameter data */
660 typedef struct tagTLBParDesc
664 TLBCustData * pCustData; /* linked list to cust data */
667 /* internal Function data */
668 typedef struct tagTLBFuncDesc
670 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
671 BSTR Name; /* the name of this function */
672 TLBParDesc *pParamDesc; /* array with param names and custom data */
674 int HelpStringContext;
676 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
678 TLBCustData * pCustData; /* linked list to cust data; */
679 struct tagTLBFuncDesc * next;
682 /* internal Variable data */
683 typedef struct tagTLBVarDesc
685 VARDESC vardesc; /* lots of info on the variable and its attributes. */
686 BSTR Name; /* the name of this variable */
688 int HelpStringContext; /* fixme: where? */
691 TLBCustData * pCustData;/* linked list to cust data; */
692 struct tagTLBVarDesc * next;
695 /* internal implemented interface data */
696 typedef struct tagTLBImplType
698 HREFTYPE hRef; /* hRef of interface */
699 int implflags; /* IMPLFLAG_*s */
701 TLBCustData * pCustData;/* linked list to custom data; */
702 struct tagTLBImplType *next;
705 /* internal TypeInfo data */
706 typedef struct tagITypeInfoImpl
708 ICOM_VFIELD(ITypeInfo2);
710 TYPEATTR TypeAttr ; /* _lots_ of type information. */
711 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
712 int index; /* index in this typelib; */
713 /* type libs seem to store the doc strings in ascii
714 * so why should we do it in unicode?
718 unsigned long dwHelpContext;
719 unsigned long dwHelpStringContext;
722 TLBFuncDesc * funclist; /* linked list with function descriptions */
725 TLBVarDesc * varlist; /* linked list with variable descriptions */
727 /* Implemented Interfaces */
728 TLBImplType * impltypelist;
730 TLBRefType * reflist;
732 TLBCustData * pCustData; /* linked list to cust data; */
733 struct tagITypeInfoImpl * next;
736 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
738 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
740 typedef struct tagTLBContext
742 unsigned int oStart; /* start of TLB in file */
743 unsigned int pos; /* current pos */
744 unsigned int length; /* total length */
745 void *mapping; /* memory mapping */
746 MSFT_SegDir * pTblDir;
747 ITypeLibImpl* pLibInfo;
751 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
756 static void dump_VarType(VARTYPE vt,char *szVarType) {
757 /* FIXME : we could have better trace here, depending on the VARTYPE
760 if (vt & VT_RESERVED)
761 szVarType += strlen(strcpy(szVarType, "reserved | "));
763 szVarType += strlen(strcpy(szVarType, "ref to "));
765 szVarType += strlen(strcpy(szVarType, "array of "));
767 szVarType += strlen(strcpy(szVarType, "vector of "));
768 switch(vt & VT_TYPEMASK) {
769 case VT_UI1: sprintf(szVarType, "VT_UI"); break;
770 case VT_I2: sprintf(szVarType, "VT_I2"); break;
771 case VT_I4: sprintf(szVarType, "VT_I4"); break;
772 case VT_R4: sprintf(szVarType, "VT_R4"); break;
773 case VT_R8: sprintf(szVarType, "VT_R8"); break;
774 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
775 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
776 case VT_CY: sprintf(szVarType, "VT_CY"); break;
777 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
778 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
779 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
780 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
781 case VT_I1: sprintf(szVarType, "VT_I1"); break;
782 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
783 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
784 case VT_INT: sprintf(szVarType, "VT_INT"); break;
785 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
786 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
787 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
788 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED\n"); break;
789 default: sprintf(szVarType, "unknown(%d)", vt & VT_TYPEMASK); break;
793 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
794 if (pTD->vt & VT_RESERVED)
795 szVarType += strlen(strcpy(szVarType, "reserved | "));
796 if (pTD->vt & VT_BYREF)
797 szVarType += strlen(strcpy(szVarType, "ref to "));
798 if (pTD->vt & VT_ARRAY)
799 szVarType += strlen(strcpy(szVarType, "array of "));
800 if (pTD->vt & VT_VECTOR)
801 szVarType += strlen(strcpy(szVarType, "vector of "));
802 switch(pTD->vt & VT_TYPEMASK) {
803 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
804 case VT_I2: sprintf(szVarType, "VT_I2"); break;
805 case VT_I4: sprintf(szVarType, "VT_I4"); break;
806 case VT_R4: sprintf(szVarType, "VT_R4"); break;
807 case VT_R8: sprintf(szVarType, "VT_R8"); break;
808 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
809 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
810 case VT_CY: sprintf(szVarType, "VT_CY"); break;
811 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
812 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
813 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
814 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
815 case VT_I1: sprintf(szVarType, "VT_I1"); break;
816 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
817 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
818 case VT_INT: sprintf(szVarType, "VT_INT"); break;
819 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
820 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
821 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
822 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
823 pTD->u.hreftype); break;
824 case VT_PTR: sprintf(szVarType, "ptr to ");
825 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
827 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
828 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
830 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
831 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
832 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
835 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
839 static void dump_ELEMDESC(ELEMDESC *edesc) {
841 dump_TypeDesc(&edesc->tdesc,buf);
842 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
843 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
844 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
846 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
848 MESSAGE("memid is %08lx\n",funcdesc->memid);
849 for (i=0;i<funcdesc->cParams;i++) {
850 MESSAGE("Param %d:\n",i);
851 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
853 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
854 switch (funcdesc->funckind) {
855 case FUNC_VIRTUAL: MESSAGE("virtual");break;
856 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
857 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
858 case FUNC_STATIC: MESSAGE("static");break;
859 case FUNC_DISPATCH: MESSAGE("dispatch");break;
860 default: MESSAGE("unknown");break;
862 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
863 switch (funcdesc->invkind) {
864 case INVOKE_FUNC: MESSAGE("func");break;
865 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
866 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
867 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
869 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
870 switch (funcdesc->callconv) {
871 case CC_CDECL: MESSAGE("cdecl");break;
872 case CC_PASCAL: MESSAGE("pascal");break;
873 case CC_STDCALL: MESSAGE("stdcall");break;
874 case CC_SYSCALL: MESSAGE("syscall");break;
877 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
878 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
879 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
881 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
884 if (!TRACE_ON(typelib))
886 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
887 for (i=0;i<pfd->funcdesc.cParams;i++)
888 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
891 dump_FUNCDESC(&(pfd->funcdesc));
893 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
894 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
896 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
900 dump_TLBFuncDescOne(pfd);
904 static void dump_TLBVarDesc(TLBVarDesc * pvd)
908 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
913 static void dump_TLBImpLib(TLBImpLib *import)
915 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
916 debugstr_w(import->name));
917 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
918 import->wVersionMinor, import->lcid, import->offset);
921 static void dump_TLBRefType(TLBRefType * prt)
925 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
927 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
929 TRACE_(typelib)("type no: %d\n", prt->index);
931 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
932 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
933 TRACE_(typelib)("in lib\n");
934 dump_TLBImpLib(prt->pImpTLInfo);
940 static void dump_TLBImplType(TLBImplType * impl)
944 "implementing/inheriting interface hRef = %lx implflags %x\n",
945 impl->hRef, impl->implflags);
950 static void dump_Variant(VARIANT * pvar)
955 TRACE("(%p)\n", pvar);
959 ZeroMemory(szVarType, sizeof(szVarType));
961 /* FIXME : we could have better trace here, depending on the VARTYPE
964 dump_VarType(V_VT(pvar),szVarType);
966 TRACE("VARTYPE: %s\n", szVarType);
968 if (V_VT(pvar) & VT_BYREF) {
969 ref = V_UNION(pvar, byref);
972 else ref = &V_UNION(pvar, cVal);
974 if (V_VT(pvar) & VT_ARRAY) {
978 if (V_VT(pvar) & VT_VECTOR) {
986 TRACE("%d\n", *(short*)ref);
990 TRACE("%d\n", *(INT*)ref);
994 TRACE("%3.3e\n", *(float*)ref);
998 TRACE("%3.3e\n", *(double*)ref);
1002 TRACE("%s\n", *(VARIANT_BOOL*)ref ? "TRUE" : "FALSE");
1006 TRACE("%s\n", debugstr_w(*(BSTR*)ref));
1011 TRACE("%p\n", *(LPVOID*)ref);
1015 if (V_VT(pvar) & VT_BYREF) dump_Variant(ref);
1019 TRACE("(?)%ld\n", *(long*)ref);
1024 static void dump_DispParms(DISPPARAMS * pdp)
1028 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1030 while (index < pdp->cArgs)
1032 dump_Variant( &pdp->rgvarg[index] );
1037 static char * typekind_desc[] =
1050 static void dump_TypeInfo(ITypeInfoImpl * pty)
1052 TRACE("%p ref=%u\n", pty, pty->ref);
1053 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1054 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1055 TRACE("fct:%u var:%u impl:%u\n",
1056 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1057 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1058 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1059 dump_TLBFuncDesc(pty->funclist);
1060 dump_TLBVarDesc(pty->varlist);
1061 dump_TLBImplType(pty->impltypelist);
1064 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1066 /* VT_LPWSTR is largest type that */
1067 /* may appear in type description*/
1068 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1069 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1070 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1071 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1072 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1073 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1077 static void TLB_abort()
1081 static void * TLB_Alloc(unsigned size)
1084 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1086 ERR("cannot allocate memory\n");
1091 static void TLB_Free(void * ptr)
1093 HeapFree(GetProcessHeap(), 0, ptr);
1097 /**********************************************************************
1099 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1102 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1104 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1105 pcx->pos, count, pcx->oStart, pcx->length, where);
1107 if (where != DO_NOT_SEEK)
1109 where += pcx->oStart;
1110 if (where > pcx->length)
1113 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1118 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1119 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1124 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1126 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1128 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1129 memset(pGuid,0, sizeof(GUID));
1132 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1135 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1138 MSFT_NameIntro niName;
1140 WCHAR* pwstring = NULL;
1141 BSTR bstrName = NULL;
1143 MSFT_Read(&niName, sizeof(niName), pcx,
1144 pcx->pTblDir->pNametab.offset+offset);
1145 niName.namelen &= 0xFF; /* FIXME: correct ? */
1146 name=TLB_Alloc((niName.namelen & 0xff) +1);
1147 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1148 name[niName.namelen & 0xff]='\0';
1150 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1153 /* no invalid characters in string */
1156 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1158 /* don't check for invalid character since this has been done previously */
1159 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1161 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1162 lengthInChars = SysStringLen(bstrName);
1163 HeapFree(GetProcessHeap(), 0, pwstring);
1166 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1170 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1177 if(offset<0) return NULL;
1178 MSFT_Read(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1179 if(length <= 0) return 0;
1180 string=TLB_Alloc(length +1);
1181 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1182 string[length]='\0';
1184 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1185 string, -1, NULL, 0);
1187 /* no invalid characters in string */
1190 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1192 /* don't check for invalid character since this has been done previously */
1193 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1195 bstr = SysAllocStringLen(pwstring, lengthInChars);
1196 lengthInChars = SysStringLen(bstr);
1197 HeapFree(GetProcessHeap(), 0, pwstring);
1200 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1204 * read a value and fill a VARIANT structure
1206 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1210 TRACE_(typelib)("\n");
1212 if(offset <0) { /* data are packed in here */
1213 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1214 V_UNION(pVar, iVal) = offset & 0xffff;
1217 MSFT_Read(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1218 pcx->pTblDir->pCustData.offset + offset );
1219 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1220 switch (V_VT(pVar)){
1221 case VT_EMPTY: /* FIXME: is this right? */
1222 case VT_NULL: /* FIXME: is this right? */
1223 case VT_I2 : /* this should not happen */
1234 case VT_VOID : /* FIXME: is this right? */
1242 case VT_DECIMAL : /* FIXME: is this right? */
1245 /* pointer types with known behaviour */
1248 MSFT_Read(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1250 FIXME("BSTR length = %d?\n", size);
1252 ptr=TLB_Alloc(size);/* allocate temp buffer */
1253 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1254 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1255 /* FIXME: do we need a AtoW conversion here? */
1256 V_UNION(pVar, bstrVal[size])=L'\0';
1257 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1262 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1269 case VT_USERDEFINED :
1275 case VT_STREAMED_OBJECT :
1276 case VT_STORED_OBJECT :
1277 case VT_BLOB_OBJECT :
1282 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1286 if(size>0) /* (big|small) endian correct? */
1287 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1291 * create a linked list with custom data
1293 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1299 TRACE_(typelib)("\n");
1303 pNew=TLB_Alloc(sizeof(TLBCustData));
1304 MSFT_Read(&entry, sizeof(entry), pcx,
1305 pcx->pTblDir->pCDGuids.offset+offset);
1306 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1307 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1308 /* add new custom data at head of the list */
1309 pNew->next=*ppCustData;
1311 offset = entry.next;
1316 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1320 pTd->vt=type & VT_TYPEMASK;
1322 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1324 if(pTd->vt == VT_USERDEFINED)
1325 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1327 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1331 MSFT_DoFuncs(TLBContext* pcx,
1336 TLBFuncDesc** pptfd)
1339 * member information is stored in a data structure at offset
1340 * indicated by the memoffset field of the typeinfo structure
1341 * There are several distinctive parts.
1342 * the first part starts with a field that holds the total length
1343 * of this (first) part excluding this field. Then follow the records,
1344 * for each member there is one record.
1346 * First entry is always the length of the record (excluding this
1348 * Rest of the record depends on the type of the member. If there is
1349 * a field indicating the member type (function variable intereface etc)
1350 * I have not found it yet. At this time we depend on the information
1351 * in the type info and the usual order how things are stored.
1353 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1356 * Third is a equal sized array with file offsets to the name entry
1359 * Forth and last (?) part is an array with offsets to the records in the
1360 * first part of this file segment.
1363 int infolen, nameoffset, reclength, nrattributes, i;
1364 int recoffset = offset + sizeof(INT);
1367 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1369 TRACE_(typelib)("\n");
1371 MSFT_Read(&infolen, sizeof(INT), pcx, offset);
1373 for ( i = 0; i < cFuncs ; i++ )
1375 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1377 /* name, eventually add to a hash table */
1378 MSFT_Read(&nameoffset,
1381 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1383 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1385 /* read the function information record */
1386 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1390 MSFT_Read(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1392 /* do the attributes */
1393 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1396 if ( nrattributes > 0 )
1398 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1400 if ( nrattributes > 1 )
1402 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1403 pFuncRec->OptAttr[1]) ;
1405 if ( nrattributes > 2 )
1407 if ( pFuncRec->FKCCIC & 0x2000 )
1409 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1413 (*pptfd)->Entry = MSFT_ReadString(pcx,
1414 pFuncRec->OptAttr[2]);
1416 if( nrattributes > 5 )
1418 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1420 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1423 pFuncRec->OptAttr[6],
1424 &(*pptfd)->pCustData);
1431 /* fill the FuncDesc Structure */
1432 MSFT_Read( & (*pptfd)->funcdesc.memid,
1434 offset + infolen + ( i + 1) * sizeof(INT));
1436 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1437 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1438 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1439 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1440 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1441 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1442 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1446 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1449 /* do the parameters/arguments */
1450 if(pFuncRec->nrargs)
1453 MSFT_ParameterInfo paraminfo;
1455 (*pptfd)->funcdesc.lprgelemdescParam =
1456 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1458 (*pptfd)->pParamDesc =
1459 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1461 MSFT_Read(¶minfo,
1464 recoffset + reclength -
1465 pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1467 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1469 TYPEDESC* lpArgTypeDesc = 0;
1473 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1476 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1478 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1480 /* SEEK value = jump to offset,
1481 * from there jump to the end of record,
1482 * go back by (j-1) arguments
1484 MSFT_Read( ¶minfo ,
1485 sizeof(MSFT_ParameterInfo), pcx,
1486 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1487 * sizeof(MSFT_ParameterInfo)));
1489 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1491 while ( lpArgTypeDesc != NULL )
1493 switch ( lpArgTypeDesc->vt )
1496 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1500 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1503 case VT_USERDEFINED:
1504 MSFT_DoRefType(pcx, pTI,
1505 lpArgTypeDesc->u.hreftype);
1507 lpArgTypeDesc = NULL;
1511 lpArgTypeDesc = NULL;
1517 /* parameter is the return value! */
1518 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1520 TYPEDESC* lpArgTypeDesc;
1522 (*pptfd)->funcdesc.elemdescFunc =
1523 (*pptfd)->funcdesc.lprgelemdescParam[j];
1525 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1527 while ( lpArgTypeDesc != NULL )
1529 switch ( lpArgTypeDesc->vt )
1532 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1536 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1540 case VT_USERDEFINED:
1543 lpArgTypeDesc->u.hreftype);
1545 lpArgTypeDesc = NULL;
1549 lpArgTypeDesc = NULL;
1554 /* second time around */
1555 for(j=0;j<pFuncRec->nrargs;j++)
1558 (*pptfd)->pParamDesc[j].Name =
1559 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1562 if ( (PARAMFLAG_FHASDEFAULT &
1563 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1564 ((pFuncRec->FKCCIC) & 0x1000) )
1566 INT* pInt = (INT *)((char *)pFuncRec +
1568 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1570 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1572 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1573 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1575 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1579 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1582 pFuncRec->OptAttr[7+j],
1583 &(*pptfd)->pParamDesc[j].pCustData);
1588 /* scode is not used: archaic win16 stuff FIXME: right? */
1589 (*pptfd)->funcdesc.cScodes = 0 ;
1590 (*pptfd)->funcdesc.lprgscode = NULL ;
1592 pptfd = & ((*pptfd)->next);
1593 recoffset += reclength;
1596 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1597 int cVars, int offset, TLBVarDesc ** pptvd)
1599 int infolen, nameoffset, reclength;
1601 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1605 TRACE_(typelib)("\n");
1607 MSFT_Read(&infolen,sizeof(INT), pcx, offset);
1608 MSFT_Read(&recoffset,sizeof(INT), pcx, offset + infolen +
1609 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1610 recoffset += offset+sizeof(INT);
1611 for(i=0;i<cVars;i++){
1612 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1613 /* name, eventually add to a hash table */
1614 MSFT_Read(&nameoffset, sizeof(INT), pcx,
1615 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1616 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1617 /* read the variable information record */
1618 MSFT_Read(&reclength, sizeof(INT), pcx, recoffset);
1620 MSFT_Read(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK) ;
1622 if(reclength >(6*sizeof(INT)) )
1623 (*pptvd)->HelpContext=pVarRec->HelpContext;
1624 if(reclength >(7*sizeof(INT)) )
1625 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1626 if(reclength >(8*sizeof(INT)) )
1627 if(reclength >(9*sizeof(INT)) )
1628 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1629 /* fill the VarDesc Structure */
1630 MSFT_Read(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1631 offset + infolen + ( i + 1) * sizeof(INT));
1632 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1633 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1634 MSFT_GetTdesc(pcx, pVarRec->DataType,
1635 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1636 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) fixme?? */
1637 if(pVarRec->VarKind == VAR_CONST ){
1638 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1639 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1640 pVarRec->OffsValue, pcx);
1642 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1643 pptvd=&((*pptvd)->next);
1644 recoffset += reclength;
1647 /* fill in data for a hreftype (offset). When the refernced type is contained
1648 * in the typelib, it's just an (file) offset in the type info base dir.
1649 * If comes from import, it's an offset+1 in the ImpInfo table
1651 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1655 TLBRefType **ppRefType = &pTI->reflist;
1657 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1660 if((*ppRefType)->reference == offset)
1662 ppRefType = &(*ppRefType)->next;
1665 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1666 sizeof(**ppRefType));
1668 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1669 /* external typelib */
1670 MSFT_ImpInfo impinfo;
1671 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1673 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1675 MSFT_Read(&impinfo, sizeof(impinfo), pcx,
1676 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1677 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1678 if(pImpLib->offset==impinfo.oImpFile) break;
1679 pImpLib=pImpLib->next;
1682 (*ppRefType)->reference=offset;
1683 (*ppRefType)->pImpTLInfo = pImpLib;
1684 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1685 (*ppRefType)->index = TLB_REF_USE_GUID;
1687 ERR("Cannot find a reference\n");
1688 (*ppRefType)->reference=-1;
1689 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1692 /* in this typelib */
1693 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1694 (*ppRefType)->reference=offset;
1695 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1699 /* process Implemented Interfaces of a com class */
1700 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1704 MSFT_RefRecord refrec;
1705 TLBImplType **ppImpl = &pTI->impltypelist;
1707 TRACE_(typelib)("\n");
1709 for(i=0;i<count;i++){
1710 if(offset<0) break; /* paranoia */
1711 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1712 MSFT_Read(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1713 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1714 (*ppImpl)->hRef = refrec.reftype;
1715 (*ppImpl)->implflags=refrec.flags;
1716 (*ppImpl)->ctCustData=
1717 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1718 offset=refrec.onext;
1719 ppImpl=&((*ppImpl)->next);
1723 * process a typeinfo record
1725 ITypeInfoImpl * MSFT_DoTypeInfo(
1728 ITypeLibImpl * pLibInfo)
1730 MSFT_TypeInfoBase tiBase;
1731 ITypeInfoImpl *ptiRet;
1733 TRACE_(typelib)("count=%u\n", count);
1735 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1736 MSFT_Read(&tiBase, sizeof(tiBase) ,pcx ,
1737 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1738 /* this is where we are coming from */
1739 ptiRet->pTypeLib = pLibInfo;
1740 ptiRet->index=count;
1741 /* fill in the typeattr fields */
1742 FIXME("Assign constructor/destructor memid\n");
1744 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
1745 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
1746 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
1747 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
1748 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
1749 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
1750 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
1751 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
1752 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
1753 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
1754 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
1755 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
1756 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
1757 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
1758 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
1759 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
1760 MSFT_GetTdesc(pcx, tiBase.datatype1,
1761 &ptiRet->TypeAttr.tdescAlias, ptiRet);
1764 /* IDLDESC idldescType; *//* never saw this one != zero */
1766 /* name, eventually add to a hash table */
1767 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
1768 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
1770 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
1771 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
1772 ptiRet->dwHelpContext=tiBase.helpcontext;
1773 /* note: InfoType's Help file and HelpStringDll come from the containing
1774 * library. Further HelpString and Docstring appear to be the same thing :(
1777 if(ptiRet->TypeAttr.cFuncs >0 )
1778 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1779 ptiRet->TypeAttr.cVars,
1780 tiBase.memoffset, & ptiRet->funclist);
1782 if(ptiRet->TypeAttr.cVars >0 )
1783 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
1784 ptiRet->TypeAttr.cVars,
1785 tiBase.memoffset, & ptiRet->varlist);
1786 if(ptiRet->TypeAttr.cImplTypes >0 ) {
1787 switch(ptiRet->TypeAttr.typekind)
1790 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
1793 case TKIND_DISPATCH:
1794 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1796 if (tiBase.datatype1 != -1)
1798 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1799 ptiRet->impltypelist->hRef = tiBase.datatype1;
1802 { /* FIXME: This is a really bad hack to add IDispatch */
1803 char* szStdOle = "stdole2.tlb\0";
1804 int nStdOleLen = strlen(szStdOle);
1805 TLBRefType **ppRef = &ptiRet->reflist;
1808 if((*ppRef)->reference == -1)
1810 ppRef = &(*ppRef)->next;
1813 *ppRef = TLB_Alloc(sizeof(**ppRef));
1814 (*ppRef)->guid = IID_IDispatch;
1815 (*ppRef)->reference = -1;
1816 (*ppRef)->index = TLB_REF_USE_GUID;
1817 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
1818 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
1819 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
1822 MultiByteToWideChar(CP_ACP,
1826 (*ppRef)->pImpTLInfo->name,
1827 SysStringLen((*ppRef)->pImpTLInfo->name));
1829 (*ppRef)->pImpTLInfo->lcid = 0;
1830 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
1831 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
1836 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
1837 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
1838 ptiRet->impltypelist->hRef = tiBase.datatype1;
1843 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
1845 TRACE_(typelib)("%s guid: %s kind:%s\n",
1846 debugstr_w(ptiRet->Name),
1847 debugstr_guid(&ptiRet->TypeAttr.guid),
1848 typekind_desc[ptiRet->TypeAttr.typekind]);
1853 /****************************************************************************
1856 * find the type of the typelib file and map the typelib resource into
1859 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
1860 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
1861 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
1863 int ret = TYPE_E_CANTLOADLIBRARY;
1864 DWORD dwSignature = 0;
1867 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
1871 /* check the signature of the file */
1872 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1873 if (INVALID_HANDLE_VALUE != hFile)
1875 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
1878 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
1881 /* retrieve file size */
1882 DWORD dwTLBLength = GetFileSize(hFile, NULL);
1884 /* first try to load as *.tlb */
1885 dwSignature = *((DWORD*) pBase);
1886 if ( dwSignature == MSFT_SIGNATURE)
1888 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1890 else if ( dwSignature == SLTG_SIGNATURE)
1892 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1894 UnmapViewOfFile(pBase);
1896 CloseHandle(hMapping);
1901 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
1903 /* find the typelibrary resource*/
1904 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
1905 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
1908 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
1912 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
1915 LPVOID pBase = LockResource(hGlobal);
1916 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
1920 /* try to load as incore resource */
1921 dwSignature = *((DWORD*) pBase);
1922 if ( dwSignature == MSFT_SIGNATURE)
1924 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
1926 else if ( dwSignature == SLTG_SIGNATURE)
1928 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
1932 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
1935 FreeResource( hGlobal );
1938 FreeLibrary(hinstDLL);
1945 ERR("Loading of typelib %s failed with error %ld\n",
1946 debugstr_w(pszFileName), GetLastError());
1951 /*================== ITypeLib(2) Methods ===================================*/
1953 /****************************************************************************
1954 * ITypeLib2_Constructor_MSFT
1956 * loading an MSFT typelib from an in-memory image
1958 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
1962 MSFT_Header tlbHeader;
1963 MSFT_SegDir tlbSegDir;
1964 ITypeLibImpl * pTypeLibImpl;
1966 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
1968 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
1969 if (!pTypeLibImpl) return NULL;
1971 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
1972 pTypeLibImpl->ref = 1;
1974 /* get pointer to beginning of typelib data */
1978 cx.pLibInfo = pTypeLibImpl;
1979 cx.length = dwTLBLength;
1982 MSFT_Read((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
1984 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
1985 if (memcmp(&tlbHeader.magic1,TLBMAGIC2,4)) {
1986 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
1989 /* there is a small amount of information here until the next important
1991 * the segment directory . Try to calculate the amount of data */
1992 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
1994 /* now read the segment directory */
1995 TRACE("read segment directory (at %ld)\n",lPSegDir);
1996 MSFT_Read((void*)&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
1997 cx.pTblDir = &tlbSegDir;
1999 /* just check two entries */
2000 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2002 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2003 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2007 /* now fill our internal data */
2008 /* TLIBATTR fields */
2009 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2010 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;
2011 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2012 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2013 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2014 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2016 /* name, eventually add to a hash table */
2017 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2020 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2021 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2023 if( tlbHeader.varflags & HELPDLLFLAG)
2026 MSFT_Read(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2027 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2030 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2033 if(tlbHeader.CustomDataOffset >= 0)
2035 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2038 /* fill in typedescriptions */
2039 if(tlbSegDir.pTypdescTab.length > 0)
2041 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2043 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2044 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2047 /* FIXME: add several sanity checks here */
2048 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2049 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2051 /* FIXME: check safearray */
2053 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2055 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2057 else if(td[0] == VT_CARRAY)
2059 /* array descr table here */
2060 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2062 else if(td[0] == VT_USERDEFINED)
2064 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2066 if(++i<cTD) MSFT_Read(td, sizeof(td), &cx, DO_NOT_SEEK);
2069 /* second time around to fill the array subscript info */
2072 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2073 if(tlbSegDir.pArrayDescriptions.offset>0)
2075 MSFT_Read(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2076 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2079 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2081 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2083 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2085 for(j = 0; j<td[2]; j++)
2087 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2088 sizeof(INT), &cx, DO_NOT_SEEK);
2089 MSFT_Read(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2090 sizeof(INT), &cx, DO_NOT_SEEK);
2095 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2096 ERR("didn't find array description data\n");
2101 /* imported type libs */
2102 if(tlbSegDir.pImpFiles.offset>0)
2104 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2105 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2108 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2110 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2111 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2112 MSFT_Read(&oGuid, sizeof(INT), &cx, offset);
2114 MSFT_Read(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2115 MSFT_Read(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2116 MSFT_Read(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2117 MSFT_Read(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2120 (*ppImpLib)->name = TLB_Alloc(size+1);
2121 MSFT_Read((*ppImpLib)->name, size, &cx, DO_NOT_SEEK);
2122 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2123 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & 0xfffffffc;
2125 ppImpLib = &(*ppImpLib)->next;
2130 if(tlbHeader.nrtypeinfos >= 0 )
2132 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2133 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2136 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2138 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2140 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2141 ppTI = &((*ppTI)->next);
2142 (pTypeLibImpl->TypeInfoCount)++;
2146 TRACE("(%p)\n", pTypeLibImpl);
2147 return (ITypeLib2*) pTypeLibImpl;
2151 static BSTR TLB_MultiByteToBSTR(char *ptr)
2157 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2158 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2159 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2160 ret = SysAllocString(nameW);
2161 HeapFree(GetProcessHeap(), 0, nameW);
2165 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2171 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2172 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2176 guid->Data4[0] = s >> 8;
2177 guid->Data4[1] = s & 0xff;
2180 for(i = 0; i < 6; i++) {
2181 memcpy(b, str + 24 + 2 * i, 2);
2182 guid->Data4[i + 2] = strtol(b, NULL, 16);
2187 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2194 bytelen = *(WORD*)ptr;
2195 if(bytelen == 0xffff) return 2;
2196 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2197 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2198 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2199 *pBstr = SysAllocStringLen(nameW, len);
2200 HeapFree(GetProcessHeap(), 0, nameW);
2204 static WORD SLTG_ReadStringA(char *ptr, char **str)
2209 bytelen = *(WORD*)ptr;
2210 if(bytelen == 0xffff) return 2;
2211 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2212 memcpy(*str, ptr + 2, bytelen);
2213 (*str)[bytelen] = '\0';
2217 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2219 char *ptr = pLibBlk;
2222 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2223 FIXME("libblk magic = %04x\n", w);
2228 if((w = *(WORD*)ptr) != 0xffff) {
2229 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2234 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2236 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2238 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2241 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2244 pTypeLibImpl->LibAttr.lcid = *(WORD*)ptr;
2247 ptr += 4; /* skip res12 */
2249 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2252 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2255 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2258 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2259 ptr += sizeof(GUID);
2261 return ptr - (char*)pLibBlk;
2264 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2267 TYPEDESC *pTD = &pElem->tdesc;
2269 /* Handle [in/out] first */
2270 if((*pType & 0xc000) == 0xc000)
2271 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2272 else if(*pType & 0x8000)
2273 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2274 else if(*pType & 0x4000)
2275 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2277 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2280 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2283 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2286 if((*pType & 0xe00) == 0xe00) {
2288 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2290 pTD = pTD->u.lptdesc;
2292 switch(*pType & 0x7f) {
2295 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2297 pTD = pTD->u.lptdesc;
2300 case VT_USERDEFINED:
2301 pTD->vt = VT_USERDEFINED;
2302 pTD->u.hreftype = *(++pType) / 4;
2308 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2311 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2313 pTD->vt = VT_CARRAY;
2314 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2316 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2317 pTD->u.lpadesc->cDims = pSA->cDims;
2318 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2319 pSA->cDims * sizeof(SAFEARRAYBOUND));
2321 pTD = &pTD->u.lpadesc->tdescElem;
2327 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2331 pTD->vt = VT_SAFEARRAY;
2332 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2334 pTD = pTD->u.lptdesc;
2338 pTD->vt = *pType & 0x7f;
2348 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2353 TLBRefType **ppRefType;
2355 if(pRef->magic != SLTG_REF_MAGIC) {
2356 FIXME("Ref magic = %x\n", pRef->magic);
2359 name = ( (char*)(&pRef->names) + pRef->number);
2361 ppRefType = &pTI->reflist;
2362 for(ref = 0; ref < pRef->number >> 3; ref++) {
2364 unsigned int lib_offs, type_num;
2366 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2367 sizeof(**ppRefType));
2369 name += SLTG_ReadStringA(name, &refname);
2370 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2371 FIXME("Can't sscanf ref\n");
2372 if(lib_offs != 0xffff) {
2373 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2376 if((*import)->offset == lib_offs)
2378 import = &(*import)->next;
2381 char fname[MAX_PATH+1];
2384 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2386 (*import)->offset = lib_offs;
2387 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2389 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2390 &(*import)->wVersionMajor,
2391 &(*import)->wVersionMinor,
2392 &(*import)->lcid, fname) != 4) {
2393 FIXME("can't sscanf ref %s\n",
2394 pNameTable + lib_offs + 40);
2396 len = strlen(fname);
2397 if(fname[len-1] != '#')
2398 FIXME("fname = %s\n", fname);
2399 fname[len-1] = '\0';
2400 (*import)->name = TLB_MultiByteToBSTR(fname);
2402 (*ppRefType)->pImpTLInfo = *import;
2403 } else { /* internal ref */
2404 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2406 (*ppRefType)->reference = ref;
2407 (*ppRefType)->index = type_num;
2409 HeapFree(GetProcessHeap(), 0, refname);
2410 ppRefType = &(*ppRefType)->next;
2412 if((BYTE)*name != SLTG_REF_MAGIC)
2413 FIXME("End of ref block magic = %x\n", *name);
2414 dump_TLBRefType(pTI->reflist);
2417 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2420 SLTG_ImplInfo *info;
2421 TLBImplType **ppImplType = &pTI->impltypelist;
2422 /* I don't really get this structure, usually it's 0x16 bytes
2423 long, but iuser.tlb contains some that are 0x18 bytes long.
2424 That's ok because we can use the next ptr to jump to the next
2425 one. But how do we know the length of the last one? The WORD
2426 at offs 0x8 might be the clue. For now I'm just assuming that
2427 the last one is the regular 0x16 bytes. */
2429 info = (SLTG_ImplInfo*)pBlk;
2431 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2432 sizeof(**ppImplType));
2433 (*ppImplType)->hRef = info->ref;
2434 (*ppImplType)->implflags = info->impltypeflags;
2435 pTI->TypeAttr.cImplTypes++;
2436 ppImplType = &(*ppImplType)->next;
2438 if(info->next == 0xffff)
2441 FIXME("Interface inheriting more than one interface\n");
2442 info = (SLTG_ImplInfo*)(pBlk + info->next);
2444 info++; /* see comment at top of function */
2448 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2451 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2452 SLTG_MemberHeader *pMemHeader;
2453 char *pFirstItem, *pNextItem;
2455 if(pTIHeader->href_table != 0xffffffff) {
2456 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2461 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2463 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2465 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2466 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2469 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2473 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2476 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2477 SLTG_MemberHeader *pMemHeader;
2478 SLTG_Function *pFunc;
2479 char *pFirstItem, *pNextItem;
2480 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2483 if(pTIHeader->href_table != 0xffffffff) {
2484 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2488 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2490 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2492 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2493 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2496 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2497 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2502 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2503 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2504 FIXME("func magic = %02x\n", pFunc->magic);
2507 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2508 sizeof(**ppFuncDesc));
2509 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2511 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2512 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2513 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2514 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2515 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2516 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2518 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2519 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2521 if(pFunc->retnextopt & 0x80)
2522 pType = &pFunc->rettype;
2524 pType = (WORD*)(pFirstItem + pFunc->rettype);
2527 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2529 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2530 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2531 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2532 (*ppFuncDesc)->pParamDesc =
2533 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2534 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2536 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2538 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2539 char *paramName = pNameTable + *pArg;
2541 /* If arg type follows then paramName points to the 2nd
2542 letter of the name, else the next WORD is an offset to
2543 the arg type and paramName points to the first letter.
2544 So let's take one char off paramName and see if we're
2545 pointing at an alpha-numeric char. However if *pArg is
2546 0xffff or 0xfffe then the param has no name, the former
2547 meaning that the next WORD is the type, the latter
2548 meaning the the next WORD is an offset to the type. */
2553 else if(*pArg == 0xfffe) {
2557 else if(!isalnum(*(paramName-1)))
2562 if(HaveOffs) { /* the next word is an offset to type */
2563 pType = (WORD*)(pFirstItem + *pArg);
2564 SLTG_DoType(pType, pFirstItem,
2565 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2570 pArg = SLTG_DoType(pArg, pFirstItem,
2571 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2574 /* Are we an optional param ? */
2575 if((*ppFuncDesc)->funcdesc.cParams - param <=
2576 (*ppFuncDesc)->funcdesc.cParamsOpt)
2577 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2580 (*ppFuncDesc)->pParamDesc[param].Name =
2581 TLB_MultiByteToBSTR(paramName);
2585 ppFuncDesc = &((*ppFuncDesc)->next);
2586 if(pFunc->next == 0xffff) break;
2588 pTI->TypeAttr.cFuncs = num;
2589 dump_TLBFuncDesc(pTI->funclist);
2590 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2593 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2596 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2597 SLTG_MemberHeader *pMemHeader;
2598 SLTG_RecordItem *pItem;
2600 TLBVarDesc **ppVarDesc = &pTI->varlist;
2605 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2607 pFirstItem = (char*)(pMemHeader + 1);
2608 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2609 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2610 if(pItem->magic != SLTG_RECORD_MAGIC) {
2611 FIXME("record magic = %02x\n", pItem->magic);
2614 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2615 sizeof(**ppVarDesc));
2616 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2617 (*ppVarDesc)->vardesc.memid = pItem->memid;
2618 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2619 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2621 if(pItem->typepos == 0x02)
2622 pType = &pItem->type;
2623 else if(pItem->typepos == 0x00)
2624 pType = (WORD*)(pFirstItem + pItem->type);
2626 FIXME("typepos = %02x\n", pItem->typepos);
2630 SLTG_DoType(pType, pFirstItem,
2631 &(*ppVarDesc)->vardesc.elemdescVar);
2633 /* FIXME("helpcontext, helpstring\n"); */
2635 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2637 ppVarDesc = &((*ppVarDesc)->next);
2638 if(pItem->next == 0xffff) break;
2640 pTI->TypeAttr.cVars = num;
2641 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2644 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
2647 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2648 SLTG_MemberHeader *pMemHeader;
2649 SLTG_EnumItem *pItem;
2651 TLBVarDesc **ppVarDesc = &pTI->varlist;
2654 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2656 pFirstItem = (char*)(pMemHeader + 1);
2657 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
2658 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
2659 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
2660 FIXME("enumitem magic = %04x\n", pItem->magic);
2663 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2664 sizeof(**ppVarDesc));
2665 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2666 (*ppVarDesc)->vardesc.memid = pItem->memid;
2667 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2669 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2670 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2671 *(INT*)(pItem->value + pFirstItem);
2672 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
2673 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2674 /* FIXME("helpcontext, helpstring\n"); */
2676 ppVarDesc = &((*ppVarDesc)->next);
2677 if(pItem->next == 0xffff) break;
2679 pTI->TypeAttr.cVars = num;
2680 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2683 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
2684 managable copy of it into this */
2697 } SLTG_InternalOtherTypeInfo;
2699 /****************************************************************************
2700 * ITypeLib2_Constructor_SLTG
2702 * loading a SLTG typelib from an in-memory image
2704 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
2706 ITypeLibImpl *pTypeLibImpl;
2707 SLTG_Header *pHeader;
2708 SLTG_BlkEntry *pBlkEntry;
2712 LPVOID pBlk, pFirstBlk;
2713 SLTG_LibBlk *pLibBlk;
2714 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
2715 char *pAfterOTIBlks = NULL;
2716 char *pNameTable, *ptr;
2719 ITypeInfoImpl **ppTypeInfoImpl;
2721 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2723 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2724 if (!pTypeLibImpl) return NULL;
2726 ICOM_VTBL(pTypeLibImpl) = &tlbvt;
2727 pTypeLibImpl->ref = 1;
2732 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
2733 pHeader->nrOfFileBlks );
2734 if (memcmp(&pHeader->SLTG_magic, TLBMAGIC1, 4)) {
2735 FIXME("Header type magic 0x%08lx not supported.\n",
2736 pHeader->SLTG_magic);
2740 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
2741 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
2743 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
2744 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
2746 /* Next we have a magic block */
2747 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
2749 /* Let's see if we're still in sync */
2750 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
2751 sizeof(SLTG_COMPOBJ_MAGIC))) {
2752 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
2755 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
2756 sizeof(SLTG_DIR_MAGIC))) {
2757 FIXME("dir magic = %s\n", pMagic->dir_magic);
2761 pIndex = (SLTG_Index*)(pMagic+1);
2763 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
2765 pFirstBlk = (LPVOID)(pPad9 + 1);
2767 /* We'll set up a ptr to the main library block, which is the last one. */
2769 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2770 pBlkEntry[order].next != 0;
2771 order = pBlkEntry[order].next - 1, i++) {
2772 pBlk += pBlkEntry[order].len;
2776 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
2778 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
2783 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
2785 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2786 sizeof(*pOtherTypeInfoBlks) *
2787 pTypeLibImpl->TypeInfoCount);
2790 ptr = (char*)pLibBlk + len;
2792 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
2796 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
2798 w = *(WORD*)(ptr + 2);
2801 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
2803 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
2804 pOtherTypeInfoBlks[i].index_name[w] = '\0';
2806 w = *(WORD*)(ptr + 4 + len);
2808 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
2810 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
2812 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
2813 pOtherTypeInfoBlks[i].other_name[w] = '\0';
2815 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
2816 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
2817 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
2819 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
2821 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
2824 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
2825 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
2826 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
2827 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
2828 len += sizeof(SLTG_OtherTypeInfo);
2832 pAfterOTIBlks = ptr;
2834 /* Skip this WORD and get the next DWORD */
2835 len = *(DWORD*)(pAfterOTIBlks + 2);
2837 /* Now add this to pLibBLk and then add 0x216, sprinkle a bit a
2838 magic dust and we should be pointing at the beginning of the name
2841 pNameTable = (char*)pLibBlk + len + 0x216;
2845 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
2847 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
2850 /* Hopefully we now have enough ptrs set up to actually read in
2851 some TypeInfos. It's not clear which order to do them in, so
2852 I'll just follow the links along the BlkEntry chain and read
2853 them in in the order in which they're in the file */
2855 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
2857 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
2858 pBlkEntry[order].next != 0;
2859 order = pBlkEntry[order].next - 1, i++) {
2861 SLTG_TypeInfoHeader *pTIHeader;
2862 SLTG_TypeInfoTail *pTITail;
2864 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
2865 pOtherTypeInfoBlks[i].index_name)) {
2866 FIXME("Index strings don't match\n");
2871 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
2872 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
2875 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
2876 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
2877 (*ppTypeInfoImpl)->index = i;
2878 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
2879 pOtherTypeInfoBlks[i].name_offs +
2881 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
2882 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
2884 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
2885 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
2886 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
2887 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
2888 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
2890 if((pTIHeader->typeflags1 & 7) != 2)
2891 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
2892 if(pTIHeader->typeflags3 != 2)
2893 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
2895 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
2896 debugstr_w((*ppTypeInfoImpl)->Name),
2897 typekind_desc[pTIHeader->typekind],
2898 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
2899 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
2901 switch(pTIHeader->typekind) {
2903 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
2907 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
2910 case TKIND_INTERFACE:
2911 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
2915 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
2919 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
2925 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
2926 but we've already set those */
2927 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
2928 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
2929 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
2931 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
2932 pBlk += pBlkEntry[order].len;
2935 if(i != pTypeLibImpl->TypeInfoCount) {
2936 FIXME("Somehow processed %d TypeInfos\n", i);
2940 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
2941 return (ITypeLib2*)pTypeLibImpl;
2944 /* ITypeLib::QueryInterface
2946 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
2951 ICOM_THIS( ITypeLibImpl, iface);
2953 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
2956 if(IsEqualIID(riid, &IID_IUnknown) ||
2957 IsEqualIID(riid,&IID_ITypeLib)||
2958 IsEqualIID(riid,&IID_ITypeLib2))
2965 ITypeLib2_AddRef(iface);
2966 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
2969 TRACE("-- Interface: E_NOINTERFACE\n");
2970 return E_NOINTERFACE;
2975 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
2977 ICOM_THIS( ITypeLibImpl, iface);
2979 TRACE("(%p)->ref is %u\n",This, This->ref);
2981 return ++(This->ref);
2984 /* ITypeLib::Release
2986 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
2988 ICOM_THIS( ITypeLibImpl, iface);
2992 TRACE("(%p)->(%u)\n",This, This->ref);
2996 /* fixme destroy child objects */
2998 TRACE(" destroying ITypeLib(%p)\n",This);
3002 SysFreeString(This->Name);
3006 if (This->DocString)
3008 SysFreeString(This->DocString);
3009 This->DocString = NULL;
3014 SysFreeString(This->HelpFile);
3015 This->HelpFile = NULL;
3018 if (This->HelpStringDll)
3020 SysFreeString(This->HelpStringDll);
3021 This->HelpStringDll = NULL;
3024 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3025 HeapFree(GetProcessHeap(),0,This);
3032 /* ITypeLib::GetTypeInfoCount
3034 * Returns the number of type descriptions in the type library
3036 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3038 ICOM_THIS( ITypeLibImpl, iface);
3039 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3040 return This->TypeInfoCount;
3043 /* ITypeLib::GetTypeInfo
3045 * retrieves the specified type description in the library.
3047 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3050 ITypeInfo **ppTInfo)
3054 ICOM_THIS( ITypeLibImpl, iface);
3055 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3057 TRACE("(%p)->(index=%d) \n", This, index);
3059 if (!ppTInfo) return E_INVALIDARG;
3061 /* search element n in list */
3062 for(i=0; i < index; i++)
3064 pTypeInfo = pTypeInfo->next;
3067 TRACE("-- element not found\n");
3068 return TYPE_E_ELEMENTNOTFOUND;
3072 *ppTInfo = (ITypeInfo *) pTypeInfo;
3074 ITypeInfo_AddRef(*ppTInfo);
3075 TRACE("-- found (%p)\n",*ppTInfo);
3080 /* ITypeLibs::GetTypeInfoType
3082 * Retrieves the type of a type description.
3084 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3089 ICOM_THIS( ITypeLibImpl, iface);
3091 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3093 TRACE("(%p) index %d \n",This, index);
3095 if(!pTKind) return E_INVALIDARG;
3097 /* search element n in list */
3098 for(i=0; i < index; i++)
3102 TRACE("-- element not found\n");
3103 return TYPE_E_ELEMENTNOTFOUND;
3105 pTInfo = pTInfo->next;
3108 *pTKind = pTInfo->TypeAttr.typekind;
3109 TRACE("-- found Type (%d)\n", *pTKind);
3113 /* ITypeLib::GetTypeInfoOfGuid
3115 * Retrieves the type description that corresponds to the specified GUID.
3118 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3121 ITypeInfo **ppTInfo)
3123 ICOM_THIS( ITypeLibImpl, iface);
3124 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3126 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3128 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3130 /* search linked list for guid */
3131 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3133 pTypeInfo = pTypeInfo->next;
3137 /* end of list reached */
3138 TRACE("-- element not found\n");
3139 return TYPE_E_ELEMENTNOTFOUND;
3143 TRACE("-- found (%p, %s)\n",
3145 debugstr_w(pTypeInfo->Name));
3147 *ppTInfo = (ITypeInfo*)pTypeInfo;
3148 ITypeInfo_AddRef(*ppTInfo);
3152 /* ITypeLib::GetLibAttr
3154 * Retrieves the structure that contains the library's attributes.
3157 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3159 LPTLIBATTR *ppTLibAttr)
3161 ICOM_THIS( ITypeLibImpl, iface);
3162 TRACE("(%p)\n",This);
3163 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3164 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3168 /* ITypeLib::GetTypeComp
3170 * Enables a client compiler to bind to a library's types, variables,
3171 * constants, and global functions.
3174 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3176 ITypeComp **ppTComp)
3178 ICOM_THIS( ITypeLibImpl, iface);
3179 FIXME("(%p): stub!\n",This);
3183 /* ITypeLib::GetDocumentation
3185 * Retrieves the library's documentation string, the complete Help file name
3186 * and path, and the context identifier for the library Help topic in the Help
3190 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3194 BSTR *pBstrDocString,
3195 DWORD *pdwHelpContext,
3196 BSTR *pBstrHelpFile)
3198 ICOM_THIS( ITypeLibImpl, iface);
3200 HRESULT result = E_INVALIDARG;
3205 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3207 pBstrName, pBstrDocString,
3208 pdwHelpContext, pBstrHelpFile);
3212 /* documentation for the typelib */
3213 if(pBstrName && This->Name)
3215 *pBstrName = SysAllocString(This->Name);
3217 if (!(*pBstrName)) return STG_E_INSUFFICIENTMEMORY;
3219 if(pBstrDocString && This->DocString)
3221 *pBstrDocString = SysAllocString(This->DocString);
3223 if (!(*pBstrDocString)) return STG_E_INSUFFICIENTMEMORY;
3228 *pdwHelpContext = This->dwHelpContext;
3230 if(pBstrHelpFile && This->HelpFile)
3232 *pBstrHelpFile = SysAllocString(This->HelpFile);
3234 if (!(*pBstrHelpFile)) return STG_E_INSUFFICIENTMEMORY;
3241 /* for a typeinfo */
3242 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3244 if(SUCCEEDED(result))
3246 result = ITypeInfo_GetDocumentation(pTInfo,
3250 pdwHelpContext, pBstrHelpFile);
3252 ITypeInfo_Release(pTInfo);
3260 * Indicates whether a passed-in string contains the name of a type or member
3261 * described in the library.
3264 static HRESULT WINAPI ITypeLib2_fnIsName(
3270 ICOM_THIS( ITypeLibImpl, iface);
3271 ITypeInfoImpl *pTInfo;
3272 TLBFuncDesc *pFInfo;
3275 UINT nNameBufLen = SysStringLen(szNameBuf);
3277 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3281 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3282 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3283 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3284 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3285 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3286 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3287 goto ITypeLib2_fnIsName_exit;
3289 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3290 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3295 ITypeLib2_fnIsName_exit:
3296 TRACE("(%p)slow! search for %s: %s found!\n", This,
3297 debugstr_w(szNameBuf), *pfName?"NOT":"");
3302 /* ITypeLib::FindName
3304 * Finds occurrences of a type description in a type library. This may be used
3305 * to quickly verify that a name exists in a type library.
3308 static HRESULT WINAPI ITypeLib2_fnFindName(
3312 ITypeInfo **ppTInfo,
3316 ICOM_THIS( ITypeLibImpl, iface);
3317 ITypeInfoImpl *pTInfo;
3318 TLBFuncDesc *pFInfo;
3322 UINT nNameBufLen = SysStringLen(szNameBuf);
3324 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3325 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3326 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3327 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3328 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3329 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3330 goto ITypeLib2_fnFindName_exit;
3332 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3333 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3335 ITypeLib2_fnFindName_exit:
3336 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3337 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3340 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3341 This, *pcFound, debugstr_w(szNameBuf), j);
3348 /* ITypeLib::ReleaseTLibAttr
3350 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3353 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3355 TLIBATTR *pTLibAttr)
3357 ICOM_THIS( ITypeLibImpl, iface);
3358 TRACE("freeing (%p)\n",This);
3359 HeapFree(GetProcessHeap(),0,pTLibAttr);
3363 /* ITypeLib2::GetCustData
3365 * gets the custom data
3367 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3372 ICOM_THIS( ITypeLibImpl, iface);
3373 TLBCustData *pCData;
3375 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3377 if( IsEqualIID(guid, &pCData->guid)) break;
3380 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3384 VariantInit( pVarVal);
3385 VariantCopy( pVarVal, &pCData->data);
3388 return E_INVALIDARG; /* FIXME: correct? */
3391 /* ITypeLib2::GetLibStatistics
3393 * Returns statistics about a type library that are required for efficient
3394 * sizing of hash tables.
3397 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3399 ULONG *pcUniqueNames,
3400 ULONG *pcchUniqueNames)
3402 ICOM_THIS( ITypeLibImpl, iface);
3404 FIXME("(%p): stub!\n", This);
3406 if(pcUniqueNames) *pcUniqueNames=1;
3407 if(pcchUniqueNames) *pcchUniqueNames=1;
3411 /* ITypeLib2::GetDocumentation2
3413 * Retrieves the library's documentation string, the complete Help file name
3414 * and path, the localization context to use, and the context ID for the
3415 * library Help topic in the Help file.
3418 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3422 BSTR *pbstrHelpString,
3423 DWORD *pdwHelpStringContext,
3424 BSTR *pbstrHelpStringDll)
3426 ICOM_THIS( ITypeLibImpl, iface);
3430 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3432 /* the help string should be obtained from the helpstringdll,
3433 * using the _DLLGetDocumentation function, based on the supplied
3434 * lcid. Nice to do sometime...
3438 /* documentation for the typelib */
3440 *pbstrHelpString=SysAllocString(This->DocString);
3441 if(pdwHelpStringContext)
3442 *pdwHelpStringContext=This->dwHelpContext;
3443 if(pbstrHelpStringDll)
3444 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3450 /* for a typeinfo */
3451 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3453 if(SUCCEEDED(result))
3455 ITypeInfo2 * pTInfo2;
3456 result = ITypeInfo_QueryInterface(pTInfo,
3458 (LPVOID*) &pTInfo2);
3460 if(SUCCEEDED(result))
3462 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3466 pdwHelpStringContext,
3467 pbstrHelpStringDll);
3469 ITypeInfo2_Release(pTInfo2);
3472 ITypeInfo_Release(pTInfo);
3478 /* ITypeLib2::GetAllCustData
3480 * Gets all custom data items for the library.
3483 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3485 CUSTDATA *pCustData)
3487 ICOM_THIS( ITypeLibImpl, iface);
3488 TLBCustData *pCData;
3490 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3491 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3492 if(pCustData->prgCustData ){
3493 pCustData->cCustData=This->ctCustData;
3494 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3495 pCustData->prgCustData[i].guid=pCData->guid;
3496 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3499 ERR(" OUT OF MEMORY! \n");
3500 return E_OUTOFMEMORY;
3505 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3506 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3507 ITypeLib2_fnQueryInterface,
3509 ITypeLib2_fnRelease,
3510 ITypeLib2_fnGetTypeInfoCount,
3511 ITypeLib2_fnGetTypeInfo,
3512 ITypeLib2_fnGetTypeInfoType,
3513 ITypeLib2_fnGetTypeInfoOfGuid,
3514 ITypeLib2_fnGetLibAttr,
3515 ITypeLib2_fnGetTypeComp,
3516 ITypeLib2_fnGetDocumentation,
3518 ITypeLib2_fnFindName,
3519 ITypeLib2_fnReleaseTLibAttr,
3521 ITypeLib2_fnGetCustData,
3522 ITypeLib2_fnGetLibStatistics,
3523 ITypeLib2_fnGetDocumentation2,
3524 ITypeLib2_fnGetAllCustData
3527 /*================== ITypeInfo(2) Methods ===================================*/
3528 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
3530 ITypeInfoImpl * pTypeInfoImpl;
3532 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
3535 ICOM_VTBL(pTypeInfoImpl) = &tinfvt;
3536 pTypeInfoImpl->ref=1;
3538 TRACE("(%p)\n", pTypeInfoImpl);
3539 return (ITypeInfo2*) pTypeInfoImpl;
3542 /* ITypeInfo::QueryInterface
3544 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
3549 ICOM_THIS( ITypeLibImpl, iface);
3551 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3554 if(IsEqualIID(riid, &IID_IUnknown) ||
3555 IsEqualIID(riid,&IID_ITypeInfo)||
3556 IsEqualIID(riid,&IID_ITypeInfo2))
3560 ITypeInfo_AddRef(iface);
3561 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3564 TRACE("-- Interface: E_NOINTERFACE\n");
3565 return E_NOINTERFACE;
3568 /* ITypeInfo::AddRef
3570 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
3572 ICOM_THIS( ITypeInfoImpl, iface);
3576 TRACE("(%p)->ref is %u\n",This, This->ref);
3580 /* ITypeInfo::Release
3582 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
3584 ICOM_THIS( ITypeInfoImpl, iface);
3588 TRACE("(%p)->(%u)\n",This, This->ref);
3592 FIXME("destroy child objects\n");
3594 TRACE("destroying ITypeInfo(%p)\n",This);
3597 SysFreeString(This->Name);
3601 if (This->DocString)
3603 SysFreeString(This->DocString);
3604 This->DocString = 0;
3609 ITypeInfo_Release((ITypeInfo*)This->next);
3612 HeapFree(GetProcessHeap(),0,This);
3618 /* ITypeInfo::GetTypeAttr
3620 * Retrieves a TYPEATTR structure that contains the attributes of the type
3624 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
3625 LPTYPEATTR *ppTypeAttr)
3627 ICOM_THIS( ITypeInfoImpl, iface);
3628 TRACE("(%p)\n",This);
3629 /* FIXME: must do a copy here */
3630 *ppTypeAttr=&This->TypeAttr;
3634 /* ITypeInfo::GetTypeComp
3636 * Retrieves the ITypeComp interface for the type description, which enables a
3637 * client compiler to bind to the type description's members.
3640 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
3641 ITypeComp * *ppTComp)
3643 ICOM_THIS( ITypeInfoImpl, iface);
3644 FIXME("(%p) stub!\n", This);
3648 /* ITypeInfo::GetFuncDesc
3650 * Retrieves the FUNCDESC structure that contains information about a
3651 * specified function.
3654 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
3655 LPFUNCDESC *ppFuncDesc)
3657 ICOM_THIS( ITypeInfoImpl, iface);
3659 TLBFuncDesc * pFDesc;
3660 TRACE("(%p) index %d\n", This, index);
3661 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
3664 /* FIXME: must do a copy here */
3665 *ppFuncDesc=&pFDesc->funcdesc;
3668 return E_INVALIDARG;
3671 /* ITypeInfo::GetVarDesc
3673 * Retrieves a VARDESC structure that describes the specified variable.
3676 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
3677 LPVARDESC *ppVarDesc)
3679 ICOM_THIS( ITypeInfoImpl, iface);
3681 TLBVarDesc * pVDesc;
3682 TRACE("(%p) index %d\n", This, index);
3683 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
3686 /* FIXME: must do a copy here */
3687 *ppVarDesc=&pVDesc->vardesc;
3690 return E_INVALIDARG;
3693 /* ITypeInfo_GetNames
3695 * Retrieves the variable with the specified member ID (or the name of the
3696 * property or method and its parameters) that correspond to the specified
3699 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
3700 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
3702 ICOM_THIS( ITypeInfoImpl, iface);
3703 TLBFuncDesc * pFDesc;
3704 TLBVarDesc * pVDesc;
3706 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
3707 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
3710 /* function found, now return function and parameter names */
3711 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
3714 *rgBstrNames=SysAllocString(pFDesc->Name);
3716 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
3722 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
3725 *rgBstrNames=SysAllocString(pVDesc->Name);
3730 if(This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes )
3732 /* recursive search */
3735 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
3737 if(SUCCEEDED(result))
3739 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
3740 ITypeInfo_Release(pTInfo);
3743 WARN("Could not search inherited interface!\n");
3747 WARN("no names found\n");
3750 return TYPE_E_ELEMENTNOTFOUND;
3757 /* ITypeInfo::GetRefTypeOfImplType
3759 * If a type description describes a COM class, it retrieves the type
3760 * description of the implemented interface types. For an interface,
3761 * GetRefTypeOfImplType returns the type information for inherited interfaces,
3765 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
3770 ICOM_THIS( ITypeInfoImpl, iface);
3772 TLBImplType *pImpl = This->impltypelist;
3774 TRACE("(%p) index %d\n", This, index);
3775 dump_TypeInfo(This);
3779 /* only valid on dual interfaces;
3780 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
3782 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
3784 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
3785 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
3791 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3792 *pRefType = pImpl->hRef;
3797 /* get element n from linked list */
3798 for(i=0; pImpl && i<index; i++)
3800 pImpl = pImpl->next;
3803 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
3805 *pRefType = pImpl->hRef;
3807 TRACE("-- 0x%08lx\n", pImpl->hRef );
3814 /* ITypeInfo::GetImplTypeFlags
3816 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
3817 * or base interface in a type description.
3819 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
3820 UINT index, INT *pImplTypeFlags)
3822 ICOM_THIS( ITypeInfoImpl, iface);
3826 TRACE("(%p) index %d\n", This, index);
3827 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
3828 i++, pImpl=pImpl->next)
3830 if(i==index && pImpl){
3831 *pImplTypeFlags=pImpl->implflags;
3835 return TYPE_E_ELEMENTNOTFOUND;
3839 * Maps between member names and member IDs, and parameter names and
3842 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
3843 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
3845 ICOM_THIS( ITypeInfoImpl, iface);
3846 TLBFuncDesc * pFDesc;
3847 TLBVarDesc * pVDesc;
3850 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
3852 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
3854 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
3855 if(cNames) *pMemId=pFDesc->funcdesc.memid;
3856 for(i=1; i < cNames; i++){
3857 for(j=0; j<pFDesc->funcdesc.cParams; j++)
3858 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
3860 if( j<pFDesc->funcdesc.cParams)
3863 ret=DISP_E_UNKNOWNNAME;
3868 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
3869 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
3870 if(cNames) *pMemId=pVDesc->vardesc.memid;
3874 /* not found, see if this is and interface with an inheritance */
3875 if(This->TypeAttr.typekind==TKIND_INTERFACE &&
3876 This->TypeAttr.cImplTypes ){
3877 /* recursive search */
3879 ret=ITypeInfo_GetRefTypeInfo(iface,
3880 This->impltypelist->hRef, &pTInfo);
3882 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
3883 ITypeInfo_Release(pTInfo);
3886 WARN("Could not search inherited interface!\n");
3888 WARN("no names found\n");
3889 return DISP_E_UNKNOWNNAME;
3892 /* ITypeInfo::Invoke
3894 * Invokes a method, or accesses a property of an object, that implements the
3895 * interface described by the type description.
3897 static DWORD _invoke(LPVOID func,CALLCONV callconv, int nrargs, DWORD *args) {
3900 if (TRACE_ON(ole)) {
3902 MESSAGE("Calling %p(",func);
3903 for (i=0;i<nrargs;i++) MESSAGE("%08lx,",args[i]);
3912 DWORD (WINAPI *xfunc)() = func;
3917 DWORD (WINAPI *xfunc)(DWORD) = func;
3918 res = xfunc(args[0]);
3922 DWORD (WINAPI *xfunc)(DWORD,DWORD) = func;
3923 res = xfunc(args[0],args[1]);
3927 DWORD (WINAPI *xfunc)(DWORD,DWORD,DWORD) = func;
3928 res = xfunc(args[0],args[1],args[2]);
3932 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
3938 FIXME("unsupported calling convention %d\n",callconv);
3942 TRACE("returns %08lx\n",res);
3946 static HRESULT WINAPI ITypeInfo_fnInvoke(
3951 DISPPARAMS *pDispParams,
3952 VARIANT *pVarResult,
3953 EXCEPINFO *pExcepInfo,
3956 ICOM_THIS( ITypeInfoImpl, iface);
3957 TLBFuncDesc * pFDesc;
3958 TLBVarDesc * pVDesc;
3961 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
3962 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
3964 dump_DispParms(pDispParams);
3966 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
3967 if (pFDesc->funcdesc.memid == memid) {
3968 if (pFDesc->funcdesc.invkind & dwFlags)
3972 dump_TLBFuncDescOne(pFDesc);
3973 switch (pFDesc->funcdesc.funckind) {
3974 case FUNC_PUREVIRTUAL:
3975 case FUNC_VIRTUAL: {
3977 DWORD *args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*(pFDesc->funcdesc.cParams+1));
3978 DWORD *args2 = (DWORD*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*(pFDesc->funcdesc.cParams));
3979 args[0] = (DWORD)pIUnk;
3981 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
3982 if (i<pDispParams->cArgs) {
3983 TRACE("set %d to disparg type %d vs %d\n",i,
3984 V_VT(&pDispParams->rgvarg[pDispParams->cArgs-i-1]),
3985 pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt
3987 args[i+1] = V_UNION(&pDispParams->rgvarg[pDispParams->cArgs-i-1],lVal);
3989 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
3990 TRACE("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
3991 /*FIXME: give pointers for the rest, so propertyget works*/
3992 args[i+1] = (DWORD)&args2[i];
3994 /* If pointer to variant, pass reference to variant
3995 * in result variant array.
3997 if ((tdesc->vt == VT_PTR) &&
3998 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4001 args[i+1] = (DWORD)(pVarResult+(i-pDispParams->cArgs));
4004 if (pFDesc->funcdesc.cParamsOpt)
4005 FIXME("Does not support optional parameters (%d)\n",
4006 pFDesc->funcdesc.cParamsOpt
4009 res = _invoke((*(DWORD***)pIUnk)[pFDesc->funcdesc.oVft/4],
4010 pFDesc->funcdesc.callconv,
4011 pFDesc->funcdesc.cParams+1,
4014 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4015 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4016 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4017 /* If we are a pointer to a variant, we are done already */
4018 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4021 VariantInit(&pVarResult[i]);
4022 V_UNION(pVarResult+i,intVal) = args2[i+pDispParams->cArgs];
4024 if (tdesc->vt == VT_PTR)
4025 tdesc = tdesc->u.lptdesc;
4026 V_VT(pVarResult+i) = tdesc->vt;
4028 /* HACK: VB5 likes this.
4029 * I do not know why. There is 1 example in MSDN which uses
4030 * this which appears broken (mixes int vals and
4033 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4034 V_VT(pVarResult+i) = VT_DISPATCH;
4035 TRACE("storing into variant: [%d]\n", i);
4036 dump_Variant(pVarResult+i);
4039 HeapFree(GetProcessHeap(),0,args2);
4040 HeapFree(GetProcessHeap(),0,args);
4043 case FUNC_DISPATCH: {
4047 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4049 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4052 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4053 hr = IDispatch_Invoke(
4054 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4055 pVarResult,pExcepInfo,pArgErr
4058 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4059 IDispatch_Release(disp);
4063 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4067 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4068 if (pVDesc->vardesc.memid == memid) {
4069 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4070 dump_TLBVarDesc(pVDesc);
4075 /* not found, look for it in inherited interfaces */
4076 if (This->TypeAttr.typekind==TKIND_INTERFACE && This->TypeAttr.cImplTypes) {
4077 /* recursive search */
4080 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4082 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4083 ITypeInfo_Release(pTInfo);
4086 WARN("Could not search inherited interface!\n");
4088 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4089 return DISP_E_MEMBERNOTFOUND;
4092 /* ITypeInfo::GetDocumentation
4094 * Retrieves the documentation string, the complete Help file name and path,
4095 * and the context ID for the Help topic for a specified type description.
4097 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4098 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4099 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4101 ICOM_THIS( ITypeInfoImpl, iface);
4102 TLBFuncDesc * pFDesc;
4103 TLBVarDesc * pVDesc;
4104 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4105 " HelpContext(%p) HelpFile(%p)\n",
4106 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4107 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4109 *pBstrName=SysAllocString(This->Name);
4111 *pBstrDocString=SysAllocString(This->DocString);
4113 *pdwHelpContext=This->dwHelpContext;
4115 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4117 }else {/* for a member */
4118 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4119 if(pFDesc->funcdesc.memid==memid){
4121 *pBstrName = SysAllocString(pFDesc->Name);
4123 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4125 *pdwHelpContext=pFDesc->helpcontext;
4128 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4129 if(pVDesc->vardesc.memid==memid){
4130 FIXME("Not implemented\n");
4134 return TYPE_E_ELEMENTNOTFOUND;
4137 /* ITypeInfo::GetDllEntry
4139 * Retrieves a description or specification of an entry point for a function
4142 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4143 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4146 ICOM_THIS( ITypeInfoImpl, iface);
4147 FIXME("(%p) stub!\n", This);
4151 /* ITypeInfo::GetRefTypeInfo
4153 * If a type description references other type descriptions, it retrieves
4154 * the referenced type descriptions.
4156 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4159 ITypeInfo **ppTInfo)
4161 ICOM_THIS( ITypeInfoImpl, iface);
4162 HRESULT result = E_FAIL;
4165 if (hRefType == -1 &&
4166 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4167 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4169 /* when we meet a DUAL dispinterface, we must create the interface
4172 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4175 /* the interface version contains the same information as the dispinterface
4176 * copy the contents of the structs.
4178 *pTypeInfoImpl = *This;
4179 pTypeInfoImpl->ref = 1;
4181 /* change the type to interface */
4182 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4184 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4186 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4191 TLBRefType *pRefType;
4192 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4193 if(pRefType->reference == hRefType)
4197 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4198 if(pRefType && hRefType != -1) {
4201 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
4203 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
4205 if(pRefType->pImpTLInfo->pImpTypeLib) {
4206 TRACE("typeinfo in imported typelib that is already loaded\n");
4207 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
4208 ITypeLib2_AddRef((ITypeLib*) pTLib);
4211 TRACE("typeinfo in imported typelib that isn't already loaded\n");
4212 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
4213 pRefType->pImpTLInfo->wVersionMajor,
4214 pRefType->pImpTLInfo->wVersionMinor,
4215 pRefType->pImpTLInfo->lcid,
4218 if(!SUCCEEDED(result)) {
4219 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
4220 result=LoadTypeLib(libnam, &pTLib);
4221 SysFreeString(libnam);
4223 if(SUCCEEDED(result)) {
4224 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
4225 ITypeLib2_AddRef(pTLib);
4229 if(SUCCEEDED(result)) {
4230 if(pRefType->index == TLB_REF_USE_GUID)
4231 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
4235 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
4241 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
4242 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
4246 /* ITypeInfo::AddressOfMember
4248 * Retrieves the addresses of static functions or variables, such as those
4251 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
4252 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
4254 ICOM_THIS( ITypeInfoImpl, iface);
4255 FIXME("(%p) stub!\n", This);
4259 /* ITypeInfo::CreateInstance
4261 * Creates a new instance of a type that describes a component object class
4264 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
4265 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
4267 ICOM_THIS( ITypeInfoImpl, iface);
4268 FIXME("(%p) stub!\n", This);
4272 /* ITypeInfo::GetMops
4274 * Retrieves marshaling information.
4276 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
4279 ICOM_THIS( ITypeInfoImpl, iface);
4280 FIXME("(%p) stub!\n", This);
4284 /* ITypeInfo::GetContainingTypeLib
4286 * Retrieves the containing type library and the index of the type description
4287 * within that type library.
4289 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
4290 ITypeLib * *ppTLib, UINT *pIndex)
4292 ICOM_THIS( ITypeInfoImpl, iface);
4294 return E_INVALIDARG;
4295 *ppTLib=(LPTYPELIB )(This->pTypeLib);
4296 *pIndex=This->index;
4297 ITypeLib2_AddRef(*ppTLib);
4298 TRACE("(%p) returns (%p) index %d!\n", This, *ppTLib, *pIndex);
4302 /* ITypeInfo::ReleaseTypeAttr
4304 * Releases a TYPEATTR previously returned by GetTypeAttr.
4307 static HRESULT WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
4308 TYPEATTR* pTypeAttr)
4310 ICOM_THIS( ITypeInfoImpl, iface);
4311 TRACE("(%p)->(%p)\n", This, pTypeAttr);
4315 /* ITypeInfo::ReleaseFuncDesc
4317 * Releases a FUNCDESC previously returned by GetFuncDesc. *
4319 static HRESULT WINAPI ITypeInfo_fnReleaseFuncDesc(
4321 FUNCDESC *pFuncDesc)
4323 ICOM_THIS( ITypeInfoImpl, iface);
4324 TRACE("(%p)->(%p)\n", This, pFuncDesc);
4328 /* ITypeInfo::ReleaseVarDesc
4330 * Releases a VARDESC previously returned by GetVarDesc.
4332 static HRESULT WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
4335 ICOM_THIS( ITypeInfoImpl, iface);
4336 TRACE("(%p)->(%p)\n", This, pVarDesc);
4340 /* ITypeInfo2::GetTypeKind
4342 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
4345 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
4346 TYPEKIND *pTypeKind)
4348 ICOM_THIS( ITypeInfoImpl, iface);
4349 *pTypeKind=This->TypeAttr.typekind;
4350 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
4354 /* ITypeInfo2::GetTypeFlags
4356 * Returns the type flags without any allocations. This returns a DWORD type
4357 * flag, which expands the type flags without growing the TYPEATTR (type
4361 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 * iface,
4364 ICOM_THIS( ITypeInfoImpl, iface);
4365 *pTypeFlags=This->TypeAttr.wTypeFlags;
4366 TRACE("(%p) flags 0x%04x\n", This,*pTypeFlags);
4370 /* ITypeInfo2::GetFuncIndexOfMemId
4371 * Binds to a specific member based on a known DISPID, where the member name
4372 * is not known (for example, when binding to a default member).
4375 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
4376 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
4378 ICOM_THIS( ITypeInfoImpl, iface);
4379 TLBFuncDesc *pFuncInfo;
4382 /* FIXME: should check for invKind??? */
4383 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
4384 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
4390 result=E_INVALIDARG;
4392 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
4393 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
4397 /* TypeInfo2::GetVarIndexOfMemId
4399 * Binds to a specific member based on a known DISPID, where the member name
4400 * is not known (for example, when binding to a default member).
4403 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
4404 MEMBERID memid, UINT *pVarIndex)
4406 ICOM_THIS( ITypeInfoImpl, iface);
4407 TLBVarDesc *pVarInfo;
4410 for(i=0, pVarInfo=This->varlist; pVarInfo &&
4411 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
4418 result=E_INVALIDARG;
4420 TRACE("(%p) memid 0x%08lx -> %s\n", This,
4421 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
4425 /* ITypeInfo2::GetCustData
4427 * Gets the custom data
4429 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
4434 ICOM_THIS( ITypeInfoImpl, iface);
4435 TLBCustData *pCData;
4437 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4438 if( IsEqualIID(guid, &pCData->guid)) break;
4440 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4444 VariantInit( pVarVal);
4445 VariantCopy( pVarVal, &pCData->data);
4448 return E_INVALIDARG; /* FIXME: correct? */
4451 /* ITypeInfo2::GetFuncCustData
4453 * Gets the custom data
4455 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
4461 ICOM_THIS( ITypeInfoImpl, iface);
4462 TLBCustData *pCData=NULL;
4463 TLBFuncDesc * pFDesc;
4465 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4466 pFDesc=pFDesc->next);
4469 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
4470 if( IsEqualIID(guid, &pCData->guid)) break;
4472 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4475 VariantInit( pVarVal);
4476 VariantCopy( pVarVal, &pCData->data);
4479 return E_INVALIDARG; /* FIXME: correct? */
4482 /* ITypeInfo2::GetParamCustData
4484 * Gets the custom data
4486 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
4493 ICOM_THIS( ITypeInfoImpl, iface);
4494 TLBCustData *pCData=NULL;
4495 TLBFuncDesc * pFDesc;
4498 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
4500 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
4501 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
4502 pCData = pCData->next)
4503 if( IsEqualIID(guid, &pCData->guid)) break;
4505 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4509 VariantInit( pVarVal);
4510 VariantCopy( pVarVal, &pCData->data);
4513 return E_INVALIDARG; /* FIXME: correct? */
4516 /* ITypeInfo2::GetVarCustData
4518 * Gets the custom data
4520 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
4526 ICOM_THIS( ITypeInfoImpl, iface);
4527 TLBCustData *pCData=NULL;
4528 TLBVarDesc * pVDesc;
4531 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
4535 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
4537 if( IsEqualIID(guid, &pCData->guid)) break;
4541 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4545 VariantInit( pVarVal);
4546 VariantCopy( pVarVal, &pCData->data);
4549 return E_INVALIDARG; /* FIXME: correct? */
4552 /* ITypeInfo2::GetImplCustData
4554 * Gets the custom data
4556 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
4562 ICOM_THIS( ITypeInfoImpl, iface);
4563 TLBCustData *pCData=NULL;
4564 TLBImplType * pRDesc;
4567 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
4571 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
4573 if( IsEqualIID(guid, &pCData->guid)) break;
4577 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4581 VariantInit( pVarVal);
4582 VariantCopy( pVarVal, &pCData->data);
4585 return E_INVALIDARG; /* FIXME: correct? */
4588 /* ITypeInfo2::GetDocumentation2
4590 * Retrieves the documentation string, the complete Help file name and path,
4591 * the localization context to use, and the context ID for the library Help
4592 * topic in the Help file.
4595 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
4599 BSTR *pbstrHelpString,
4600 DWORD *pdwHelpStringContext,
4601 BSTR *pbstrHelpStringDll)
4603 ICOM_THIS( ITypeInfoImpl, iface);
4604 TLBFuncDesc * pFDesc;
4605 TLBVarDesc * pVDesc;
4606 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
4607 "HelpStringContext(%p) HelpStringDll(%p)\n",
4608 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
4609 pbstrHelpStringDll );
4610 /* the help string should be obtained from the helpstringdll,
4611 * using the _DLLGetDocumentation function, based on the supplied
4612 * lcid. Nice to do sometime...
4614 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4616 *pbstrHelpString=SysAllocString(This->Name);
4617 if(pdwHelpStringContext)
4618 *pdwHelpStringContext=This->dwHelpStringContext;
4619 if(pbstrHelpStringDll)
4620 *pbstrHelpStringDll=
4621 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4623 }else {/* for a member */
4624 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4625 if(pFDesc->funcdesc.memid==memid){
4627 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
4628 if(pdwHelpStringContext)
4629 *pdwHelpStringContext=pFDesc->HelpStringContext;
4630 if(pbstrHelpStringDll)
4631 *pbstrHelpStringDll=
4632 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4635 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4636 if(pVDesc->vardesc.memid==memid){
4638 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
4639 if(pdwHelpStringContext)
4640 *pdwHelpStringContext=pVDesc->HelpStringContext;
4641 if(pbstrHelpStringDll)
4642 *pbstrHelpStringDll=
4643 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
4647 return TYPE_E_ELEMENTNOTFOUND;
4650 /* ITypeInfo2::GetAllCustData
4652 * Gets all custom data items for the Type info.
4655 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
4657 CUSTDATA *pCustData)
4659 ICOM_THIS( ITypeInfoImpl, iface);
4660 TLBCustData *pCData;
4663 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4665 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4666 if(pCustData->prgCustData ){
4667 pCustData->cCustData=This->ctCustData;
4668 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4669 pCustData->prgCustData[i].guid=pCData->guid;
4670 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4673 ERR(" OUT OF MEMORY! \n");
4674 return E_OUTOFMEMORY;
4679 /* ITypeInfo2::GetAllFuncCustData
4681 * Gets all custom data items for the specified Function
4684 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
4687 CUSTDATA *pCustData)
4689 ICOM_THIS( ITypeInfoImpl, iface);
4690 TLBCustData *pCData;
4691 TLBFuncDesc * pFDesc;
4693 TRACE("(%p) index %d\n", This, index);
4694 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
4695 pFDesc=pFDesc->next)
4698 pCustData->prgCustData =
4699 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
4700 if(pCustData->prgCustData ){
4701 pCustData->cCustData=pFDesc->ctCustData;
4702 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
4703 pCData = pCData->next){
4704 pCustData->prgCustData[i].guid=pCData->guid;
4705 VariantCopy(& pCustData->prgCustData[i].varValue,
4709 ERR(" OUT OF MEMORY! \n");
4710 return E_OUTOFMEMORY;
4714 return TYPE_E_ELEMENTNOTFOUND;
4717 /* ITypeInfo2::GetAllParamCustData
4719 * Gets all custom data items for the Functions
4722 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
4723 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
4725 ICOM_THIS( ITypeInfoImpl, iface);
4726 TLBCustData *pCData=NULL;
4727 TLBFuncDesc * pFDesc;
4729 TRACE("(%p) index %d\n", This, indexFunc);
4730 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
4731 pFDesc=pFDesc->next)
4733 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
4734 pCustData->prgCustData =
4735 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
4736 sizeof(CUSTDATAITEM));
4737 if(pCustData->prgCustData ){
4738 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
4739 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
4740 pCData; i++, pCData = pCData->next){
4741 pCustData->prgCustData[i].guid=pCData->guid;
4742 VariantCopy(& pCustData->prgCustData[i].varValue,
4746 ERR(" OUT OF MEMORY! \n");
4747 return E_OUTOFMEMORY;
4751 return TYPE_E_ELEMENTNOTFOUND;
4754 /* ITypeInfo2::GetAllVarCustData
4756 * Gets all custom data items for the specified Variable
4759 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
4760 UINT index, CUSTDATA *pCustData)
4762 ICOM_THIS( ITypeInfoImpl, iface);
4763 TLBCustData *pCData;
4764 TLBVarDesc * pVDesc;
4766 TRACE("(%p) index %d\n", This, index);
4767 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
4768 pVDesc=pVDesc->next)
4771 pCustData->prgCustData =
4772 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
4773 if(pCustData->prgCustData ){
4774 pCustData->cCustData=pVDesc->ctCustData;
4775 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
4776 pCData = pCData->next){
4777 pCustData->prgCustData[i].guid=pCData->guid;
4778 VariantCopy(& pCustData->prgCustData[i].varValue,
4782 ERR(" OUT OF MEMORY! \n");
4783 return E_OUTOFMEMORY;
4787 return TYPE_E_ELEMENTNOTFOUND;
4790 /* ITypeInfo2::GetAllImplCustData
4792 * Gets all custom data items for the specified implementation type
4795 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
4798 CUSTDATA *pCustData)
4800 ICOM_THIS( ITypeInfoImpl, iface);
4801 TLBCustData *pCData;
4802 TLBImplType * pRDesc;
4804 TRACE("(%p) index %d\n", This, index);
4805 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
4806 pRDesc=pRDesc->next)
4809 pCustData->prgCustData =
4810 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
4811 if(pCustData->prgCustData ){
4812 pCustData->cCustData=pRDesc->ctCustData;
4813 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
4814 pCData = pCData->next){
4815 pCustData->prgCustData[i].guid=pCData->guid;
4816 VariantCopy(& pCustData->prgCustData[i].varValue,
4820 ERR(" OUT OF MEMORY! \n");
4821 return E_OUTOFMEMORY;
4825 return TYPE_E_ELEMENTNOTFOUND;
4828 static ICOM_VTABLE(ITypeInfo2) tinfvt =
4830 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4832 ITypeInfo_fnQueryInterface,
4834 ITypeInfo_fnRelease,
4836 ITypeInfo_fnGetTypeAttr,
4837 ITypeInfo_fnGetTypeComp,
4838 ITypeInfo_fnGetFuncDesc,
4839 ITypeInfo_fnGetVarDesc,
4840 ITypeInfo_fnGetNames,
4841 ITypeInfo_fnGetRefTypeOfImplType,
4842 ITypeInfo_fnGetImplTypeFlags,
4843 ITypeInfo_fnGetIDsOfNames,
4845 ITypeInfo_fnGetDocumentation,
4846 ITypeInfo_fnGetDllEntry,
4847 ITypeInfo_fnGetRefTypeInfo,
4848 ITypeInfo_fnAddressOfMember,
4849 ITypeInfo_fnCreateInstance,
4850 ITypeInfo_fnGetMops,
4851 ITypeInfo_fnGetContainingTypeLib,
4852 ITypeInfo_fnReleaseTypeAttr,
4853 ITypeInfo_fnReleaseFuncDesc,
4854 ITypeInfo_fnReleaseVarDesc,
4856 ITypeInfo2_fnGetTypeKind,
4857 ITypeInfo2_fnGetTypeFlags,
4858 ITypeInfo2_fnGetFuncIndexOfMemId,
4859 ITypeInfo2_fnGetVarIndexOfMemId,
4860 ITypeInfo2_fnGetCustData,
4861 ITypeInfo2_fnGetFuncCustData,
4862 ITypeInfo2_fnGetParamCustData,
4863 ITypeInfo2_fnGetVarCustData,
4864 ITypeInfo2_fnGetImplTypeCustData,
4865 ITypeInfo2_fnGetDocumentation2,
4866 ITypeInfo2_fnGetAllCustData,
4867 ITypeInfo2_fnGetAllFuncCustData,
4868 ITypeInfo2_fnGetAllParamCustData,
4869 ITypeInfo2_fnGetAllVarCustData,
4870 ITypeInfo2_fnGetAllImplTypeCustData,