4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
64 #define NONAMELESSUNION
65 #define NONAMELESSSTRUCT
73 #include "wine/unicode.h"
78 #include "wine/debug.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 /****************************************************************************
90 * Takes p_iVal (which is in little endian) and returns it
91 * in the host machine's byte order.
93 #ifdef WORDS_BIGENDIAN
94 static WORD FromLEWord(WORD p_iVal)
96 return (((p_iVal & 0x00FF) << 8) |
97 ((p_iVal & 0xFF00) >> 8));
101 static DWORD FromLEDWord(DWORD p_iVal)
103 return (((p_iVal & 0x000000FF) << 24) |
104 ((p_iVal & 0x0000FF00) << 8) |
105 ((p_iVal & 0x00FF0000) >> 8) |
106 ((p_iVal & 0xFF000000) >> 24));
109 #define FromLEWord(X) (X)
110 #define FromLEDWord(X) (X)
114 /****************************************************************************
117 * Fix byte order in any structure if necessary
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val, int p_iSize)
124 p_iSize /= sizeof(WORD);
127 *Val = FromLEWord(*Val);
134 static void FromLEDWords(void *p_Val, int p_iSize)
138 p_iSize /= sizeof(DWORD);
141 *Val = FromLEDWord(*Val);
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
152 /****************************************************************************
153 * QueryPathOfRegTypeLib [OLEAUT32.164]
158 QueryPathOfRegTypeLib(
159 REFGUID guid, /* [in] referenced guid */
160 WORD wMaj, /* [in] major version */
161 WORD wMin, /* [in] minor version */
162 LCID lcid, /* [in] locale id */
163 LPBSTR path ) /* [out] path of typelib */
165 /* don't need to ZeroMemory those arrays since sprintf and RegQueryValue add
166 string termination character on output strings */
173 char szTypeLibKey[100];
174 char szPath[MAX_PATH];
175 DWORD dwPathLen = sizeof(szPath);
183 FIXME("(%s,%d,%d,0x%04lx,%p),stub!\n", szXGUID, wMaj, wMin, (DWORD)lcid, path);
189 sprintf(szTypeLibKey,
190 "SOFTWARE\\Classes\\Typelib\\{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\\%d.%d\\%lx\\win32",
191 guid->Data1, guid->Data2, guid->Data3,
192 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
193 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7],
198 if (RegQueryValueA(HKEY_LOCAL_MACHINE, szTypeLibKey, szPath, &dwPathLen))
202 else if (myLCID == lcid)
204 /* try with sub-langid */
205 myLCID = SUBLANGID(lcid);
207 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
209 /* try with system langid */
219 DWORD len = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, szPath, dwPathLen, NULL, 0 );
220 BSTR bstrPath = SysAllocStringLen(NULL,len);
222 MultiByteToWideChar(CP_ACP,
234 TRACE_(typelib)("%s not found\n", szTypeLibKey);
239 /******************************************************************************
240 * CreateTypeLib [OLEAUT32.160] creates a typelib
246 HRESULT WINAPI CreateTypeLib(
247 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
249 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
252 /******************************************************************************
253 * LoadTypeLib [OLEAUT32.161]
254 * Loads and registers a type library
256 * Docs: OLECHAR FAR* szFile
257 * Docs: iTypeLib FAR* FAR* pptLib
263 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
265 HRESULT WINAPI LoadTypeLib(
266 const OLECHAR *szFile,/* [in] Name of file to load from */
267 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
270 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
273 /******************************************************************************
274 * LoadTypeLibEx [OLEAUT32.183]
275 * Loads and optionally registers a type library
281 HRESULT WINAPI LoadTypeLibEx(
282 LPCOLESTR szFile, /* [in] Name of file to load from */
283 REGKIND regkind, /* [in] Specify kind of registration */
284 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
286 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
291 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
294 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
297 /* Look for a trailing '\\' followed by an index */
298 pIndexStr = strrchrW(szFile, '\\');
299 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
300 index = atoiW(pIndexStr);
301 memcpy(szFileCopy, szFile,
302 (pIndexStr - szFile - 1) * sizeof(WCHAR));
303 szFileCopy[pIndexStr - szFile - 1] = '\0';
304 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
306 return TYPE_E_CANTLOADLIBRARY;
307 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
308 return TYPE_E_CANTLOADLIBRARY;
311 static const WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
314 lstrcpyW(tstpath,szFile);
316 for (i=0;i<strlenW(tstpath);i++) {
317 if (tstpath[i] == 's') {
318 if (!strcmpW(tstpath+i,stdole32tlb)) {
320 MESSAGE("**************************************************************************\n");
321 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
322 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
323 MESSAGE("on the Microsoft Download Pages.\n");
324 MESSAGE("**************************************************************************\n");
329 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
330 return TYPE_E_CANTLOADLIBRARY;
334 TRACE("File %s index %d\n", debugstr_w(szPath), index);
336 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
341 case REGKIND_DEFAULT:
342 /* don't register typelibs supplied with full path. Experimentation confirms the following */
344 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
345 (szFile[0] && (szFile[1] == ':'))) break;
346 /* else fall-through */
348 case REGKIND_REGISTER:
349 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
351 IUnknown_Release(*pptLib);
359 TRACE(" returns %08lx\n",res);
363 /******************************************************************************
364 * LoadRegTypeLib [OLEAUT32.162]
366 HRESULT WINAPI LoadRegTypeLib(
367 REFGUID rguid, /* [in] referenced guid */
368 WORD wVerMajor, /* [in] major version */
369 WORD wVerMinor, /* [in] minor version */
370 LCID lcid, /* [in] locale id */
371 ITypeLib **ppTLib) /* [out] path of typelib */
374 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
378 res= LoadTypeLib(bstr, ppTLib);
382 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
388 /******************************************************************************
389 * RegisterTypeLib [OLEAUT32.163]
390 * Adds information about a type library to the System Registry
392 * Docs: ITypeLib FAR * ptlib
393 * Docs: OLECHAR FAR* szFullPath
394 * Docs: OLECHAR FAR* szHelpDir
400 HRESULT WINAPI RegisterTypeLib(
401 ITypeLib * ptlib, /* [in] Pointer to the library*/
402 OLECHAR * szFullPath, /* [in] full Path of the library*/
403 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
416 static const char *PSOA = "{00020424-0000-0000-C000-000000000046}";
418 if (ptlib == NULL || szFullPath == NULL)
421 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
424 StringFromGUID2(&attr->guid, guid, 80);
425 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
426 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
427 guidA, attr->wMajorVerNum, attr->wMinorVerNum);
428 HeapFree(GetProcessHeap(), 0, guidA);
431 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
432 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
436 /* Set the human-readable name of the typelib */
437 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
439 if (RegSetValueExW(key, NULL, 0, REG_SZ,
440 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
448 /* Make up the name of the typelib path subkey */
449 sprintf(tmp, "%lu\\", attr->lcid);
450 switch(attr->syskind) {
452 strcat(tmp, "win16");
456 strcat(tmp, "win32");
460 TRACE("Typelib is for unsupported syskind %i\n", attr->syskind);
465 /* Create the typelib path subkey */
466 if (res == S_OK && RegCreateKeyExA(key, tmp, 0, NULL, 0,
467 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
469 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
470 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
478 /* Create the flags subkey */
479 if (res == S_OK && RegCreateKeyExA(key, "FLAGS", 0, NULL, 0,
480 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
483 /* FIXME: is %u correct? */
484 snprintf(buf, sizeof(buf), "%u", attr->wLibFlags);
485 if (RegSetValueExA(subKey, NULL, 0, REG_SZ,
486 buf, lstrlenA(buf) + 1) != ERROR_SUCCESS)
494 /* create the helpdir subkey */
495 if (res == S_OK && RegCreateKeyExA(key, "HELPDIR", 0, NULL, 0,
496 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
498 BOOL freeHelpDir = FALSE;
501 /* if we created a new key, and helpDir was null, set the helpdir
502 to the directory which contains the typelib. However,
503 if we just opened an existing key, we leave the helpdir alone */
504 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
505 szHelpDir = SysAllocString(szFullPath);
506 pIndexStr = strrchrW(szHelpDir, '\\');
513 /* if we have an szHelpDir, set it! */
514 if (szHelpDir != NULL) {
515 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
516 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
522 if (freeHelpDir) SysFreeString(szHelpDir);
534 /* register OLE Automation-compatible interfaces for this typelib */
535 types = ITypeLib_GetTypeInfoCount(ptlib);
536 for (tidx=0; tidx<types; tidx++) {
537 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
538 LPOLESTR name = NULL;
539 ITypeInfo *tinfo = NULL;
541 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
544 case TKIND_INTERFACE:
545 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
546 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
550 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
551 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
555 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
560 TYPEATTR *tattr = NULL;
561 ITypeInfo_GetTypeAttr(tinfo, &tattr);
564 TRACE_(typelib)("guid=%s, flags=%04x (",
565 debugstr_guid(&tattr->guid),
568 if (TRACE_ON(typelib)) {
569 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
590 * FIXME: The 1 is just here until we implement rpcrt4
591 * stub/proxy handling. Until then it helps IShield
594 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
596 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
597 FIXME("Registering non-oleautomation interface!\n");
600 /* register interface<->typelib coupling */
601 StringFromGUID2(&tattr->guid, guid, 80);
602 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
603 snprintf(keyName, sizeof(keyName), "Interface\\%s", guidA);
604 HeapFree(GetProcessHeap(), 0, guidA);
606 if (RegCreateKeyExA(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
607 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS) {
609 RegSetValueExW(key, NULL, 0, REG_SZ,
610 (BYTE *)name, lstrlenW(name) * sizeof(OLECHAR));
612 if (RegCreateKeyExA(key, "ProxyStubClsid", 0, NULL, 0,
613 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
614 RegSetValueExA(subKey, NULL, 0, REG_SZ,
619 if (RegCreateKeyExA(key, "ProxyStubClsid32", 0, NULL, 0,
620 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
621 RegSetValueExA(subKey, NULL, 0, REG_SZ,
626 if (RegCreateKeyExA(key, "TypeLib", 0, NULL, 0,
627 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
629 StringFromGUID2(&attr->guid, guid, 80);
630 snprintf(ver, sizeof(ver), "%x.%x",
631 attr->wMajorVerNum, attr->wMinorVerNum);
632 RegSetValueExW(subKey, NULL, 0, REG_SZ,
633 (BYTE *)guid, lstrlenW(guid) * sizeof(OLECHAR));
634 RegSetValueExA(subKey, "Version", 0, REG_SZ,
643 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
646 ITypeInfo_Release(tinfo);
653 ITypeLib_ReleaseTLibAttr(ptlib, attr);
659 /******************************************************************************
660 * UnRegisterTypeLib [OLEAUT32.186]
661 * Removes information about a type library from the System Registry
668 HRESULT WINAPI UnRegisterTypeLib(
669 REFGUID libid, /* [in] Guid of the library */
670 WORD wVerMajor, /* [in] major version */
671 WORD wVerMinor, /* [in] minor version */
672 LCID lcid, /* [in] locale id */
675 BSTR tlibPath = NULL;
677 CHAR keyName[MAX_PATH];
679 CHAR subKeyName[MAX_PATH];
684 BOOL deleteOtherStuff;
687 TYPEATTR* typeAttr = NULL;
689 ITypeInfo* typeInfo = NULL;
690 ITypeLib* typeLib = NULL;
693 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
695 /* Create the path to the key */
696 StringFromGUID2(libid, guid, 80);
697 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
698 snprintf(keyName, sizeof(keyName), "TypeLib\\%s\\%x.%x",
699 guidA, wVerMajor, wVerMinor);
700 HeapFree(GetProcessHeap(), 0, guidA);
702 /* Work out the syskind name */
705 syskindName = "win16";
709 syskindName = "win32";
713 TRACE("Unsupported syskind %i\n", syskind);
714 result = E_INVALIDARG;
718 /* get the path to the typelib on disk */
719 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
720 result = E_INVALIDARG;
724 /* Try and open the key to the type library. */
725 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
726 result = E_INVALIDARG;
730 /* Try and load the type library */
731 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
732 result = TYPE_E_INVALIDSTATE;
736 /* remove any types registered with this typelib */
737 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
738 for (i=0; i<numTypes; i++) {
739 /* get the kind of type */
740 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
744 /* skip non-interfaces, and get type info for the type */
745 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
748 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
751 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
755 /* the path to the type */
756 StringFromGUID2(&typeAttr->guid, guid, 80);
757 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
758 snprintf(subKeyName, sizeof(subKeyName), "Interface\\%s", guidA);
759 HeapFree(GetProcessHeap(), 0, guidA);
761 /* Delete its bits */
762 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
765 RegDeleteKeyA(subKey, "ProxyStubClsid");
766 RegDeleteKeyA(subKey, "ProxyStubClsid32");
767 RegDeleteKeyA(subKey, "TypeLib");
770 RegDeleteKeyA(HKEY_CLASSES_ROOT, subKeyName);
773 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
775 if (typeInfo) ITypeInfo_Release(typeInfo);
779 /* Now, delete the type library path subkey */
780 sprintf(subKeyName, "%lu\\%s", lcid, syskindName);
781 RegDeleteKeyA(key, subKeyName);
782 sprintf(subKeyName, "%lu", lcid);
783 RegDeleteKeyA(key, subKeyName);
785 /* check if there is anything besides the FLAGS/HELPDIR keys.
786 If there is, we don't delete them */
787 tmpLength = sizeof(subKeyName);
788 deleteOtherStuff = TRUE;
790 while(RegEnumKeyExA(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
791 tmpLength = sizeof(subKeyName);
793 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
794 if (!strcmp(subKeyName, "FLAGS")) continue;
795 if (!strcmp(subKeyName, "HELPDIR")) continue;
796 deleteOtherStuff = FALSE;
800 /* only delete the other parts of the key if we're absolutely sure */
801 if (deleteOtherStuff) {
802 RegDeleteKeyA(key, "FLAGS");
803 RegDeleteKeyA(key, "HELPDIR");
807 StringFromGUID2(libid, guid, 80);
808 guidA = HEAP_strdupWtoA(GetProcessHeap(), 0, guid);
809 sprintf(keyName, "TypeLib\\%s\\%x.%x", guidA, wVerMajor, wVerMinor);
810 RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
811 sprintf(keyName, "TypeLib\\%s", guidA);
812 RegDeleteKeyA(HKEY_CLASSES_ROOT, keyName);
813 HeapFree(GetProcessHeap(), 0, guidA);
817 if (tlibPath) SysFreeString(tlibPath);
818 if (typeLib) ITypeLib_Release(typeLib);
819 if (subKey) RegCloseKey(subKey);
820 if (key) RegCloseKey(key);
824 /*======================= ITypeLib implementation =======================*/
826 typedef struct tagTLBCustData
830 struct tagTLBCustData* next;
833 /* data structure for import typelibs */
834 typedef struct tagTLBImpLib
836 int offset; /* offset in the file (MSFT)
837 offset in nametable (SLTG)
838 just used to identify library while reading
840 GUID guid; /* libid */
841 BSTR name; /* name */
843 LCID lcid; /* lcid of imported typelib */
845 WORD wVersionMajor; /* major version number */
846 WORD wVersionMinor; /* minor version number */
848 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
849 NULL if not yet loaded */
850 struct tagTLBImpLib * next;
853 /* internal ITypeLib data */
854 typedef struct tagITypeLibImpl
856 ICOM_VFIELD(ITypeLib2);
857 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
859 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
861 /* strings can be stored in tlb as multibyte strings BUT they are *always*
862 * exported to the application as a UNICODE string.
868 unsigned long dwHelpContext;
869 int TypeInfoCount; /* nr of typeinfo's in librarry */
870 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
871 int ctCustData; /* number of items in cust data list */
872 TLBCustData * pCustData; /* linked list to cust data */
873 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
874 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
875 libary. Only used while read MSFT
878 /* typelibs are cached, keyed by path, so store the linked list info within them */
879 struct tagITypeLibImpl *next, *prev;
883 static struct ICOM_VTABLE(ITypeLib2) tlbvt;
884 static struct ICOM_VTABLE(ITypeComp) tlbtcvt;
886 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
887 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
889 /* ITypeLib methods */
890 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
891 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
893 /*======================= ITypeInfo implementation =======================*/
895 /* data for refernced types */
896 typedef struct tagTLBRefType
898 INT index; /* Type index for internal ref or for external ref
899 it the format is SLTG. -2 indicates to
902 GUID guid; /* guid of the referenced type */
903 /* if index == TLB_REF_USE_GUID */
905 HREFTYPE reference; /* The href of this ref */
906 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
907 TLB_REF_INTERNAL for internal refs
908 TLB_REF_NOT_FOUND for broken refs */
910 struct tagTLBRefType * next;
913 #define TLB_REF_USE_GUID -2
915 #define TLB_REF_INTERNAL (void*)-2
916 #define TLB_REF_NOT_FOUND (void*)-1
918 /* internal Parameter data */
919 typedef struct tagTLBParDesc
923 TLBCustData * pCustData; /* linked list to cust data */
926 /* internal Function data */
927 typedef struct tagTLBFuncDesc
929 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
930 BSTR Name; /* the name of this function */
931 TLBParDesc *pParamDesc; /* array with param names and custom data */
933 int HelpStringContext;
935 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
937 TLBCustData * pCustData; /* linked list to cust data; */
938 struct tagTLBFuncDesc * next;
941 /* internal Variable data */
942 typedef struct tagTLBVarDesc
944 VARDESC vardesc; /* lots of info on the variable and its attributes. */
945 BSTR Name; /* the name of this variable */
947 int HelpStringContext; /* FIXME: where? */
950 TLBCustData * pCustData;/* linked list to cust data; */
951 struct tagTLBVarDesc * next;
954 /* internal implemented interface data */
955 typedef struct tagTLBImplType
957 HREFTYPE hRef; /* hRef of interface */
958 int implflags; /* IMPLFLAG_*s */
960 TLBCustData * pCustData;/* linked list to custom data; */
961 struct tagTLBImplType *next;
964 /* internal TypeInfo data */
965 typedef struct tagITypeInfoImpl
967 ICOM_VFIELD(ITypeInfo2);
968 ICOM_VTABLE(ITypeComp) * lpVtblTypeComp;
970 TYPEATTR TypeAttr ; /* _lots_ of type information. */
971 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
972 int index; /* index in this typelib; */
973 /* type libs seem to store the doc strings in ascii
974 * so why should we do it in unicode?
978 unsigned long dwHelpContext;
979 unsigned long dwHelpStringContext;
982 TLBFuncDesc * funclist; /* linked list with function descriptions */
985 TLBVarDesc * varlist; /* linked list with variable descriptions */
987 /* Implemented Interfaces */
988 TLBImplType * impltypelist;
990 TLBRefType * reflist;
992 TLBCustData * pCustData; /* linked list to cust data; */
993 struct tagITypeInfoImpl * next;
996 static struct ICOM_VTABLE(ITypeInfo2) tinfvt;
997 static struct ICOM_VTABLE(ITypeComp) tcompvt;
999 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
1001 typedef struct tagTLBContext
1003 unsigned int oStart; /* start of TLB in file */
1004 unsigned int pos; /* current pos */
1005 unsigned int length; /* total length */
1006 void *mapping; /* memory mapping */
1007 MSFT_SegDir * pTblDir;
1008 ITypeLibImpl* pLibInfo;
1012 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1017 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1018 if (pTD->vt & VT_RESERVED)
1019 szVarType += strlen(strcpy(szVarType, "reserved | "));
1020 if (pTD->vt & VT_BYREF)
1021 szVarType += strlen(strcpy(szVarType, "ref to "));
1022 if (pTD->vt & VT_ARRAY)
1023 szVarType += strlen(strcpy(szVarType, "array of "));
1024 if (pTD->vt & VT_VECTOR)
1025 szVarType += strlen(strcpy(szVarType, "vector of "));
1026 switch(pTD->vt & VT_TYPEMASK) {
1027 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1028 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1029 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1030 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1031 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1032 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1033 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1034 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1035 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1036 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1037 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1038 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1039 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1040 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1041 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1042 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1043 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1044 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1045 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1046 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1047 pTD->u.hreftype); break;
1048 case VT_PTR: sprintf(szVarType, "ptr to ");
1049 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1051 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1052 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1054 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1055 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1056 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1059 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1063 void dump_ELEMDESC(ELEMDESC *edesc) {
1065 dump_TypeDesc(&edesc->tdesc,buf);
1066 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1067 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1068 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1070 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1072 MESSAGE("memid is %08lx\n",funcdesc->memid);
1073 for (i=0;i<funcdesc->cParams;i++) {
1074 MESSAGE("Param %d:\n",i);
1075 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1077 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1078 switch (funcdesc->funckind) {
1079 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1080 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1081 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1082 case FUNC_STATIC: MESSAGE("static");break;
1083 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1084 default: MESSAGE("unknown");break;
1086 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1087 switch (funcdesc->invkind) {
1088 case INVOKE_FUNC: MESSAGE("func");break;
1089 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1090 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1091 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1093 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1094 switch (funcdesc->callconv) {
1095 case CC_CDECL: MESSAGE("cdecl");break;
1096 case CC_PASCAL: MESSAGE("pascal");break;
1097 case CC_STDCALL: MESSAGE("stdcall");break;
1098 case CC_SYSCALL: MESSAGE("syscall");break;
1101 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1102 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1103 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1106 void dump_IDLDESC(IDLDESC *idl) {
1107 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1110 static const char * typekind_desc[] =
1123 void dump_TYPEATTR(TYPEATTR *tattr) {
1125 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1126 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1127 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1128 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1129 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1130 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1131 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1132 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1133 MESSAGE("\tcVars: %d\n", tattr->cVars);
1134 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1135 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1136 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1137 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1138 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1139 dump_TypeDesc(&tattr->tdescAlias,buf);
1140 MESSAGE("\ttypedesc: %s\n", buf);
1141 dump_IDLDESC(&tattr->idldescType);
1144 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1147 if (!TRACE_ON(typelib))
1149 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1150 for (i=0;i<pfd->funcdesc.cParams;i++)
1151 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1154 dump_FUNCDESC(&(pfd->funcdesc));
1156 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1157 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1159 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1163 dump_TLBFuncDescOne(pfd);
1167 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1171 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1176 static void dump_TLBImpLib(TLBImpLib *import)
1178 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1179 debugstr_w(import->name));
1180 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1181 import->wVersionMinor, import->lcid, import->offset);
1184 static void dump_TLBRefType(TLBRefType * prt)
1188 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1189 if(prt->index == -1)
1190 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1192 TRACE_(typelib)("type no: %d\n", prt->index);
1194 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1195 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1196 TRACE_(typelib)("in lib\n");
1197 dump_TLBImpLib(prt->pImpTLInfo);
1203 static void dump_TLBImplType(TLBImplType * impl)
1207 "implementing/inheriting interface hRef = %lx implflags %x\n",
1208 impl->hRef, impl->implflags);
1213 void dump_Variant(VARIANT * pvar)
1217 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1221 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1222 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1224 TRACE(",%p", V_BYREF(pvar));
1226 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1230 else switch (V_TYPE(pvar))
1232 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1233 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1234 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1235 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1237 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1239 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1240 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1241 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1242 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1243 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1244 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1245 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1246 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1247 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1248 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1249 V_CY(pvar).s.Lo); break;
1251 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1252 TRACE(",<invalid>");
1254 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1255 st.wHour, st.wMinute, st.wSecond);
1259 case VT_USERDEFINED:
1261 case VT_NULL: break;
1262 default: TRACE(",?"); break;
1268 static void dump_DispParms(DISPPARAMS * pdp)
1272 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1274 while (index < pdp->cArgs)
1276 dump_Variant( &pdp->rgvarg[index] );
1281 static void dump_TypeInfo(ITypeInfoImpl * pty)
1283 TRACE("%p ref=%u\n", pty, pty->ref);
1284 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1285 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1286 TRACE("fct:%u var:%u impl:%u\n",
1287 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1288 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1289 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1290 dump_TLBFuncDesc(pty->funclist);
1291 dump_TLBVarDesc(pty->varlist);
1292 dump_TLBImplType(pty->impltypelist);
1295 void dump_VARDESC(VARDESC *v)
1297 MESSAGE("memid %ld\n",v->memid);
1298 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1299 MESSAGE("oInst %ld\n",v->u.oInst);
1300 dump_ELEMDESC(&(v->elemdescVar));
1301 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1302 MESSAGE("varkind %d\n",v->varkind);
1305 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1307 /* VT_LPWSTR is largest type that */
1308 /* may appear in type description*/
1309 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1310 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1311 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1312 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1313 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1314 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1318 static void TLB_abort()
1322 static void * TLB_Alloc(unsigned size)
1325 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1327 ERR("cannot allocate memory\n");
1332 static void TLB_Free(void * ptr)
1334 HeapFree(GetProcessHeap(), 0, ptr);
1338 /**********************************************************************
1340 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1343 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1345 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1346 pcx->pos, count, pcx->oStart, pcx->length, where);
1348 if (where != DO_NOT_SEEK)
1350 where += pcx->oStart;
1351 if (where > pcx->length)
1354 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1359 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1360 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1365 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1370 ret = MSFT_Read(buffer, count, pcx, where);
1371 FromLEDWords(buffer, ret);
1376 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1381 ret = MSFT_Read(buffer, count, pcx, where);
1382 FromLEWords(buffer, ret);
1387 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1389 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1390 memset(pGuid,0, sizeof(GUID));
1393 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1394 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1395 pGuid->Data2 = FromLEWord(pGuid->Data2);
1396 pGuid->Data3 = FromLEWord(pGuid->Data3);
1397 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1400 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1403 MSFT_NameIntro niName;
1405 WCHAR* pwstring = NULL;
1406 BSTR bstrName = NULL;
1408 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1409 pcx->pTblDir->pNametab.offset+offset);
1410 niName.namelen &= 0xFF; /* FIXME: correct ? */
1411 name=TLB_Alloc((niName.namelen & 0xff) +1);
1412 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1413 name[niName.namelen & 0xff]='\0';
1415 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1418 /* no invalid characters in string */
1421 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1423 /* don't check for invalid character since this has been done previously */
1424 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1426 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1427 lengthInChars = SysStringLen(bstrName);
1428 HeapFree(GetProcessHeap(), 0, pwstring);
1431 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1435 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1442 if(offset<0) return NULL;
1443 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1444 if(length <= 0) return 0;
1445 string=TLB_Alloc(length +1);
1446 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1447 string[length]='\0';
1449 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1450 string, -1, NULL, 0);
1452 /* no invalid characters in string */
1455 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1457 /* don't check for invalid character since this has been done previously */
1458 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1460 bstr = SysAllocStringLen(pwstring, lengthInChars);
1461 lengthInChars = SysStringLen(bstr);
1462 HeapFree(GetProcessHeap(), 0, pwstring);
1465 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1469 * read a value and fill a VARIANT structure
1471 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1475 TRACE_(typelib)("\n");
1477 if(offset <0) { /* data are packed in here */
1478 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1479 V_UNION(pVar, iVal) = offset & 0xffff;
1482 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1483 pcx->pTblDir->pCustData.offset + offset );
1484 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1485 switch (V_VT(pVar)){
1486 case VT_EMPTY: /* FIXME: is this right? */
1487 case VT_NULL: /* FIXME: is this right? */
1488 case VT_I2 : /* this should not happen */
1499 case VT_VOID : /* FIXME: is this right? */
1507 case VT_DECIMAL : /* FIXME: is this right? */
1510 /* pointer types with known behaviour */
1513 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1515 FIXME("BSTR length = %d?\n", size);
1517 ptr=TLB_Alloc(size);/* allocate temp buffer */
1518 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1519 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1520 /* FIXME: do we need a AtoW conversion here? */
1521 V_UNION(pVar, bstrVal[size])=L'\0';
1522 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1527 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1534 case VT_USERDEFINED :
1540 case VT_STREAMED_OBJECT :
1541 case VT_STORED_OBJECT :
1542 case VT_BLOB_OBJECT :
1547 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1551 if(size>0) /* (big|small) endian correct? */
1552 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1556 * create a linked list with custom data
1558 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1564 TRACE_(typelib)("\n");
1568 pNew=TLB_Alloc(sizeof(TLBCustData));
1569 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1570 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1571 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1572 /* add new custom data at head of the list */
1573 pNew->next=*ppCustData;
1575 offset = entry.next;
1580 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1584 pTd->vt=type & VT_TYPEMASK;
1586 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1588 if(pTd->vt == VT_USERDEFINED)
1589 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1591 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1595 MSFT_DoFuncs(TLBContext* pcx,
1600 TLBFuncDesc** pptfd)
1603 * member information is stored in a data structure at offset
1604 * indicated by the memoffset field of the typeinfo structure
1605 * There are several distinctive parts.
1606 * the first part starts with a field that holds the total length
1607 * of this (first) part excluding this field. Then follow the records,
1608 * for each member there is one record.
1610 * First entry is always the length of the record (excluding this
1612 * Rest of the record depends on the type of the member. If there is
1613 * a field indicating the member type (function variable intereface etc)
1614 * I have not found it yet. At this time we depend on the information
1615 * in the type info and the usual order how things are stored.
1617 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1620 * Third is a equal sized array with file offsets to the name entry
1623 * Forth and last (?) part is an array with offsets to the records in the
1624 * first part of this file segment.
1627 int infolen, nameoffset, reclength, nrattributes, i;
1628 int recoffset = offset + sizeof(INT);
1631 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1633 TRACE_(typelib)("\n");
1635 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1637 for ( i = 0; i < cFuncs ; i++ )
1639 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1641 /* name, eventually add to a hash table */
1642 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1643 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1645 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1647 /* read the function information record */
1648 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1652 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1654 /* do the attributes */
1655 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1658 if ( nrattributes > 0 )
1660 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1662 if ( nrattributes > 1 )
1664 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1665 pFuncRec->OptAttr[1]) ;
1667 if ( nrattributes > 2 )
1669 if ( pFuncRec->FKCCIC & 0x2000 )
1671 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1675 (*pptfd)->Entry = MSFT_ReadString(pcx,
1676 pFuncRec->OptAttr[2]);
1678 if( nrattributes > 5 )
1680 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1682 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1685 pFuncRec->OptAttr[6],
1686 &(*pptfd)->pCustData);
1693 /* fill the FuncDesc Structure */
1694 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1695 offset + infolen + ( i + 1) * sizeof(INT));
1697 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1698 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1699 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1700 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1701 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1702 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1703 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1707 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1710 /* do the parameters/arguments */
1711 if(pFuncRec->nrargs)
1714 MSFT_ParameterInfo paraminfo;
1716 (*pptfd)->funcdesc.lprgelemdescParam =
1717 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1719 (*pptfd)->pParamDesc =
1720 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1722 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1723 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1725 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1727 TYPEDESC* lpArgTypeDesc = 0;
1731 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1734 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1736 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1738 /* SEEK value = jump to offset,
1739 * from there jump to the end of record,
1740 * go back by (j-1) arguments
1742 MSFT_ReadLEDWords( ¶minfo ,
1743 sizeof(MSFT_ParameterInfo), pcx,
1744 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1745 * sizeof(MSFT_ParameterInfo)));
1747 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1749 while ( lpArgTypeDesc != NULL )
1751 switch ( lpArgTypeDesc->vt )
1754 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1758 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1761 case VT_USERDEFINED:
1762 MSFT_DoRefType(pcx, pTI,
1763 lpArgTypeDesc->u.hreftype);
1765 lpArgTypeDesc = NULL;
1769 lpArgTypeDesc = NULL;
1775 /* parameter is the return value! */
1776 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1778 TYPEDESC* lpArgTypeDesc;
1780 (*pptfd)->funcdesc.elemdescFunc =
1781 (*pptfd)->funcdesc.lprgelemdescParam[j];
1783 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1785 while ( lpArgTypeDesc != NULL )
1787 switch ( lpArgTypeDesc->vt )
1790 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1794 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1798 case VT_USERDEFINED:
1801 lpArgTypeDesc->u.hreftype);
1803 lpArgTypeDesc = NULL;
1807 lpArgTypeDesc = NULL;
1812 /* second time around */
1813 for(j=0;j<pFuncRec->nrargs;j++)
1816 (*pptfd)->pParamDesc[j].Name =
1817 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1820 if ( (PARAMFLAG_FHASDEFAULT &
1821 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1822 ((pFuncRec->FKCCIC) & 0x1000) )
1824 INT* pInt = (INT *)((char *)pFuncRec +
1826 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1828 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1830 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1831 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1833 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1837 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1840 pFuncRec->OptAttr[7+j],
1841 &(*pptfd)->pParamDesc[j].pCustData);
1846 /* scode is not used: archaic win16 stuff FIXME: right? */
1847 (*pptfd)->funcdesc.cScodes = 0 ;
1848 (*pptfd)->funcdesc.lprgscode = NULL ;
1850 pptfd = & ((*pptfd)->next);
1851 recoffset += reclength;
1855 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1856 int cVars, int offset, TLBVarDesc ** pptvd)
1858 int infolen, nameoffset, reclength;
1860 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1864 TRACE_(typelib)("\n");
1866 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1867 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1868 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1869 recoffset += offset+sizeof(INT);
1870 for(i=0;i<cVars;i++){
1871 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1872 /* name, eventually add to a hash table */
1873 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1874 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1875 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1876 /* read the variable information record */
1877 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1879 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1881 if(reclength >(6*sizeof(INT)) )
1882 (*pptvd)->HelpContext=pVarRec->HelpContext;
1883 if(reclength >(7*sizeof(INT)) )
1884 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1885 if(reclength >(8*sizeof(INT)) )
1886 if(reclength >(9*sizeof(INT)) )
1887 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1888 /* fill the VarDesc Structure */
1889 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1890 offset + infolen + ( i + 1) * sizeof(INT));
1891 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1892 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1893 MSFT_GetTdesc(pcx, pVarRec->DataType,
1894 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1895 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1896 if(pVarRec->VarKind == VAR_CONST ){
1897 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1898 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1899 pVarRec->OffsValue, pcx);
1901 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1902 pptvd=&((*pptvd)->next);
1903 recoffset += reclength;
1906 /* fill in data for a hreftype (offset). When the refernced type is contained
1907 * in the typelib, it's just an (file) offset in the type info base dir.
1908 * If comes from import, it's an offset+1 in the ImpInfo table
1910 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1914 TLBRefType **ppRefType = &pTI->reflist;
1916 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1919 if((*ppRefType)->reference == offset)
1921 ppRefType = &(*ppRefType)->next;
1924 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1925 sizeof(**ppRefType));
1927 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1928 /* external typelib */
1929 MSFT_ImpInfo impinfo;
1930 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1932 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1934 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1935 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1936 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1937 if(pImpLib->offset==impinfo.oImpFile) break;
1938 pImpLib=pImpLib->next;
1941 (*ppRefType)->reference=offset;
1942 (*ppRefType)->pImpTLInfo = pImpLib;
1943 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1944 (*ppRefType)->index = TLB_REF_USE_GUID;
1946 ERR("Cannot find a reference\n");
1947 (*ppRefType)->reference=-1;
1948 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1951 /* in this typelib */
1952 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1953 (*ppRefType)->reference=offset;
1954 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1958 /* process Implemented Interfaces of a com class */
1959 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1963 MSFT_RefRecord refrec;
1964 TLBImplType **ppImpl = &pTI->impltypelist;
1966 TRACE_(typelib)("\n");
1968 for(i=0;i<count;i++){
1969 if(offset<0) break; /* paranoia */
1970 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1971 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1972 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1973 (*ppImpl)->hRef = refrec.reftype;
1974 (*ppImpl)->implflags=refrec.flags;
1975 (*ppImpl)->ctCustData=
1976 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
1977 offset=refrec.onext;
1978 ppImpl=&((*ppImpl)->next);
1982 * process a typeinfo record
1984 ITypeInfoImpl * MSFT_DoTypeInfo(
1987 ITypeLibImpl * pLibInfo)
1989 MSFT_TypeInfoBase tiBase;
1990 ITypeInfoImpl *ptiRet;
1992 TRACE_(typelib)("count=%u\n", count);
1994 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
1995 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
1996 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
1997 /* this is where we are coming from */
1998 ptiRet->pTypeLib = pLibInfo;
1999 ptiRet->index=count;
2000 /* fill in the typeattr fields */
2001 WARN("Assign constructor/destructor memid\n");
2003 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2004 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2005 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2006 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2007 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2008 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2009 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2010 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2011 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2012 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2013 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2014 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2015 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2016 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2017 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2018 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2019 MSFT_GetTdesc(pcx, tiBase.datatype1,
2020 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2023 /* IDLDESC idldescType; *//* never saw this one != zero */
2025 /* name, eventually add to a hash table */
2026 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2027 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2029 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2030 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2031 ptiRet->dwHelpContext=tiBase.helpcontext;
2032 /* note: InfoType's Help file and HelpStringDll come from the containing
2033 * library. Further HelpString and Docstring appear to be the same thing :(
2036 if(ptiRet->TypeAttr.cFuncs >0 )
2037 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2038 ptiRet->TypeAttr.cVars,
2039 tiBase.memoffset, & ptiRet->funclist);
2041 if(ptiRet->TypeAttr.cVars >0 )
2042 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2043 ptiRet->TypeAttr.cVars,
2044 tiBase.memoffset, & ptiRet->varlist);
2045 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2046 switch(ptiRet->TypeAttr.typekind)
2049 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2052 case TKIND_DISPATCH:
2053 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2055 if (tiBase.datatype1 != -1)
2057 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2058 ptiRet->impltypelist->hRef = tiBase.datatype1;
2061 { /* FIXME: This is a really bad hack to add IDispatch */
2062 const char* szStdOle = "stdole2.tlb\0";
2063 int nStdOleLen = strlen(szStdOle);
2064 TLBRefType **ppRef = &ptiRet->reflist;
2067 if((*ppRef)->reference == -1)
2069 ppRef = &(*ppRef)->next;
2072 *ppRef = TLB_Alloc(sizeof(**ppRef));
2073 (*ppRef)->guid = IID_IDispatch;
2074 (*ppRef)->reference = -1;
2075 (*ppRef)->index = TLB_REF_USE_GUID;
2076 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2077 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2078 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2081 MultiByteToWideChar(CP_ACP,
2085 (*ppRef)->pImpTLInfo->name,
2086 SysStringLen((*ppRef)->pImpTLInfo->name));
2088 (*ppRef)->pImpTLInfo->lcid = 0;
2089 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2090 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2095 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2096 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2097 ptiRet->impltypelist->hRef = tiBase.datatype1;
2102 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2104 TRACE_(typelib)("%s guid: %s kind:%s\n",
2105 debugstr_w(ptiRet->Name),
2106 debugstr_guid(&ptiRet->TypeAttr.guid),
2107 typekind_desc[ptiRet->TypeAttr.typekind]);
2112 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2113 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2114 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2117 static ITypeLibImpl *tlb_cache_first;
2118 static CRITICAL_SECTION cache_section;
2119 static CRITICAL_SECTION_DEBUG cache_section_debug =
2121 0, 0, &cache_section,
2122 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2123 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2125 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2128 /****************************************************************************
2131 * find the type of the typelib file and map the typelib resource into
2134 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2135 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2136 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2138 ITypeLibImpl *entry;
2139 int ret = TYPE_E_CANTLOADLIBRARY;
2140 DWORD dwSignature = 0;
2143 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2147 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2148 EnterCriticalSection(&cache_section);
2149 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2151 if (!strcmpiW(entry->path, pszFileName))
2153 TRACE("cache hit\n");
2154 *ppTypeLib = (ITypeLib2*)entry;
2155 ITypeLib_AddRef(*ppTypeLib);
2156 LeaveCriticalSection(&cache_section);
2160 LeaveCriticalSection(&cache_section);
2162 /* check the signature of the file */
2163 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2164 if (INVALID_HANDLE_VALUE != hFile)
2166 HANDLE hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2169 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2172 /* retrieve file size */
2173 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2175 /* first try to load as *.tlb */
2176 dwSignature = FromLEDWord(*((DWORD*) pBase));
2177 if ( dwSignature == MSFT_SIGNATURE)
2179 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2181 else if ( dwSignature == SLTG_SIGNATURE)
2183 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2185 UnmapViewOfFile(pBase);
2187 CloseHandle(hMapping);
2192 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2194 /* find the typelibrary resource*/
2195 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2196 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2199 HRSRC hrsrc = FindResourceA(hinstDLL, MAKEINTRESOURCEA(index),
2203 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2206 LPVOID pBase = LockResource(hGlobal);
2207 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2211 /* try to load as incore resource */
2212 dwSignature = FromLEDWord(*((DWORD*) pBase));
2213 if ( dwSignature == MSFT_SIGNATURE)
2215 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2217 else if ( dwSignature == SLTG_SIGNATURE)
2219 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2223 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2226 FreeResource( hGlobal );
2229 FreeLibrary(hinstDLL);
2234 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2236 TRACE("adding to cache\n");
2237 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2238 lstrcpyW(impl->path, pszFileName);
2239 /* We should really canonicalise the path here. */
2241 /* FIXME: check if it has added already in the meantime */
2242 EnterCriticalSection(&cache_section);
2243 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2245 tlb_cache_first = impl;
2246 LeaveCriticalSection(&cache_section);
2249 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2254 /*================== ITypeLib(2) Methods ===================================*/
2256 /****************************************************************************
2257 * ITypeLib2_Constructor_MSFT
2259 * loading an MSFT typelib from an in-memory image
2261 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2265 MSFT_Header tlbHeader;
2266 MSFT_SegDir tlbSegDir;
2267 ITypeLibImpl * pTypeLibImpl;
2269 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2271 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2272 if (!pTypeLibImpl) return NULL;
2274 pTypeLibImpl->lpVtbl = &tlbvt;
2275 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2276 pTypeLibImpl->ref = 1;
2278 /* get pointer to beginning of typelib data */
2282 cx.pLibInfo = pTypeLibImpl;
2283 cx.length = dwTLBLength;
2286 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2288 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2289 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2290 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2293 /* there is a small amount of information here until the next important
2295 * the segment directory . Try to calculate the amount of data */
2296 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2298 /* now read the segment directory */
2299 TRACE("read segment directory (at %ld)\n",lPSegDir);
2300 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2301 cx.pTblDir = &tlbSegDir;
2303 /* just check two entries */
2304 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2306 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2307 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2311 /* now fill our internal data */
2312 /* TLIBATTR fields */
2313 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2315 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2316 /* Windows seems to have zero here, is this correct? */
2317 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2318 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2320 pTypeLibImpl->LibAttr.lcid = 0;
2322 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2323 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2324 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2325 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2327 /* name, eventually add to a hash table */
2328 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2331 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2332 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2334 if( tlbHeader.varflags & HELPDLLFLAG)
2337 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2338 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2341 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2344 if(tlbHeader.CustomDataOffset >= 0)
2346 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2349 /* fill in typedescriptions */
2350 if(tlbSegDir.pTypdescTab.length > 0)
2352 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2354 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2355 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2358 /* FIXME: add several sanity checks here */
2359 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2360 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2362 /* FIXME: check safearray */
2364 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2366 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2368 else if(td[0] == VT_CARRAY)
2370 /* array descr table here */
2371 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2373 else if(td[0] == VT_USERDEFINED)
2375 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2377 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2380 /* second time around to fill the array subscript info */
2383 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2384 if(tlbSegDir.pArrayDescriptions.offset>0)
2386 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2387 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2390 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2392 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2394 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2396 for(j = 0; j<td[2]; j++)
2398 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2399 sizeof(INT), &cx, DO_NOT_SEEK);
2400 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2401 sizeof(INT), &cx, DO_NOT_SEEK);
2406 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2407 ERR("didn't find array description data\n");
2412 /* imported type libs */
2413 if(tlbSegDir.pImpFiles.offset>0)
2415 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2416 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2419 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2424 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2425 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2426 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2428 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2429 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2430 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2431 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2434 name = TLB_Alloc(size+1);
2435 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2436 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2437 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2438 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2441 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2442 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2444 ppImpLib = &(*ppImpLib)->next;
2449 if(tlbHeader.nrtypeinfos >= 0 )
2451 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2452 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2455 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2457 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2459 ITypeInfo_AddRef((ITypeInfo*) *ppTI);
2460 ppTI = &((*ppTI)->next);
2461 (pTypeLibImpl->TypeInfoCount)++;
2465 TRACE("(%p)\n", pTypeLibImpl);
2466 return (ITypeLib2*) pTypeLibImpl;
2470 static BSTR TLB_MultiByteToBSTR(char *ptr)
2476 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2477 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2478 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2479 ret = SysAllocString(nameW);
2480 HeapFree(GetProcessHeap(), 0, nameW);
2484 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2490 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2491 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2495 guid->Data4[0] = s >> 8;
2496 guid->Data4[1] = s & 0xff;
2499 for(i = 0; i < 6; i++) {
2500 memcpy(b, str + 24 + 2 * i, 2);
2501 guid->Data4[i + 2] = strtol(b, NULL, 16);
2506 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2513 bytelen = *(WORD*)ptr;
2514 if(bytelen == 0xffff) return 2;
2515 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2516 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2517 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2518 *pBstr = SysAllocStringLen(nameW, len);
2519 HeapFree(GetProcessHeap(), 0, nameW);
2523 static WORD SLTG_ReadStringA(char *ptr, char **str)
2528 bytelen = *(WORD*)ptr;
2529 if(bytelen == 0xffff) return 2;
2530 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2531 memcpy(*str, ptr + 2, bytelen);
2532 (*str)[bytelen] = '\0';
2536 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2538 char *ptr = pLibBlk;
2541 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2542 FIXME("libblk magic = %04x\n", w);
2547 if((w = *(WORD*)ptr) != 0xffff) {
2548 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2553 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2555 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2557 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2560 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2563 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2564 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2566 pTypeLibImpl->LibAttr.lcid = 0;
2569 ptr += 4; /* skip res12 */
2571 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2574 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2577 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2580 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2581 ptr += sizeof(GUID);
2583 return ptr - (char*)pLibBlk;
2586 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2589 TYPEDESC *pTD = &pElem->tdesc;
2591 /* Handle [in/out] first */
2592 if((*pType & 0xc000) == 0xc000)
2593 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2594 else if(*pType & 0x8000)
2595 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2596 else if(*pType & 0x4000)
2597 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2599 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2602 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2605 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2608 if((*pType & 0xe00) == 0xe00) {
2610 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2612 pTD = pTD->u.lptdesc;
2614 switch(*pType & 0x7f) {
2617 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2619 pTD = pTD->u.lptdesc;
2622 case VT_USERDEFINED:
2623 pTD->vt = VT_USERDEFINED;
2624 pTD->u.hreftype = *(++pType) / 4;
2630 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2633 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2635 pTD->vt = VT_CARRAY;
2636 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2638 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2639 pTD->u.lpadesc->cDims = pSA->cDims;
2640 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2641 pSA->cDims * sizeof(SAFEARRAYBOUND));
2643 pTD = &pTD->u.lpadesc->tdescElem;
2649 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2653 pTD->vt = VT_SAFEARRAY;
2654 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2656 pTD = pTD->u.lptdesc;
2660 pTD->vt = *pType & 0x7f;
2670 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2675 TLBRefType **ppRefType;
2677 if(pRef->magic != SLTG_REF_MAGIC) {
2678 FIXME("Ref magic = %x\n", pRef->magic);
2681 name = ( (char*)(&pRef->names) + pRef->number);
2683 ppRefType = &pTI->reflist;
2684 for(ref = 0; ref < pRef->number >> 3; ref++) {
2686 unsigned int lib_offs, type_num;
2688 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2689 sizeof(**ppRefType));
2691 name += SLTG_ReadStringA(name, &refname);
2692 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2693 FIXME("Can't sscanf ref\n");
2694 if(lib_offs != 0xffff) {
2695 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2698 if((*import)->offset == lib_offs)
2700 import = &(*import)->next;
2703 char fname[MAX_PATH+1];
2706 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2708 (*import)->offset = lib_offs;
2709 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2711 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2712 &(*import)->wVersionMajor,
2713 &(*import)->wVersionMinor,
2714 &(*import)->lcid, fname) != 4) {
2715 FIXME("can't sscanf ref %s\n",
2716 pNameTable + lib_offs + 40);
2718 len = strlen(fname);
2719 if(fname[len-1] != '#')
2720 FIXME("fname = %s\n", fname);
2721 fname[len-1] = '\0';
2722 (*import)->name = TLB_MultiByteToBSTR(fname);
2724 (*ppRefType)->pImpTLInfo = *import;
2725 } else { /* internal ref */
2726 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2728 (*ppRefType)->reference = ref;
2729 (*ppRefType)->index = type_num;
2731 HeapFree(GetProcessHeap(), 0, refname);
2732 ppRefType = &(*ppRefType)->next;
2734 if((BYTE)*name != SLTG_REF_MAGIC)
2735 FIXME("End of ref block magic = %x\n", *name);
2736 dump_TLBRefType(pTI->reflist);
2739 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2742 SLTG_ImplInfo *info;
2743 TLBImplType **ppImplType = &pTI->impltypelist;
2744 /* I don't really get this structure, usually it's 0x16 bytes
2745 long, but iuser.tlb contains some that are 0x18 bytes long.
2746 That's ok because we can use the next ptr to jump to the next
2747 one. But how do we know the length of the last one? The WORD
2748 at offs 0x8 might be the clue. For now I'm just assuming that
2749 the last one is the regular 0x16 bytes. */
2751 info = (SLTG_ImplInfo*)pBlk;
2753 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2754 sizeof(**ppImplType));
2755 (*ppImplType)->hRef = info->ref;
2756 (*ppImplType)->implflags = info->impltypeflags;
2757 pTI->TypeAttr.cImplTypes++;
2758 ppImplType = &(*ppImplType)->next;
2760 if(info->next == 0xffff)
2763 FIXME("Interface inheriting more than one interface\n");
2764 info = (SLTG_ImplInfo*)(pBlk + info->next);
2766 info++; /* see comment at top of function */
2770 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2773 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2774 SLTG_MemberHeader *pMemHeader;
2775 char *pFirstItem, *pNextItem;
2777 if(pTIHeader->href_table != 0xffffffff) {
2778 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2783 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2785 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2787 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2788 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2791 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2795 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2798 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2799 SLTG_MemberHeader *pMemHeader;
2800 SLTG_Function *pFunc;
2801 char *pFirstItem, *pNextItem;
2802 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2805 if(pTIHeader->href_table != 0xffffffff) {
2806 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2810 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2812 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2814 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2815 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2818 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2819 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2824 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2825 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2826 FIXME("func magic = %02x\n", pFunc->magic);
2829 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2830 sizeof(**ppFuncDesc));
2831 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2833 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2834 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2835 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2836 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2837 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2838 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2840 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2841 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2843 if(pFunc->retnextopt & 0x80)
2844 pType = &pFunc->rettype;
2846 pType = (WORD*)(pFirstItem + pFunc->rettype);
2849 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2851 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2852 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2853 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2854 (*ppFuncDesc)->pParamDesc =
2855 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2856 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2858 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2860 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2861 char *paramName = pNameTable + *pArg;
2863 /* If arg type follows then paramName points to the 2nd
2864 letter of the name, else the next WORD is an offset to
2865 the arg type and paramName points to the first letter.
2866 So let's take one char off paramName and see if we're
2867 pointing at an alpha-numeric char. However if *pArg is
2868 0xffff or 0xfffe then the param has no name, the former
2869 meaning that the next WORD is the type, the latter
2870 meaning the the next WORD is an offset to the type. */
2875 else if(*pArg == 0xfffe) {
2879 else if(!isalnum(*(paramName-1)))
2884 if(HaveOffs) { /* the next word is an offset to type */
2885 pType = (WORD*)(pFirstItem + *pArg);
2886 SLTG_DoType(pType, pFirstItem,
2887 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2892 pArg = SLTG_DoType(pArg, pFirstItem,
2893 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2896 /* Are we an optional param ? */
2897 if((*ppFuncDesc)->funcdesc.cParams - param <=
2898 (*ppFuncDesc)->funcdesc.cParamsOpt)
2899 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2902 (*ppFuncDesc)->pParamDesc[param].Name =
2903 TLB_MultiByteToBSTR(paramName);
2907 ppFuncDesc = &((*ppFuncDesc)->next);
2908 if(pFunc->next == 0xffff) break;
2910 pTI->TypeAttr.cFuncs = num;
2911 dump_TLBFuncDesc(pTI->funclist);
2912 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2915 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2918 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2919 SLTG_MemberHeader *pMemHeader;
2920 SLTG_RecordItem *pItem;
2922 TLBVarDesc **ppVarDesc = &pTI->varlist;
2927 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2929 pFirstItem = (char*)(pMemHeader + 1);
2930 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2931 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2932 if(pItem->magic != SLTG_RECORD_MAGIC) {
2933 FIXME("record magic = %02x\n", pItem->magic);
2936 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2937 sizeof(**ppVarDesc));
2938 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2939 (*ppVarDesc)->vardesc.memid = pItem->memid;
2940 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2941 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2943 if(pItem->typepos == 0x02)
2944 pType = &pItem->type;
2945 else if(pItem->typepos == 0x00)
2946 pType = (WORD*)(pFirstItem + pItem->type);
2948 FIXME("typepos = %02x\n", pItem->typepos);
2952 SLTG_DoType(pType, pFirstItem,
2953 &(*ppVarDesc)->vardesc.elemdescVar);
2955 /* FIXME("helpcontext, helpstring\n"); */
2957 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2959 ppVarDesc = &((*ppVarDesc)->next);
2960 if(pItem->next == 0xffff) break;
2962 pTI->TypeAttr.cVars = num;
2963 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2966 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
2969 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2970 SLTG_MemberHeader *pMemHeader;
2971 SLTG_AliasItem *pItem;
2974 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2975 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
2978 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
2979 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
2980 if (pItem->vt == 0xffff) {
2981 if (i<(pMemHeader->cbExtra/4-1))
2982 FIXME("Endmarker too early in process alias data!\n");
2986 FIXME("Chain extends over last entry?\n");
2989 if (pItem->vt == VT_USERDEFINED) {
2990 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
2991 /* guessing here ... */
2992 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
2993 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
2996 FIXME("alias %d: 0x%x\n",i,pItem->vt);
2997 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3001 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3004 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3007 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3008 SLTG_MemberHeader *pMemHeader;
3009 SLTG_AliasItem *pItem;
3011 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3012 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3013 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3014 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3015 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3018 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3021 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3022 SLTG_MemberHeader *pMemHeader;
3023 SLTG_EnumItem *pItem;
3025 TLBVarDesc **ppVarDesc = &pTI->varlist;
3028 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3030 pFirstItem = (char*)(pMemHeader + 1);
3031 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3032 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3033 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3034 FIXME("enumitem magic = %04x\n", pItem->magic);
3037 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3038 sizeof(**ppVarDesc));
3039 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3040 (*ppVarDesc)->vardesc.memid = pItem->memid;
3041 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3043 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3044 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3045 *(INT*)(pItem->value + pFirstItem);
3046 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3047 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3048 /* FIXME("helpcontext, helpstring\n"); */
3050 ppVarDesc = &((*ppVarDesc)->next);
3051 if(pItem->next == 0xffff) break;
3053 pTI->TypeAttr.cVars = num;
3054 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3057 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3058 managable copy of it into this */
3071 } SLTG_InternalOtherTypeInfo;
3073 /****************************************************************************
3074 * ITypeLib2_Constructor_SLTG
3076 * loading a SLTG typelib from an in-memory image
3078 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3080 ITypeLibImpl *pTypeLibImpl;
3081 SLTG_Header *pHeader;
3082 SLTG_BlkEntry *pBlkEntry;
3086 LPVOID pBlk, pFirstBlk;
3087 SLTG_LibBlk *pLibBlk;
3088 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3089 char *pAfterOTIBlks = NULL;
3090 char *pNameTable, *ptr;
3093 ITypeInfoImpl **ppTypeInfoImpl;
3095 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3097 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3098 if (!pTypeLibImpl) return NULL;
3100 pTypeLibImpl->lpVtbl = &tlbvt;
3101 pTypeLibImpl->ref = 1;
3106 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3107 pHeader->nrOfFileBlks );
3108 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3109 FIXME("Header type magic 0x%08lx not supported.\n",
3110 pHeader->SLTG_magic);
3114 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3115 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3117 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3118 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3120 /* Next we have a magic block */
3121 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3123 /* Let's see if we're still in sync */
3124 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3125 sizeof(SLTG_COMPOBJ_MAGIC))) {
3126 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3129 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3130 sizeof(SLTG_DIR_MAGIC))) {
3131 FIXME("dir magic = %s\n", pMagic->dir_magic);
3135 pIndex = (SLTG_Index*)(pMagic+1);
3137 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3139 pFirstBlk = (LPVOID)(pPad9 + 1);
3141 /* We'll set up a ptr to the main library block, which is the last one. */
3143 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3144 pBlkEntry[order].next != 0;
3145 order = pBlkEntry[order].next - 1, i++) {
3146 pBlk = (char*)pBlk + pBlkEntry[order].len;
3150 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3152 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3157 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3159 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3160 sizeof(*pOtherTypeInfoBlks) *
3161 pTypeLibImpl->TypeInfoCount);
3164 ptr = (char*)pLibBlk + len;
3166 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3170 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3172 w = *(WORD*)(ptr + 2);
3175 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3177 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3178 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3180 w = *(WORD*)(ptr + 4 + len);
3182 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3184 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3186 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3187 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3189 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3190 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3191 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3193 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3195 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3198 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3199 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3200 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3201 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3202 len += sizeof(SLTG_OtherTypeInfo);
3206 pAfterOTIBlks = ptr;
3208 /* Skip this WORD and get the next DWORD */
3209 len = *(DWORD*)(pAfterOTIBlks + 2);
3211 /* Now add this to pLibBLk look at what we're pointing at and
3212 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3213 dust and we should be pointing at the beginning of the name
3216 pNameTable = (char*)pLibBlk + len;
3218 switch(*(WORD*)pNameTable) {
3225 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3229 pNameTable += 0x216;
3233 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3235 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3238 /* Hopefully we now have enough ptrs set up to actually read in
3239 some TypeInfos. It's not clear which order to do them in, so
3240 I'll just follow the links along the BlkEntry chain and read
3241 them in in the order in which they're in the file */
3243 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3245 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3246 pBlkEntry[order].next != 0;
3247 order = pBlkEntry[order].next - 1, i++) {
3249 SLTG_TypeInfoHeader *pTIHeader;
3250 SLTG_TypeInfoTail *pTITail;
3252 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3253 pOtherTypeInfoBlks[i].index_name)) {
3254 FIXME("Index strings don't match\n");
3259 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3260 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3263 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3264 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3265 (*ppTypeInfoImpl)->index = i;
3266 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3267 pOtherTypeInfoBlks[i].name_offs +
3269 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3270 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3272 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3273 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3274 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3275 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3276 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3278 if((pTIHeader->typeflags1 & 7) != 2)
3279 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3280 if(pTIHeader->typeflags3 != 2)
3281 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3283 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3284 debugstr_w((*ppTypeInfoImpl)->Name),
3285 typekind_desc[pTIHeader->typekind],
3286 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3287 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3289 switch(pTIHeader->typekind) {
3291 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3295 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3298 case TKIND_INTERFACE:
3299 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3303 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3307 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3308 if (pTITail->tdescalias_vt)
3309 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3312 case TKIND_DISPATCH:
3313 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3317 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3323 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3324 but we've already set those */
3325 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3326 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3327 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3329 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3351 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3352 pBlk = (char*)pBlk + pBlkEntry[order].len;
3355 if(i != pTypeLibImpl->TypeInfoCount) {
3356 FIXME("Somehow processed %d TypeInfos\n", i);
3360 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3361 return (ITypeLib2*)pTypeLibImpl;
3364 /* ITypeLib::QueryInterface
3366 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3371 ICOM_THIS( ITypeLibImpl, iface);
3373 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3376 if(IsEqualIID(riid, &IID_IUnknown) ||
3377 IsEqualIID(riid,&IID_ITypeLib)||
3378 IsEqualIID(riid,&IID_ITypeLib2))
3385 ITypeLib2_AddRef(iface);
3386 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3389 TRACE("-- Interface: E_NOINTERFACE\n");
3390 return E_NOINTERFACE;
3395 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3397 ICOM_THIS( ITypeLibImpl, iface);
3399 TRACE("(%p)->ref was %u\n",This, This->ref);
3401 return ++(This->ref);
3404 /* ITypeLib::Release
3406 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3408 ICOM_THIS( ITypeLibImpl, iface);
3412 TRACE("(%p)->(%u)\n",This, This->ref);
3416 /* remove cache entry */
3417 TRACE("removing from cache list\n");
3418 EnterCriticalSection(&cache_section);
3419 if (This->next) This->next->prev = This->prev;
3420 if (This->prev) This->prev->next = This->next;
3421 else tlb_cache_first = This->next;
3422 LeaveCriticalSection(&cache_section);
3424 /* FIXME destroy child objects */
3425 TRACE(" destroying ITypeLib(%p)\n",This);
3429 SysFreeString(This->Name);
3433 if (This->DocString)
3435 SysFreeString(This->DocString);
3436 This->DocString = NULL;
3441 SysFreeString(This->HelpFile);
3442 This->HelpFile = NULL;
3445 if (This->HelpStringDll)
3447 SysFreeString(This->HelpStringDll);
3448 This->HelpStringDll = NULL;
3451 if (This->pTypeInfo) /* can be NULL */
3452 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3453 HeapFree(GetProcessHeap(),0,This);
3460 /* ITypeLib::GetTypeInfoCount
3462 * Returns the number of type descriptions in the type library
3464 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3466 ICOM_THIS( ITypeLibImpl, iface);
3467 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3468 return This->TypeInfoCount;
3471 /* ITypeLib::GetTypeInfo
3473 * retrieves the specified type description in the library.
3475 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3478 ITypeInfo **ppTInfo)
3482 ICOM_THIS( ITypeLibImpl, iface);
3483 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3485 TRACE("(%p)->(index=%d) \n", This, index);
3487 if (!ppTInfo) return E_INVALIDARG;
3489 /* search element n in list */
3490 for(i=0; i < index; i++)
3492 pTypeInfo = pTypeInfo->next;
3495 TRACE("-- element not found\n");
3496 return TYPE_E_ELEMENTNOTFOUND;
3500 *ppTInfo = (ITypeInfo *) pTypeInfo;
3502 ITypeInfo_AddRef(*ppTInfo);
3503 TRACE("-- found (%p)\n",*ppTInfo);
3508 /* ITypeLibs::GetTypeInfoType
3510 * Retrieves the type of a type description.
3512 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3517 ICOM_THIS( ITypeLibImpl, iface);
3519 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3521 TRACE("(%p) index %d \n",This, index);
3523 if(!pTKind) return E_INVALIDARG;
3525 /* search element n in list */
3526 for(i=0; i < index; i++)
3530 TRACE("-- element not found\n");
3531 return TYPE_E_ELEMENTNOTFOUND;
3533 pTInfo = pTInfo->next;
3536 *pTKind = pTInfo->TypeAttr.typekind;
3537 TRACE("-- found Type (%d)\n", *pTKind);
3541 /* ITypeLib::GetTypeInfoOfGuid
3543 * Retrieves the type description that corresponds to the specified GUID.
3546 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3549 ITypeInfo **ppTInfo)
3551 ICOM_THIS( ITypeLibImpl, iface);
3552 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3554 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3556 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3558 /* search linked list for guid */
3559 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3561 pTypeInfo = pTypeInfo->next;
3565 /* end of list reached */
3566 TRACE("-- element not found\n");
3567 return TYPE_E_ELEMENTNOTFOUND;
3571 TRACE("-- found (%p, %s)\n",
3573 debugstr_w(pTypeInfo->Name));
3575 *ppTInfo = (ITypeInfo*)pTypeInfo;
3576 ITypeInfo_AddRef(*ppTInfo);
3580 /* ITypeLib::GetLibAttr
3582 * Retrieves the structure that contains the library's attributes.
3585 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3587 LPTLIBATTR *ppTLibAttr)
3589 ICOM_THIS( ITypeLibImpl, iface);
3590 TRACE("(%p)\n",This);
3591 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3592 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3596 /* ITypeLib::GetTypeComp
3598 * Enables a client compiler to bind to a library's types, variables,
3599 * constants, and global functions.
3602 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3604 ITypeComp **ppTComp)
3606 ICOM_THIS( ITypeLibImpl, iface);
3608 TRACE("(%p)->(%p)\n",This,ppTComp);
3609 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3610 ITypeComp_AddRef(*ppTComp);
3615 /* ITypeLib::GetDocumentation
3617 * Retrieves the library's documentation string, the complete Help file name
3618 * and path, and the context identifier for the library Help topic in the Help
3621 * On a successful return all non-null BSTR pointers will have been set,
3624 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3628 BSTR *pBstrDocString,
3629 DWORD *pdwHelpContext,
3630 BSTR *pBstrHelpFile)
3632 ICOM_THIS( ITypeLibImpl, iface);
3634 HRESULT result = E_INVALIDARG;
3639 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3641 pBstrName, pBstrDocString,
3642 pdwHelpContext, pBstrHelpFile);
3646 /* documentation for the typelib */
3650 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3656 if (This->DocString)
3657 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3658 else if (This->Name)
3659 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3661 *pBstrDocString = NULL;
3665 *pdwHelpContext = This->dwHelpContext;
3670 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3672 *pBstrHelpFile = NULL;
3679 /* for a typeinfo */
3680 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3682 if(SUCCEEDED(result))
3684 result = ITypeInfo_GetDocumentation(pTInfo,
3688 pdwHelpContext, pBstrHelpFile);
3690 ITypeInfo_Release(pTInfo);
3695 if (pBstrDocString) SysFreeString (*pBstrDocString);
3697 if (pBstrName) SysFreeString (*pBstrName);
3699 return STG_E_INSUFFICIENTMEMORY;
3704 * Indicates whether a passed-in string contains the name of a type or member
3705 * described in the library.
3708 static HRESULT WINAPI ITypeLib2_fnIsName(
3714 ICOM_THIS( ITypeLibImpl, iface);
3715 ITypeInfoImpl *pTInfo;
3716 TLBFuncDesc *pFInfo;
3719 UINT nNameBufLen = SysStringLen(szNameBuf);
3721 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3725 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3726 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3727 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3728 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3729 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3730 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3731 goto ITypeLib2_fnIsName_exit;
3733 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3734 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3739 ITypeLib2_fnIsName_exit:
3740 TRACE("(%p)slow! search for %s: %s found!\n", This,
3741 debugstr_w(szNameBuf), *pfName?"NOT":"");
3746 /* ITypeLib::FindName
3748 * Finds occurrences of a type description in a type library. This may be used
3749 * to quickly verify that a name exists in a type library.
3752 static HRESULT WINAPI ITypeLib2_fnFindName(
3756 ITypeInfo **ppTInfo,
3760 ICOM_THIS( ITypeLibImpl, iface);
3761 ITypeInfoImpl *pTInfo;
3762 TLBFuncDesc *pFInfo;
3766 UINT nNameBufLen = SysStringLen(szNameBuf);
3768 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3769 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3770 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3771 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3772 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3773 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3774 goto ITypeLib2_fnFindName_exit;
3776 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3777 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3779 ITypeLib2_fnFindName_exit:
3780 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3781 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3784 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3785 This, *pcFound, debugstr_w(szNameBuf), j);
3792 /* ITypeLib::ReleaseTLibAttr
3794 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3797 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3799 TLIBATTR *pTLibAttr)
3801 ICOM_THIS( ITypeLibImpl, iface);
3802 TRACE("freeing (%p)\n",This);
3803 HeapFree(GetProcessHeap(),0,pTLibAttr);
3807 /* ITypeLib2::GetCustData
3809 * gets the custom data
3811 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3816 ICOM_THIS( ITypeLibImpl, iface);
3817 TLBCustData *pCData;
3819 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3821 if( IsEqualIID(guid, &pCData->guid)) break;
3824 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3828 VariantInit( pVarVal);
3829 VariantCopy( pVarVal, &pCData->data);
3832 return E_INVALIDARG; /* FIXME: correct? */
3835 /* ITypeLib2::GetLibStatistics
3837 * Returns statistics about a type library that are required for efficient
3838 * sizing of hash tables.
3841 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3843 ULONG *pcUniqueNames,
3844 ULONG *pcchUniqueNames)
3846 ICOM_THIS( ITypeLibImpl, iface);
3848 FIXME("(%p): stub!\n", This);
3850 if(pcUniqueNames) *pcUniqueNames=1;
3851 if(pcchUniqueNames) *pcchUniqueNames=1;
3855 /* ITypeLib2::GetDocumentation2
3857 * Retrieves the library's documentation string, the complete Help file name
3858 * and path, the localization context to use, and the context ID for the
3859 * library Help topic in the Help file.
3862 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3866 BSTR *pbstrHelpString,
3867 DWORD *pdwHelpStringContext,
3868 BSTR *pbstrHelpStringDll)
3870 ICOM_THIS( ITypeLibImpl, iface);
3874 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3876 /* the help string should be obtained from the helpstringdll,
3877 * using the _DLLGetDocumentation function, based on the supplied
3878 * lcid. Nice to do sometime...
3882 /* documentation for the typelib */
3884 *pbstrHelpString=SysAllocString(This->DocString);
3885 if(pdwHelpStringContext)
3886 *pdwHelpStringContext=This->dwHelpContext;
3887 if(pbstrHelpStringDll)
3888 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3894 /* for a typeinfo */
3895 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3897 if(SUCCEEDED(result))
3899 ITypeInfo2 * pTInfo2;
3900 result = ITypeInfo_QueryInterface(pTInfo,
3902 (LPVOID*) &pTInfo2);
3904 if(SUCCEEDED(result))
3906 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3910 pdwHelpStringContext,
3911 pbstrHelpStringDll);
3913 ITypeInfo2_Release(pTInfo2);
3916 ITypeInfo_Release(pTInfo);
3922 /* ITypeLib2::GetAllCustData
3924 * Gets all custom data items for the library.
3927 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3929 CUSTDATA *pCustData)
3931 ICOM_THIS( ITypeLibImpl, iface);
3932 TLBCustData *pCData;
3934 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3935 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3936 if(pCustData->prgCustData ){
3937 pCustData->cCustData=This->ctCustData;
3938 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3939 pCustData->prgCustData[i].guid=pCData->guid;
3940 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3943 ERR(" OUT OF MEMORY! \n");
3944 return E_OUTOFMEMORY;
3949 static ICOM_VTABLE(ITypeLib2) tlbvt = {
3950 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3951 ITypeLib2_fnQueryInterface,
3953 ITypeLib2_fnRelease,
3954 ITypeLib2_fnGetTypeInfoCount,
3955 ITypeLib2_fnGetTypeInfo,
3956 ITypeLib2_fnGetTypeInfoType,
3957 ITypeLib2_fnGetTypeInfoOfGuid,
3958 ITypeLib2_fnGetLibAttr,
3959 ITypeLib2_fnGetTypeComp,
3960 ITypeLib2_fnGetDocumentation,
3962 ITypeLib2_fnFindName,
3963 ITypeLib2_fnReleaseTLibAttr,
3965 ITypeLib2_fnGetCustData,
3966 ITypeLib2_fnGetLibStatistics,
3967 ITypeLib2_fnGetDocumentation2,
3968 ITypeLib2_fnGetAllCustData
3972 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
3974 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3976 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
3979 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
3981 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3983 return ITypeInfo_AddRef((ITypeInfo *)This);
3986 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
3988 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
3990 return ITypeInfo_Release((ITypeInfo *)This);
3993 static HRESULT WINAPI ITypeLibComp_fnBind(
3996 unsigned long lHash,
3997 unsigned short wFlags,
3998 ITypeInfo ** ppTInfo,
3999 DESCKIND * pDescKind,
4002 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4006 static HRESULT WINAPI ITypeLibComp_fnBindType(
4009 unsigned long lHash,
4010 ITypeInfo ** ppTInfo,
4011 ITypeComp ** ppTComp)
4013 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4017 static ICOM_VTABLE(ITypeComp) tlbtcvt =
4019 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
4021 ITypeLibComp_fnQueryInterface,
4022 ITypeLibComp_fnAddRef,
4023 ITypeLibComp_fnRelease,
4025 ITypeLibComp_fnBind,
4026 ITypeLibComp_fnBindType
4029 /*================== ITypeInfo(2) Methods ===================================*/
4030 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4032 ITypeInfoImpl * pTypeInfoImpl;
4034 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4037 pTypeInfoImpl->lpVtbl = &tinfvt;
4038 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4039 pTypeInfoImpl->ref=1;
4041 TRACE("(%p)\n", pTypeInfoImpl);
4042 return (ITypeInfo2*) pTypeInfoImpl;
4045 /* ITypeInfo::QueryInterface
4047 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4052 ICOM_THIS( ITypeLibImpl, iface);
4054 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4057 if(IsEqualIID(riid, &IID_IUnknown) ||
4058 IsEqualIID(riid,&IID_ITypeInfo)||
4059 IsEqualIID(riid,&IID_ITypeInfo2))
4063 ITypeInfo_AddRef(iface);
4064 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4067 TRACE("-- Interface: E_NOINTERFACE\n");
4068 return E_NOINTERFACE;
4071 /* ITypeInfo::AddRef
4073 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4075 ICOM_THIS( ITypeInfoImpl, iface);
4079 TRACE("(%p)->ref is %u\n",This, This->ref);
4083 /* ITypeInfo::Release
4085 static ULONG WINAPI ITypeInfo_fnRelease( ITypeInfo2 *iface)
4087 ICOM_THIS( ITypeInfoImpl, iface);
4091 TRACE("(%p)->(%u)\n",This, This->ref);
4095 FIXME("destroy child objects\n");
4097 TRACE("destroying ITypeInfo(%p)\n",This);
4100 SysFreeString(This->Name);
4104 if (This->DocString)
4106 SysFreeString(This->DocString);
4107 This->DocString = 0;
4112 ITypeInfo_Release((ITypeInfo*)This->next);
4115 HeapFree(GetProcessHeap(),0,This);
4121 /* ITypeInfo::GetTypeAttr
4123 * Retrieves a TYPEATTR structure that contains the attributes of the type
4127 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4128 LPTYPEATTR *ppTypeAttr)
4130 ICOM_THIS( ITypeInfoImpl, iface);
4131 TRACE("(%p)\n",This);
4132 /* FIXME: must do a copy here */
4133 *ppTypeAttr=&This->TypeAttr;
4137 /* ITypeInfo::GetTypeComp
4139 * Retrieves the ITypeComp interface for the type description, which enables a
4140 * client compiler to bind to the type description's members.
4143 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4144 ITypeComp * *ppTComp)
4146 ICOM_THIS( ITypeInfoImpl, iface);
4148 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4150 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4151 ITypeComp_AddRef(*ppTComp);
4155 /* ITypeInfo::GetFuncDesc
4157 * Retrieves the FUNCDESC structure that contains information about a
4158 * specified function.
4161 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4162 LPFUNCDESC *ppFuncDesc)
4164 ICOM_THIS( ITypeInfoImpl, iface);
4166 TLBFuncDesc * pFDesc;
4167 TRACE("(%p) index %d\n", This, index);
4168 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4171 /* FIXME: must do a copy here */
4172 *ppFuncDesc=&pFDesc->funcdesc;
4175 return E_INVALIDARG;
4178 /* ITypeInfo::GetVarDesc
4180 * Retrieves a VARDESC structure that describes the specified variable.
4183 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4184 LPVARDESC *ppVarDesc)
4186 ICOM_THIS( ITypeInfoImpl, iface);
4188 TLBVarDesc * pVDesc;
4189 TRACE("(%p) index %d\n", This, index);
4190 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4193 /* FIXME: must do a copy here */
4194 *ppVarDesc=&pVDesc->vardesc;
4197 return E_INVALIDARG;
4200 /* ITypeInfo_GetNames
4202 * Retrieves the variable with the specified member ID (or the name of the
4203 * property or method and its parameters) that correspond to the specified
4206 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4207 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4209 ICOM_THIS( ITypeInfoImpl, iface);
4210 TLBFuncDesc * pFDesc;
4211 TLBVarDesc * pVDesc;
4213 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4214 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4217 /* function found, now return function and parameter names */
4218 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4221 *rgBstrNames=SysAllocString(pFDesc->Name);
4223 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4229 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4232 *rgBstrNames=SysAllocString(pVDesc->Name);
4237 if(This->TypeAttr.cImplTypes &&
4238 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4239 /* recursive search */
4242 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4244 if(SUCCEEDED(result))
4246 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4247 ITypeInfo_Release(pTInfo);
4250 WARN("Could not search inherited interface!\n");
4254 WARN("no names found\n");
4257 return TYPE_E_ELEMENTNOTFOUND;
4264 /* ITypeInfo::GetRefTypeOfImplType
4266 * If a type description describes a COM class, it retrieves the type
4267 * description of the implemented interface types. For an interface,
4268 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4272 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4277 ICOM_THIS( ITypeInfoImpl, iface);
4279 TLBImplType *pImpl = This->impltypelist;
4281 TRACE("(%p) index %d\n", This, index);
4282 if (TRACE_ON(ole)) dump_TypeInfo(This);
4286 /* only valid on dual interfaces;
4287 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4289 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4291 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4292 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4298 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4299 *pRefType = pImpl->hRef;
4304 /* get element n from linked list */
4305 for(i=0; pImpl && i<index; i++)
4307 pImpl = pImpl->next;
4310 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4312 *pRefType = pImpl->hRef;
4314 TRACE("-- 0x%08lx\n", pImpl->hRef );
4321 /* ITypeInfo::GetImplTypeFlags
4323 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4324 * or base interface in a type description.
4326 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4327 UINT index, INT *pImplTypeFlags)
4329 ICOM_THIS( ITypeInfoImpl, iface);
4333 TRACE("(%p) index %d\n", This, index);
4334 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4335 i++, pImpl=pImpl->next)
4337 if(i==index && pImpl){
4338 *pImplTypeFlags=pImpl->implflags;
4342 return TYPE_E_ELEMENTNOTFOUND;
4346 * Maps between member names and member IDs, and parameter names and
4349 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4350 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4352 ICOM_THIS( ITypeInfoImpl, iface);
4353 TLBFuncDesc * pFDesc;
4354 TLBVarDesc * pVDesc;
4357 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4359 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4361 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4362 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4363 for(i=1; i < cNames; i++){
4364 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4365 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4367 if( j<pFDesc->funcdesc.cParams)
4370 ret=DISP_E_UNKNOWNNAME;
4375 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4376 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4377 if(cNames) *pMemId=pVDesc->vardesc.memid;
4381 /* not found, see if this is and interface with an inheritance */
4382 if(This->TypeAttr.cImplTypes &&
4383 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4384 /* recursive search */
4386 ret=ITypeInfo_GetRefTypeInfo(iface,
4387 This->impltypelist->hRef, &pTInfo);
4389 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4390 ITypeInfo_Release(pTInfo);
4393 WARN("Could not search inherited interface!\n");
4395 WARN("no names found\n");
4396 return DISP_E_UNKNOWNNAME;
4399 /* ITypeInfo::Invoke
4401 * Invokes a method, or accesses a property of an object, that implements the
4402 * interface described by the type description.
4405 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4408 if (TRACE_ON(ole)) {
4410 TRACE("Calling %p(",func);
4411 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4423 res = func(args[0]);
4426 res = func(args[0],args[1]);
4429 res = func(args[0],args[1],args[2]);
4432 res = func(args[0],args[1],args[2],args[3]);
4435 res = func(args[0],args[1],args[2],args[3],args[4]);
4438 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4441 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4444 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4447 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4450 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4453 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4456 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4462 FIXME("unsupported calling convention %d\n",callconv);
4466 TRACE("returns %08lx\n",res);
4470 extern int const _argsize(DWORD vt);
4472 /****************************************************************************
4473 * Helper functions for Dispcall / Invoke, which copies one variant
4474 * with target type onto the argument stack.
4477 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4478 DWORD *argpos, VARIANT *arg, VARTYPE vt
4480 UINT arglen = _argsize(vt)*sizeof(DWORD);
4484 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4485 memcpy(argpos,&arg,sizeof(void*));
4489 if (V_VT(arg) == vt) {
4490 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4494 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4495 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4499 if (vt == VT_VARIANT) {
4500 memcpy(argpos, arg, arglen);
4503 /* Deref BYREF vars if there is need */
4504 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4505 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4508 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4509 /* in this context, if the type lib specifies IUnknown*, giving an IDispatch* is correct; so, don't invoke VariantChangeType */
4510 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4513 if ((vt == VT_PTR) && tdesc)
4514 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4516 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4521 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4523 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing from vt 0x%x. Copying 4 byte.\n",tdesc->u.hreftype,V_VT(arg));
4524 memcpy(argpos, &V_UNION(arg,lVal), 4);
4527 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4528 switch (tattr->typekind) {
4530 switch ( V_VT( arg ) ) {
4532 *argpos = V_UNION(arg,iVal);
4535 memcpy(argpos, &V_UNION(arg,lVal), 4);
4538 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4543 tdesc = &(tattr->tdescAlias);
4544 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4545 ITypeInfo_Release(tinfo2);
4548 case TKIND_INTERFACE:
4549 if (V_VT(arg) == VT_DISPATCH) {
4551 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4552 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4555 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),&IID_IDispatch,(LPVOID*)&disp);
4556 if (SUCCEEDED(hres)) {
4557 memcpy(argpos,&disp,4);
4558 IUnknown_Release(V_UNION(arg,pdispVal));
4561 FIXME("Failed to query IDispatch interface from %s while converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4564 if (V_VT(arg) == VT_UNKNOWN) {
4565 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4568 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",V_VT(arg),debugstr_guid(&(tattr->guid)));
4570 case TKIND_DISPATCH:
4571 if (V_VT(arg) == VT_DISPATCH) {
4572 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4575 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4578 FIXME("TKIND_RECORD unhandled.\n");
4581 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4589 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4590 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4591 FIXME("Should not use VariantChangeType here. (conversion from 0x%x -> 0x%x)\n",
4596 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4600 /***********************************************************************
4601 * DispCallFunc (OLEAUT32.@)
4605 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4606 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4608 int i, argsize, argspos;
4612 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4613 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4615 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4616 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4618 for (i=0;i<cActuals;i++) {
4619 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4620 dump_Variant(prgpvarg[i]);
4621 argsize += _argsize(prgvt[i]);
4623 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4624 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4626 for (i=0;i<cActuals;i++) {
4627 VARIANT *arg = prgpvarg[i];
4628 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4629 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4630 argspos += _argsize(prgvt[i]);
4633 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4635 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4640 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4641 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4642 FIXME("Method returned %lx\n",hres);
4644 HeapFree(GetProcessHeap(),0,args);
4648 static HRESULT WINAPI ITypeInfo_fnInvoke(
4653 DISPPARAMS *pDispParams,
4654 VARIANT *pVarResult,
4655 EXCEPINFO *pExcepInfo,
4658 ICOM_THIS( ITypeInfoImpl, iface);
4659 TLBFuncDesc * pFDesc;
4660 TLBVarDesc * pVDesc;
4664 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4665 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4667 dump_DispParms(pDispParams);
4669 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4670 if (pFDesc->funcdesc.memid == memid) {
4671 if (pFDesc->funcdesc.invkind & dwFlags)
4676 if (TRACE_ON(typelib)) dump_TLBFuncDescOne(pFDesc);
4677 /* dump_FUNCDESC(&pFDesc->funcdesc);*/
4678 switch (pFDesc->funcdesc.funckind) {
4679 case FUNC_PUREVIRTUAL:
4680 case FUNC_VIRTUAL: {
4682 int numargs, numargs2, argspos, args2pos;
4683 DWORD *args , *args2;
4686 numargs = 1; numargs2 = 0;
4687 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4688 if (i<pDispParams->cArgs)
4689 numargs += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4691 numargs += 1; /* sizeof(lpvoid) */
4692 numargs2 += _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4696 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4697 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4699 args[0] = (DWORD)pIUnk;
4700 argspos = 1; args2pos = 0;
4701 for (i=0;i<pFDesc->funcdesc.cParams;i++) {
4702 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4703 if (i<pDispParams->cArgs) {
4704 VARIANT *arg = &pDispParams->rgvarg[pDispParams->cArgs-i-1];
4705 TYPEDESC *tdesc = &pFDesc->funcdesc.lprgelemdescParam[i].tdesc;
4706 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4707 if (FAILED(hres)) return hres;
4710 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i].tdesc);
4711 if (tdesc->vt != VT_PTR)
4712 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4713 /*FIXME: give pointers for the rest, so propertyget works*/
4714 args[argspos] = (DWORD)&args2[args2pos];
4716 /* If pointer to variant, pass reference it. */
4717 if ((tdesc->vt == VT_PTR) &&
4718 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4721 args[argspos]= (DWORD)pVarResult;
4726 if (pFDesc->funcdesc.cParamsOpt)
4727 FIXME("Does not support optional parameters (%d)\n",
4728 pFDesc->funcdesc.cParamsOpt
4731 res = _invoke((*(FARPROC**)pIUnk)[pFDesc->funcdesc.oVft/4],
4732 pFDesc->funcdesc.callconv,
4736 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4738 for (i=0;i<pFDesc->funcdesc.cParams-pDispParams->cArgs;i++) {
4739 int arglen = _argsize(pFDesc->funcdesc.lprgelemdescParam[i].tdesc.vt);
4740 TYPEDESC *tdesc = &(pFDesc->funcdesc.lprgelemdescParam[i+pDispParams->cArgs].tdesc);
4742 i4_tdesc.vt = VT_I4;
4744 /* If we are a pointer to a variant, we are done already */
4745 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4748 VariantInit(pVarResult);
4749 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4751 if (tdesc->vt == VT_PTR)
4752 tdesc = tdesc->u.lptdesc;
4753 if (tdesc->vt == VT_USERDEFINED) {
4757 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4759 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4762 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4763 switch (tattr->typekind) {
4765 /* force the return type to be VT_I4 */
4769 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4770 tdesc = &(tattr->tdescAlias);
4773 case TKIND_INTERFACE:
4774 FIXME("TKIND_INTERFACE unhandled.\n");
4776 case TKIND_DISPATCH:
4777 FIXME("TKIND_DISPATCH unhandled.\n");
4780 FIXME("TKIND_RECORD unhandled.\n");
4783 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4786 ITypeInfo_Release(tinfo2);
4788 V_VT(pVarResult) = tdesc->vt;
4790 /* HACK: VB5 likes this.
4791 * I do not know why. There is 1 example in MSDN which uses
4792 * this which appears broken (mixes int vals and
4795 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4796 V_VT(pVarResult) = VT_DISPATCH;
4797 TRACE("storing into variant:\n");
4798 dump_Variant(pVarResult);
4802 HeapFree(GetProcessHeap(),0,args2);
4803 HeapFree(GetProcessHeap(),0,args);
4806 case FUNC_DISPATCH: {
4810 hr = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4812 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4815 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4816 hr = IDispatch_Invoke(
4817 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4818 pVarResult,pExcepInfo,pArgErr
4821 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n",hr);
4822 IDispatch_Release(disp);
4826 FIXME("Unknown function invocation type %d\n",pFDesc->funcdesc.funckind);
4830 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4831 if (pVDesc->vardesc.memid == memid) {
4832 FIXME("varseek: Found memid name %s, but variable-based invoking not supported\n",debugstr_w(((LPWSTR)pVDesc->Name)));
4833 dump_TLBVarDesc(pVDesc);
4838 /* not found, look for it in inherited interfaces */
4839 if (This->TypeAttr.cImplTypes &&
4840 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4841 /* recursive search */
4844 hr=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
4846 hr=ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4847 ITypeInfo_Release(pTInfo);
4850 WARN("Could not search inherited interface!\n");
4852 ERR("did not find member id %d, flags %d!\n", (int)memid, dwFlags);
4853 return DISP_E_MEMBERNOTFOUND;
4856 /* ITypeInfo::GetDocumentation
4858 * Retrieves the documentation string, the complete Help file name and path,
4859 * and the context ID for the Help topic for a specified type description.
4861 * (Can be tested by the Visual Basic Editor in Word for instance.)
4863 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4864 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4865 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4867 ICOM_THIS( ITypeInfoImpl, iface);
4868 TLBFuncDesc * pFDesc;
4869 TLBVarDesc * pVDesc;
4870 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4871 " HelpContext(%p) HelpFile(%p)\n",
4872 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4873 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4875 *pBstrName=SysAllocString(This->Name);
4877 *pBstrDocString=SysAllocString(This->DocString);
4879 *pdwHelpContext=This->dwHelpContext;
4881 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
4883 }else {/* for a member */
4884 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4885 if(pFDesc->funcdesc.memid==memid){
4887 *pBstrName = SysAllocString(pFDesc->Name);
4889 *pBstrDocString=SysAllocString(pFDesc->HelpString);
4891 *pdwHelpContext=pFDesc->helpcontext;
4894 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
4895 if(pVDesc->vardesc.memid==memid){
4897 *pBstrName = SysAllocString(pVDesc->Name);
4899 *pBstrDocString=SysAllocString(pVDesc->HelpString);
4901 *pdwHelpContext=pVDesc->HelpContext;
4905 return TYPE_E_ELEMENTNOTFOUND;
4908 /* ITypeInfo::GetDllEntry
4910 * Retrieves a description or specification of an entry point for a function
4913 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
4914 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
4917 ICOM_THIS( ITypeInfoImpl, iface);
4918 TLBFuncDesc *pFDesc;
4920 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
4922 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
4923 if(pFDesc->funcdesc.memid==memid){
4924 dump_TypeInfo(This);
4925 dump_TLBFuncDescOne(pFDesc);
4927 /* FIXME: This is wrong, but how do you find that out? */
4929 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
4930 *pBstrDllName = SysAllocString(oleaut32W);
4933 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
4935 *pBstrName = SysAllocString(pFDesc->Entry);
4943 *pwOrdinal = (DWORD)pFDesc->Entry;
4949 /* ITypeInfo::GetRefTypeInfo
4951 * If a type description references other type descriptions, it retrieves
4952 * the referenced type descriptions.
4954 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
4957 ITypeInfo **ppTInfo)
4959 ICOM_THIS( ITypeInfoImpl, iface);
4960 HRESULT result = E_FAIL;
4963 if (hRefType == -1 &&
4964 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
4965 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4967 /* when we meet a DUAL dispinterface, we must create the interface
4970 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
4973 /* the interface version contains the same information as the dispinterface
4974 * copy the contents of the structs.
4976 *pTypeInfoImpl = *This;
4977 pTypeInfoImpl->ref = 1;
4979 /* change the type to interface */
4980 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
4982 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
4984 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
4989 TLBRefType *pRefType;
4990 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
4991 if(pRefType->reference == hRefType)
4995 FIXME("Can't find pRefType for ref %lx\n", hRefType);
4996 if(pRefType && hRefType != -1) {
4997 ITypeLib *pTLib = NULL;
4999 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5001 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5003 if(pRefType->pImpTLInfo->pImpTypeLib) {
5004 TRACE("typeinfo in imported typelib that is already loaded\n");
5005 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5006 ITypeLib2_AddRef((ITypeLib*) pTLib);
5009 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5010 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5011 pRefType->pImpTLInfo->wVersionMajor,
5012 pRefType->pImpTLInfo->wVersionMinor,
5013 pRefType->pImpTLInfo->lcid,
5016 if(!SUCCEEDED(result)) {
5017 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5018 result=LoadTypeLib(libnam, &pTLib);
5019 SysFreeString(libnam);
5021 if(SUCCEEDED(result)) {
5022 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5023 ITypeLib2_AddRef(pTLib);
5027 if(SUCCEEDED(result)) {
5028 if(pRefType->index == TLB_REF_USE_GUID)
5029 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5033 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5037 ITypeLib2_Release(pTLib);
5041 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5042 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5046 /* ITypeInfo::AddressOfMember
5048 * Retrieves the addresses of static functions or variables, such as those
5051 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5052 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5054 ICOM_THIS( ITypeInfoImpl, iface);
5055 FIXME("(%p) stub!\n", This);
5059 /* ITypeInfo::CreateInstance
5061 * Creates a new instance of a type that describes a component object class
5064 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5065 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5067 ICOM_THIS( ITypeInfoImpl, iface);
5068 FIXME("(%p) stub!\n", This);
5072 /* ITypeInfo::GetMops
5074 * Retrieves marshalling information.
5076 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5079 ICOM_THIS( ITypeInfoImpl, iface);
5080 FIXME("(%p) stub!\n", This);
5084 /* ITypeInfo::GetContainingTypeLib
5086 * Retrieves the containing type library and the index of the type description
5087 * within that type library.
5089 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5090 ITypeLib * *ppTLib, UINT *pIndex)
5092 ICOM_THIS( ITypeInfoImpl, iface);
5094 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5096 *pIndex=This->index;
5097 TRACE("returning pIndex=%d\n", *pIndex);
5101 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5102 ITypeLib2_AddRef(*ppTLib);
5103 TRACE("returning ppTLib=%p\n", *ppTLib);
5109 /* ITypeInfo::ReleaseTypeAttr
5111 * Releases a TYPEATTR previously returned by GetTypeAttr.
5114 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5115 TYPEATTR* pTypeAttr)
5117 ICOM_THIS( ITypeInfoImpl, iface);
5118 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5121 /* ITypeInfo::ReleaseFuncDesc
5123 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5125 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5127 FUNCDESC *pFuncDesc)
5129 ICOM_THIS( ITypeInfoImpl, iface);
5130 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5133 /* ITypeInfo::ReleaseVarDesc
5135 * Releases a VARDESC previously returned by GetVarDesc.
5137 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5140 ICOM_THIS( ITypeInfoImpl, iface);
5141 TRACE("(%p)->(%p)\n", This, pVarDesc);
5144 /* ITypeInfo2::GetTypeKind
5146 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5149 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5150 TYPEKIND *pTypeKind)
5152 ICOM_THIS( ITypeInfoImpl, iface);
5153 *pTypeKind=This->TypeAttr.typekind;
5154 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5158 /* ITypeInfo2::GetTypeFlags
5160 * Returns the type flags without any allocations. This returns a DWORD type
5161 * flag, which expands the type flags without growing the TYPEATTR (type
5165 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5167 ICOM_THIS( ITypeInfoImpl, iface);
5168 *pTypeFlags=This->TypeAttr.wTypeFlags;
5169 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5173 /* ITypeInfo2::GetFuncIndexOfMemId
5174 * Binds to a specific member based on a known DISPID, where the member name
5175 * is not known (for example, when binding to a default member).
5178 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5179 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5181 ICOM_THIS( ITypeInfoImpl, iface);
5182 TLBFuncDesc *pFuncInfo;
5185 /* FIXME: should check for invKind??? */
5186 for(i=0, pFuncInfo=This->funclist;pFuncInfo &&
5187 memid != pFuncInfo->funcdesc.memid; i++, pFuncInfo=pFuncInfo->next);
5193 result=E_INVALIDARG;
5195 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5196 memid, invKind, SUCCEEDED(result)? "SUCCES":"FAILED");
5200 /* TypeInfo2::GetVarIndexOfMemId
5202 * Binds to a specific member based on a known DISPID, where the member name
5203 * is not known (for example, when binding to a default member).
5206 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5207 MEMBERID memid, UINT *pVarIndex)
5209 ICOM_THIS( ITypeInfoImpl, iface);
5210 TLBVarDesc *pVarInfo;
5213 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5214 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5221 result=E_INVALIDARG;
5223 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5224 memid, SUCCEEDED(result)? "SUCCES":"FAILED");
5228 /* ITypeInfo2::GetCustData
5230 * Gets the custom data
5232 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5237 ICOM_THIS( ITypeInfoImpl, iface);
5238 TLBCustData *pCData;
5240 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5241 if( IsEqualIID(guid, &pCData->guid)) break;
5243 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5247 VariantInit( pVarVal);
5248 VariantCopy( pVarVal, &pCData->data);
5251 return E_INVALIDARG; /* FIXME: correct? */
5254 /* ITypeInfo2::GetFuncCustData
5256 * Gets the custom data
5258 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5264 ICOM_THIS( ITypeInfoImpl, iface);
5265 TLBCustData *pCData=NULL;
5266 TLBFuncDesc * pFDesc;
5268 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5269 pFDesc=pFDesc->next);
5272 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5273 if( IsEqualIID(guid, &pCData->guid)) break;
5275 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5278 VariantInit( pVarVal);
5279 VariantCopy( pVarVal, &pCData->data);
5282 return E_INVALIDARG; /* FIXME: correct? */
5285 /* ITypeInfo2::GetParamCustData
5287 * Gets the custom data
5289 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5296 ICOM_THIS( ITypeInfoImpl, iface);
5297 TLBCustData *pCData=NULL;
5298 TLBFuncDesc * pFDesc;
5301 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5303 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5304 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5305 pCData = pCData->next)
5306 if( IsEqualIID(guid, &pCData->guid)) break;
5308 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5312 VariantInit( pVarVal);
5313 VariantCopy( pVarVal, &pCData->data);
5316 return E_INVALIDARG; /* FIXME: correct? */
5319 /* ITypeInfo2::GetVarCustData
5321 * Gets the custom data
5323 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5329 ICOM_THIS( ITypeInfoImpl, iface);
5330 TLBCustData *pCData=NULL;
5331 TLBVarDesc * pVDesc;
5334 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5338 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5340 if( IsEqualIID(guid, &pCData->guid)) break;
5344 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5348 VariantInit( pVarVal);
5349 VariantCopy( pVarVal, &pCData->data);
5352 return E_INVALIDARG; /* FIXME: correct? */
5355 /* ITypeInfo2::GetImplCustData
5357 * Gets the custom data
5359 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5365 ICOM_THIS( ITypeInfoImpl, iface);
5366 TLBCustData *pCData=NULL;
5367 TLBImplType * pRDesc;
5370 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5374 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5376 if( IsEqualIID(guid, &pCData->guid)) break;
5380 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5384 VariantInit( pVarVal);
5385 VariantCopy( pVarVal, &pCData->data);
5388 return E_INVALIDARG; /* FIXME: correct? */
5391 /* ITypeInfo2::GetDocumentation2
5393 * Retrieves the documentation string, the complete Help file name and path,
5394 * the localization context to use, and the context ID for the library Help
5395 * topic in the Help file.
5398 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5402 BSTR *pbstrHelpString,
5403 DWORD *pdwHelpStringContext,
5404 BSTR *pbstrHelpStringDll)
5406 ICOM_THIS( ITypeInfoImpl, iface);
5407 TLBFuncDesc * pFDesc;
5408 TLBVarDesc * pVDesc;
5409 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5410 "HelpStringContext(%p) HelpStringDll(%p)\n",
5411 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5412 pbstrHelpStringDll );
5413 /* the help string should be obtained from the helpstringdll,
5414 * using the _DLLGetDocumentation function, based on the supplied
5415 * lcid. Nice to do sometime...
5417 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5419 *pbstrHelpString=SysAllocString(This->Name);
5420 if(pdwHelpStringContext)
5421 *pdwHelpStringContext=This->dwHelpStringContext;
5422 if(pbstrHelpStringDll)
5423 *pbstrHelpStringDll=
5424 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5426 }else {/* for a member */
5427 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5428 if(pFDesc->funcdesc.memid==memid){
5430 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5431 if(pdwHelpStringContext)
5432 *pdwHelpStringContext=pFDesc->HelpStringContext;
5433 if(pbstrHelpStringDll)
5434 *pbstrHelpStringDll=
5435 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5438 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5439 if(pVDesc->vardesc.memid==memid){
5441 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5442 if(pdwHelpStringContext)
5443 *pdwHelpStringContext=pVDesc->HelpStringContext;
5444 if(pbstrHelpStringDll)
5445 *pbstrHelpStringDll=
5446 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5450 return TYPE_E_ELEMENTNOTFOUND;
5453 /* ITypeInfo2::GetAllCustData
5455 * Gets all custom data items for the Type info.
5458 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5460 CUSTDATA *pCustData)
5462 ICOM_THIS( ITypeInfoImpl, iface);
5463 TLBCustData *pCData;
5466 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5468 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5469 if(pCustData->prgCustData ){
5470 pCustData->cCustData=This->ctCustData;
5471 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5472 pCustData->prgCustData[i].guid=pCData->guid;
5473 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5476 ERR(" OUT OF MEMORY! \n");
5477 return E_OUTOFMEMORY;
5482 /* ITypeInfo2::GetAllFuncCustData
5484 * Gets all custom data items for the specified Function
5487 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5490 CUSTDATA *pCustData)
5492 ICOM_THIS( ITypeInfoImpl, iface);
5493 TLBCustData *pCData;
5494 TLBFuncDesc * pFDesc;
5496 TRACE("(%p) index %d\n", This, index);
5497 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5498 pFDesc=pFDesc->next)
5501 pCustData->prgCustData =
5502 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5503 if(pCustData->prgCustData ){
5504 pCustData->cCustData=pFDesc->ctCustData;
5505 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5506 pCData = pCData->next){
5507 pCustData->prgCustData[i].guid=pCData->guid;
5508 VariantCopy(& pCustData->prgCustData[i].varValue,
5512 ERR(" OUT OF MEMORY! \n");
5513 return E_OUTOFMEMORY;
5517 return TYPE_E_ELEMENTNOTFOUND;
5520 /* ITypeInfo2::GetAllParamCustData
5522 * Gets all custom data items for the Functions
5525 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5526 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5528 ICOM_THIS( ITypeInfoImpl, iface);
5529 TLBCustData *pCData=NULL;
5530 TLBFuncDesc * pFDesc;
5532 TRACE("(%p) index %d\n", This, indexFunc);
5533 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5534 pFDesc=pFDesc->next)
5536 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5537 pCustData->prgCustData =
5538 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5539 sizeof(CUSTDATAITEM));
5540 if(pCustData->prgCustData ){
5541 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5542 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5543 pCData; i++, pCData = pCData->next){
5544 pCustData->prgCustData[i].guid=pCData->guid;
5545 VariantCopy(& pCustData->prgCustData[i].varValue,
5549 ERR(" OUT OF MEMORY! \n");
5550 return E_OUTOFMEMORY;
5554 return TYPE_E_ELEMENTNOTFOUND;
5557 /* ITypeInfo2::GetAllVarCustData
5559 * Gets all custom data items for the specified Variable
5562 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5563 UINT index, CUSTDATA *pCustData)
5565 ICOM_THIS( ITypeInfoImpl, iface);
5566 TLBCustData *pCData;
5567 TLBVarDesc * pVDesc;
5569 TRACE("(%p) index %d\n", This, index);
5570 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5571 pVDesc=pVDesc->next)
5574 pCustData->prgCustData =
5575 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5576 if(pCustData->prgCustData ){
5577 pCustData->cCustData=pVDesc->ctCustData;
5578 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5579 pCData = pCData->next){
5580 pCustData->prgCustData[i].guid=pCData->guid;
5581 VariantCopy(& pCustData->prgCustData[i].varValue,
5585 ERR(" OUT OF MEMORY! \n");
5586 return E_OUTOFMEMORY;
5590 return TYPE_E_ELEMENTNOTFOUND;
5593 /* ITypeInfo2::GetAllImplCustData
5595 * Gets all custom data items for the specified implementation type
5598 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5601 CUSTDATA *pCustData)
5603 ICOM_THIS( ITypeInfoImpl, iface);
5604 TLBCustData *pCData;
5605 TLBImplType * pRDesc;
5607 TRACE("(%p) index %d\n", This, index);
5608 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5609 pRDesc=pRDesc->next)
5612 pCustData->prgCustData =
5613 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5614 if(pCustData->prgCustData ){
5615 pCustData->cCustData=pRDesc->ctCustData;
5616 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5617 pCData = pCData->next){
5618 pCustData->prgCustData[i].guid=pCData->guid;
5619 VariantCopy(& pCustData->prgCustData[i].varValue,
5623 ERR(" OUT OF MEMORY! \n");
5624 return E_OUTOFMEMORY;
5628 return TYPE_E_ELEMENTNOTFOUND;
5631 static ICOM_VTABLE(ITypeInfo2) tinfvt =
5633 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5635 ITypeInfo_fnQueryInterface,
5637 ITypeInfo_fnRelease,
5639 ITypeInfo_fnGetTypeAttr,
5640 ITypeInfo_fnGetTypeComp,
5641 ITypeInfo_fnGetFuncDesc,
5642 ITypeInfo_fnGetVarDesc,
5643 ITypeInfo_fnGetNames,
5644 ITypeInfo_fnGetRefTypeOfImplType,
5645 ITypeInfo_fnGetImplTypeFlags,
5646 ITypeInfo_fnGetIDsOfNames,
5648 ITypeInfo_fnGetDocumentation,
5649 ITypeInfo_fnGetDllEntry,
5650 ITypeInfo_fnGetRefTypeInfo,
5651 ITypeInfo_fnAddressOfMember,
5652 ITypeInfo_fnCreateInstance,
5653 ITypeInfo_fnGetMops,
5654 ITypeInfo_fnGetContainingTypeLib,
5655 ITypeInfo_fnReleaseTypeAttr,
5656 ITypeInfo_fnReleaseFuncDesc,
5657 ITypeInfo_fnReleaseVarDesc,
5659 ITypeInfo2_fnGetTypeKind,
5660 ITypeInfo2_fnGetTypeFlags,
5661 ITypeInfo2_fnGetFuncIndexOfMemId,
5662 ITypeInfo2_fnGetVarIndexOfMemId,
5663 ITypeInfo2_fnGetCustData,
5664 ITypeInfo2_fnGetFuncCustData,
5665 ITypeInfo2_fnGetParamCustData,
5666 ITypeInfo2_fnGetVarCustData,
5667 ITypeInfo2_fnGetImplTypeCustData,
5668 ITypeInfo2_fnGetDocumentation2,
5669 ITypeInfo2_fnGetAllCustData,
5670 ITypeInfo2_fnGetAllFuncCustData,
5671 ITypeInfo2_fnGetAllParamCustData,
5672 ITypeInfo2_fnGetAllVarCustData,
5673 ITypeInfo2_fnGetAllImplTypeCustData,
5676 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5678 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5680 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5683 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5685 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5687 return ITypeInfo_AddRef((ITypeInfo *)This);
5690 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5692 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5694 return ITypeInfo_Release((ITypeInfo *)This);
5697 static HRESULT WINAPI ITypeComp_fnBind(
5700 unsigned long lHash,
5701 unsigned short wFlags,
5702 ITypeInfo ** ppTInfo,
5703 DESCKIND * pDescKind,
5706 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5707 TLBFuncDesc * pFDesc;
5708 TLBVarDesc * pVDesc;
5710 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5712 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5713 if (pFDesc->funcdesc.invkind & wFlags)
5714 if (!strcmpW(pFDesc->Name, szName)) {
5720 *pDescKind = DESCKIND_FUNCDESC;
5721 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5722 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5725 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5727 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5728 if (!strcmpW(pVDesc->Name, szName)) {
5729 *pDescKind = DESCKIND_VARDESC;
5730 pBindPtr->lpvardesc = &pVDesc->vardesc;
5731 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5737 /* not found, look for it in inherited interfaces */
5738 if (This->TypeAttr.cImplTypes &&
5739 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5740 /* recursive search */
5744 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5747 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5748 ITypeInfo_Release(pTInfo);
5752 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5753 ITypeComp_Release(pTComp);
5756 WARN("Could not search inherited interface!\n");
5758 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5759 *pDescKind = DESCKIND_NONE;
5760 pBindPtr->lpfuncdesc = NULL;
5762 return DISP_E_MEMBERNOTFOUND;
5765 static HRESULT WINAPI ITypeComp_fnBindType(
5768 unsigned long lHash,
5769 ITypeInfo ** ppTInfo,
5770 ITypeComp ** ppTComp)
5772 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5774 /* strange behaviour (does nothing) but like the
5777 if (!ppTInfo || !ppTComp)
5786 static ICOM_VTABLE(ITypeComp) tcompvt =
5788 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
5790 ITypeComp_fnQueryInterface,
5792 ITypeComp_fnRelease,
5795 ITypeComp_fnBindType