-/*\r
- * TYPELIB\r
- *\r
- * Copyright 1997 Marcus Meissner\r
- * 1999 Rein Klazes\r
- * 2000 Francois Jacques\r
- * 2001 Huw D M Davies for CodeWeavers\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- *\r
- * --------------------------------------------------------------------------------------\r
- * Known problems (2000, Francois Jacques)\r
- *\r
- * - Tested using OLEVIEW (Platform SDK tool) only.\r
- *\r
- * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are\r
- * creating by doing a straight copy of the dispinterface instance and just changing\r
- * its typekind. Pointed structures aren't copied - only the address of the pointers.\r
- * So when you release the dispinterface, you delete the vtable-interface structures\r
- * as well... fortunately, clean up of structures is not implemented.\r
- *\r
- * - locale stuff is partially implemented but hasn't been tested.\r
- *\r
- * - typelib file is still read in its entirety, but it is released now.\r
- * - some garbage is read from function names on some very rare occasions.\r
- *\r
- * --------------------------------------------------------------------------------------\r
- * Known problems left from previous implementation (1999, Rein Klazes) :\r
- *\r
- * -. Data structures are straightforward, but slow for look-ups.\r
- * -. (related) nothing is hashed\r
- * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most\r
- * of them I don't know yet how to implement them.\r
- * -. Most error return values are just guessed not checked with windows\r
- * behaviour.\r
- * -. didn't bother with a c++ interface\r
- * -. lousy fatal error handling\r
- * -. some methods just return pointers to internal data structures, this is\r
- * partly laziness, partly I want to check how windows does it.\r
- *\r
- */\r
-\r
-#include "config.h"\r
-#include "wine/port.h"\r
-\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <stdarg.h>\r
-#include <stdio.h>\r
-#include <ctype.h>\r
-\r
-#define COBJMACROS\r
-#define NONAMELESSUNION\r
-#define NONAMELESSSTRUCT\r
-\r
-#include "winerror.h"\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "winnls.h"\r
-#include "winreg.h"\r
-#include "winuser.h"\r
-\r
-#include "wine/unicode.h"\r
-#include "objbase.h"\r
-#include "typelib.h"\r
-#include "wine/debug.h"\r
-#include "variant.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(ole);\r
-WINE_DECLARE_DEBUG_CHANNEL(typelib);\r
-\r
-/* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */\r
-const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };\r
-\r
-/****************************************************************************\r
- * FromLExxx\r
- *\r
- * Takes p_iVal (which is in little endian) and returns it\r
- * in the host machine's byte order.\r
- */\r
-#ifdef WORDS_BIGENDIAN\r
-static WORD FromLEWord(WORD p_iVal)\r
-{\r
- return (((p_iVal & 0x00FF) << 8) |\r
- ((p_iVal & 0xFF00) >> 8));\r
-}\r
-\r
-\r
-static DWORD FromLEDWord(DWORD p_iVal)\r
-{\r
- return (((p_iVal & 0x000000FF) << 24) |\r
- ((p_iVal & 0x0000FF00) << 8) |\r
- ((p_iVal & 0x00FF0000) >> 8) |\r
- ((p_iVal & 0xFF000000) >> 24));\r
-}\r
-#else\r
-#define FromLEWord(X) (X)\r
-#define FromLEDWord(X) (X)\r
-#endif\r
-\r
-\r
-/****************************************************************************\r
- * FromLExxx\r
- *\r
- * Fix byte order in any structure if necessary\r
- */\r
-#ifdef WORDS_BIGENDIAN\r
-static void FromLEWords(void *p_Val, int p_iSize)\r
-{\r
- WORD *Val = p_Val;\r
-\r
- p_iSize /= sizeof(WORD);\r
-\r
- while (p_iSize) {\r
- *Val = FromLEWord(*Val);\r
- Val++;\r
- p_iSize--;\r
- }\r
-}\r
-\r
-\r
-static void FromLEDWords(void *p_Val, int p_iSize)\r
-{\r
- DWORD *Val = p_Val;\r
-\r
- p_iSize /= sizeof(DWORD);\r
-\r
- while (p_iSize) {\r
- *Val = FromLEDWord(*Val);\r
- Val++;\r
- p_iSize--;\r
- }\r
-}\r
-#else\r
-#define FromLEWords(X,Y) /*nothing*/\r
-#define FromLEDWords(X,Y) /*nothing*/\r
-#endif\r
-\r
-/* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */\r
-/* buffer must be at least 60 characters long */\r
-static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )\r
-{\r
- static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};\r
- static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};\r
-\r
- memcpy( buffer, TypelibW, sizeof(TypelibW) );\r
- StringFromGUID2( guid, buffer + strlenW(buffer), 40 );\r
- sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );\r
- return buffer;\r
-}\r
-\r
-/* get the path of an interface key, in the form "Interface\\<guid>" */\r
-/* buffer must be at least 50 characters long */\r
-static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )\r
-{\r
- static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};\r
-\r
- memcpy( buffer, InterfaceW, sizeof(InterfaceW) );\r
- StringFromGUID2( guid, buffer + strlenW(buffer), 40 );\r
- return buffer;\r
-}\r
-\r
-/* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */\r
-/* buffer must be at least 16 characters long */\r
-static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )\r
-{\r
- static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};\r
- static const WCHAR win16W[] = {'w','i','n','1','6',0};\r
- static const WCHAR win32W[] = {'w','i','n','3','2',0};\r
-\r
- sprintfW( buffer, LcidFormatW, lcid );\r
- switch(syskind)\r
- {\r
- case SYS_WIN16: strcatW( buffer, win16W ); break;\r
- case SYS_WIN32: strcatW( buffer, win32W ); break;\r
- default:\r
- TRACE("Typelib is for unsupported syskind %i\n", syskind);\r
- return NULL;\r
- }\r
- return buffer;\r
-}\r
-\r
-\r
-/****************************************************************************\r
- * QueryPathOfRegTypeLib [OLEAUT32.164]\r
- * RETURNS\r
- * path of typelib\r
- */\r
-HRESULT WINAPI\r
-QueryPathOfRegTypeLib(\r
- REFGUID guid, /* [in] referenced guid */\r
- WORD wMaj, /* [in] major version */\r
- WORD wMin, /* [in] minor version */\r
- LCID lcid, /* [in] locale id */\r
- LPBSTR path ) /* [out] path of typelib */\r
-{\r
- HRESULT hr = E_FAIL;\r
- LCID myLCID = lcid;\r
- HKEY hkey;\r
- WCHAR buffer[60];\r
- WCHAR Path[MAX_PATH];\r
-\r
- if ( !HIWORD(guid) )\r
- {\r
- FIXME("(guid %p,%d,%d,0x%04lx,%p),stub!\n", guid, wMaj, wMin, lcid, path);\r
- return E_FAIL;\r
- }\r
-\r
- get_typelib_key( guid, wMaj, wMin, buffer );\r
-\r
- if (RegOpenKeyW( HKEY_CLASSES_ROOT, buffer, &hkey ) != ERROR_SUCCESS)\r
- {\r
- TRACE_(typelib)("%s not found\n", debugstr_w(buffer));\r
- return E_FAIL;\r
- }\r
-\r
- while (hr != S_OK)\r
- {\r
- DWORD dwPathLen = sizeof(Path);\r
-\r
- get_lcid_subkey( myLCID, SYS_WIN32, buffer );\r
-\r
- if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))\r
- {\r
- if (!lcid)\r
- break;\r
- else if (myLCID == lcid)\r
- {\r
- /* try with sub-langid */\r
- myLCID = SUBLANGID(lcid);\r
- }\r
- else if ((myLCID == SUBLANGID(lcid)) && myLCID)\r
- {\r
- /* try with system langid */\r
- myLCID = 0;\r
- }\r
- else\r
- {\r
- break;\r
- }\r
- }\r
- else\r
- {\r
- *path = SysAllocString( Path );\r
- hr = S_OK;\r
- }\r
- }\r
- RegCloseKey( hkey );\r
- return hr;\r
-}\r
-\r
-/******************************************************************************\r
- * CreateTypeLib [OLEAUT32.160] creates a typelib\r
- *\r
- * RETURNS\r
- * Success: S_OK\r
- * Failure: Status\r
- */\r
-HRESULT WINAPI CreateTypeLib(\r
- SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib\r
-) {\r
- FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);\r
- return E_FAIL;\r
-}\r
-/******************************************************************************\r
- * LoadTypeLib [OLEAUT32.161]\r
- * Loads and registers a type library\r
- * NOTES\r
- * Docs: OLECHAR FAR* szFile\r
- * Docs: iTypeLib FAR* FAR* pptLib\r
- *\r
- * RETURNS\r
- * Success: S_OK\r
- * Failure: Status\r
- */\r
-int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);\r
-\r
-HRESULT WINAPI LoadTypeLib(\r
- const OLECHAR *szFile,/* [in] Name of file to load from */\r
- ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */\r
-{\r
- TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);\r
- return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);\r
-}\r
-\r
-/******************************************************************************\r
- * LoadTypeLibEx [OLEAUT32.183]\r
- * Loads and optionally registers a type library\r
- *\r
- * RETURNS\r
- * Success: S_OK\r
- * Failure: Status\r
- */\r
-HRESULT WINAPI LoadTypeLibEx(\r
- LPCOLESTR szFile, /* [in] Name of file to load from */\r
- REGKIND regkind, /* [in] Specify kind of registration */\r
- ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */\r
-{\r
- WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];\r
- WCHAR *pIndexStr;\r
- HRESULT res;\r
- INT index = 1;\r
-\r
- TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);\r
-\r
- /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */\r
- memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));\r
- \r
- *pptLib = NULL;\r
- if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,\r
- NULL)) {\r
-\r
- /* Look for a trailing '\\' followed by an index */\r
- pIndexStr = strrchrW(szFile, '\\');\r
- if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {\r
- index = atoiW(pIndexStr);\r
- memcpy(szFileCopy, szFile,\r
- (pIndexStr - szFile - 1) * sizeof(WCHAR));\r
- szFileCopy[pIndexStr - szFile - 1] = '\0';\r
- if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),\r
- szPath,NULL))\r
- return TYPE_E_CANTLOADLIBRARY;\r
- if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)\r
- return TYPE_E_CANTLOADLIBRARY;\r
- }\r
- }\r
-\r
- TRACE("File %s index %d\n", debugstr_w(szPath), index);\r
-\r
- res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);\r
-\r
- if (SUCCEEDED(res))\r
- switch(regkind)\r
- {\r
- case REGKIND_DEFAULT:\r
- /* don't register typelibs supplied with full path. Experimentation confirms the following */\r
- if ((!szFile) ||\r
- ((szFile[0] == '\\') && (szFile[1] == '\\')) ||\r
- (szFile[0] && (szFile[1] == ':'))) break;\r
- /* else fall-through */\r
-\r
- case REGKIND_REGISTER:\r
- if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))\r
- {\r
- IUnknown_Release(*pptLib);\r
- *pptLib = 0;\r
- }\r
- break;\r
- case REGKIND_NONE:\r
- break;\r
- }\r
-\r
- TRACE(" returns %08lx\n",res);\r
- return res;\r
-}\r
-\r
-/******************************************************************************\r
- * LoadRegTypeLib [OLEAUT32.162]\r
- */\r
-HRESULT WINAPI LoadRegTypeLib(\r
- REFGUID rguid, /* [in] referenced guid */\r
- WORD wVerMajor, /* [in] major version */\r
- WORD wVerMinor, /* [in] minor version */\r
- LCID lcid, /* [in] locale id */\r
- ITypeLib **ppTLib) /* [out] path of typelib */\r
-{\r
- BSTR bstr=NULL;\r
- HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);\r
-\r
- if(SUCCEEDED(res))\r
- {\r
- res= LoadTypeLib(bstr, ppTLib);\r
- SysFreeString(bstr);\r
- }\r
-\r
- TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);\r
-\r
- return res;\r
-}\r
-\r
-\r
-/* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */\r
-static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};\r
-static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};\r
-static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};\r
-static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};\r
-static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};\r
-\r
-/******************************************************************************\r
- * RegisterTypeLib [OLEAUT32.163]\r
- * Adds information about a type library to the System Registry\r
- * NOTES\r
- * Docs: ITypeLib FAR * ptlib\r
- * Docs: OLECHAR FAR* szFullPath\r
- * Docs: OLECHAR FAR* szHelpDir\r
- *\r
- * RETURNS\r
- * Success: S_OK\r
- * Failure: Status\r
- */\r
-HRESULT WINAPI RegisterTypeLib(\r
- ITypeLib * ptlib, /* [in] Pointer to the library*/\r
- OLECHAR * szFullPath, /* [in] full Path of the library*/\r
- OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,\r
- may be NULL*/\r
-{\r
- static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',\r
- '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',\r
- '0','0','0','0','0','0','0','0','0','0','4','6','}',0};\r
- HRESULT res;\r
- TLIBATTR *attr;\r
- WCHAR keyName[60];\r
- WCHAR tmp[16];\r
- HKEY key, subKey;\r
- UINT types, tidx;\r
- TYPEKIND kind;\r
- DWORD disposition;\r
-\r
- if (ptlib == NULL || szFullPath == NULL)\r
- return E_INVALIDARG;\r
-\r
- if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))\r
- return E_FAIL;\r
-\r
- get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );\r
-\r
- res = S_OK;\r
- if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,\r
- KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)\r
- {\r
- LPOLESTR doc;\r
-\r
- /* Set the human-readable name of the typelib */\r
- if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))\r
- {\r
- if (RegSetValueExW(key, NULL, 0, REG_SZ,\r
- (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)\r
- res = E_FAIL;\r
-\r
- SysFreeString(doc);\r
- }\r
- else\r
- res = E_FAIL;\r
-\r
- /* Make up the name of the typelib path subkey */\r
- if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;\r
-\r
- /* Create the typelib path subkey */\r
- if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,\r
- KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)\r
- {\r
- if (RegSetValueExW(subKey, NULL, 0, REG_SZ,\r
- (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)\r
- res = E_FAIL;\r
-\r
- RegCloseKey(subKey);\r
- }\r
- else\r
- res = E_FAIL;\r
-\r
- /* Create the flags subkey */\r
- if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,\r
- KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)\r
- {\r
- /* FIXME: is %u correct? */\r
- static const WCHAR formatW[] = {'%','u',0};\r
- WCHAR buf[20];\r
- sprintfW(buf, formatW, attr->wLibFlags);\r
- if (RegSetValueExW(subKey, NULL, 0, REG_SZ,\r
- (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)\r
- res = E_FAIL;\r
-\r
- RegCloseKey(subKey);\r
- }\r
- else\r
- res = E_FAIL;\r
-\r
- /* create the helpdir subkey */\r
- if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,\r
- KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)\r
- {\r
- BOOL freeHelpDir = FALSE;\r
- OLECHAR* pIndexStr;\r
-\r
- /* if we created a new key, and helpDir was null, set the helpdir\r
- to the directory which contains the typelib. However,\r
- if we just opened an existing key, we leave the helpdir alone */\r
- if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {\r
- szHelpDir = SysAllocString(szFullPath);\r
- pIndexStr = strrchrW(szHelpDir, '\\');\r
- if (pIndexStr) {\r
- *pIndexStr = 0;\r
- }\r
- freeHelpDir = TRUE;\r
- }\r
-\r
- /* if we have an szHelpDir, set it! */\r
- if (szHelpDir != NULL) {\r
- if (RegSetValueExW(subKey, NULL, 0, REG_SZ,\r
- (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {\r
- res = E_FAIL;\r
- }\r
- }\r
-\r
- /* tidy up */\r
- if (freeHelpDir) SysFreeString(szHelpDir);\r
- RegCloseKey(subKey);\r
-\r
- } else {\r
- res = E_FAIL;\r
- }\r
-\r
- RegCloseKey(key);\r
- }\r
- else\r
- res = E_FAIL;\r
-\r
- /* register OLE Automation-compatible interfaces for this typelib */\r
- types = ITypeLib_GetTypeInfoCount(ptlib);\r
- for (tidx=0; tidx<types; tidx++) {\r
- if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {\r
- LPOLESTR name = NULL;\r
- ITypeInfo *tinfo = NULL;\r
-\r
- ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);\r
-\r
- switch (kind) {\r
- case TKIND_INTERFACE:\r
- TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));\r
- ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);\r
- break;\r
-\r
- case TKIND_DISPATCH:\r
- TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));\r
- ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);\r
- break;\r
-\r
- default:\r
- TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));\r
- break;\r
- }\r
-\r
- if (tinfo) {\r
- TYPEATTR *tattr = NULL;\r
- ITypeInfo_GetTypeAttr(tinfo, &tattr);\r
-\r
- if (tattr) {\r
- TRACE_(typelib)("guid=%s, flags=%04x (",\r
- debugstr_guid(&tattr->guid),\r
- tattr->wTypeFlags);\r
-\r
- if (TRACE_ON(typelib)) {\r
-#define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");\r
- XX(FAPPOBJECT);\r
- XX(FCANCREATE);\r
- XX(FLICENSED);\r
- XX(FPREDECLID);\r
- XX(FHIDDEN);\r
- XX(FCONTROL);\r
- XX(FDUAL);\r
- XX(FNONEXTENSIBLE);\r
- XX(FOLEAUTOMATION);\r
- XX(FRESTRICTED);\r
- XX(FAGGREGATABLE);\r
- XX(FREPLACEABLE);\r
- XX(FDISPATCHABLE);\r
- XX(FREVERSEBIND);\r
- XX(FPROXY);\r
-#undef XX\r
- MESSAGE("\n");\r
- }\r
-\r
- /*\r
- * FIXME: The 1 is just here until we implement rpcrt4\r
- * stub/proxy handling. Until then it helps IShield\r
- * v6 to work.\r
- */\r
- if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))\r
- {\r
- if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {\r
- FIXME("Registering non-oleautomation interface!\n");\r
- }\r
-\r
- /* register interface<->typelib coupling */\r
- get_interface_key( &tattr->guid, keyName );\r
- if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,\r
- KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)\r
- {\r
- if (name)\r
- RegSetValueExW(key, NULL, 0, REG_SZ,\r
- (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));\r
-\r
- if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,\r
- KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {\r
- RegSetValueExW(subKey, NULL, 0, REG_SZ,\r
- (BYTE*)PSOA, sizeof PSOA);\r
- RegCloseKey(subKey);\r
- }\r
-\r
- if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,\r
- KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {\r
- RegSetValueExW(subKey, NULL, 0, REG_SZ,\r
- (BYTE*)PSOA, sizeof PSOA);\r
- RegCloseKey(subKey);\r
- }\r
-\r
- if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,\r
- KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)\r
- {\r
- WCHAR buffer[40];\r
- static const WCHAR fmtver[] = {'%','u','.','%','u',0 };\r
- static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};\r
-\r
- StringFromGUID2(&attr->guid, buffer, 40);\r
- RegSetValueExW(subKey, NULL, 0, REG_SZ,\r
- (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));\r
- sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);\r
- RegSetValueExW(subKey, VersionW, 0, REG_SZ,\r
- (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));\r
- RegCloseKey(subKey);\r
- }\r
-\r
- RegCloseKey(key);\r
- }\r
- }\r
-\r
- ITypeInfo_ReleaseTypeAttr(tinfo, tattr);\r
- }\r
-\r
- ITypeInfo_Release(tinfo);\r
- }\r
-\r
- SysFreeString(name);\r
- }\r
- }\r
-\r
- ITypeLib_ReleaseTLibAttr(ptlib, attr);\r
-\r
- return res;\r
-}\r
-\r
-\r
-/******************************************************************************\r
- * UnRegisterTypeLib [OLEAUT32.186]\r
- * Removes information about a type library from the System Registry\r
- * NOTES\r
- *\r
- * RETURNS\r
- * Success: S_OK\r
- * Failure: Status\r
- */\r
-HRESULT WINAPI UnRegisterTypeLib(\r
- REFGUID libid, /* [in] Guid of the library */\r
- WORD wVerMajor, /* [in] major version */\r
- WORD wVerMinor, /* [in] minor version */\r
- LCID lcid, /* [in] locale id */\r
- SYSKIND syskind)\r
-{\r
- BSTR tlibPath = NULL;\r
- DWORD tmpLength;\r
- WCHAR keyName[60];\r
- WCHAR subKeyName[50];\r
- int result = S_OK;\r
- DWORD i = 0;\r
- BOOL deleteOtherStuff;\r
- HKEY key = NULL;\r
- HKEY subKey = NULL;\r
- TYPEATTR* typeAttr = NULL;\r
- TYPEKIND kind;\r
- ITypeInfo* typeInfo = NULL;\r
- ITypeLib* typeLib = NULL;\r
- int numTypes;\r
-\r
- TRACE("(IID: %s): stub\n",debugstr_guid(libid));\r
-\r
- /* Create the path to the key */\r
- get_typelib_key( libid, wVerMajor, wVerMinor, keyName );\r
-\r
- if (syskind != SYS_WIN16 && syskind != SYS_WIN32)\r
- {\r
- TRACE("Unsupported syskind %i\n", syskind);\r
- result = E_INVALIDARG;\r
- goto end;\r
- }\r
-\r
- /* get the path to the typelib on disk */\r
- if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {\r
- result = E_INVALIDARG;\r
- goto end;\r
- }\r
-\r
- /* Try and open the key to the type library. */\r
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {\r
- result = E_INVALIDARG;\r
- goto end;\r
- }\r
-\r
- /* Try and load the type library */\r
- if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {\r
- result = TYPE_E_INVALIDSTATE;\r
- goto end;\r
- }\r
-\r
- /* remove any types registered with this typelib */\r
- numTypes = ITypeLib_GetTypeInfoCount(typeLib);\r
- for (i=0; i<numTypes; i++) {\r
- /* get the kind of type */\r
- if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {\r
- goto enddeleteloop;\r
- }\r
-\r
- /* skip non-interfaces, and get type info for the type */\r
- if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {\r
- goto enddeleteloop;\r
- }\r
- if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {\r
- goto enddeleteloop;\r
- }\r
- if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {\r
- goto enddeleteloop;\r
- }\r
-\r
- /* the path to the type */\r
- get_interface_key( &typeAttr->guid, subKeyName );\r
-\r
- /* Delete its bits */\r
- if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {\r
- goto enddeleteloop;\r
- }\r
- RegDeleteKeyW(subKey, ProxyStubClsidW);\r
- RegDeleteKeyW(subKey, ProxyStubClsid32W);\r
- RegDeleteKeyW(subKey, TypeLibW);\r
- RegCloseKey(subKey);\r
- subKey = NULL;\r
- RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);\r
-\r
-enddeleteloop:\r
- if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);\r
- typeAttr = NULL;\r
- if (typeInfo) ITypeInfo_Release(typeInfo);\r
- typeInfo = NULL;\r
- }\r
-\r
- /* Now, delete the type library path subkey */\r
- get_lcid_subkey( lcid, syskind, subKeyName );\r
- RegDeleteKeyW(key, subKeyName);\r
- *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */\r
- RegDeleteKeyW(key, subKeyName);\r
-\r
- /* check if there is anything besides the FLAGS/HELPDIR keys.\r
- If there is, we don't delete them */\r
- tmpLength = sizeof(subKeyName)/sizeof(WCHAR);\r
- deleteOtherStuff = TRUE;\r
- i = 0;\r
- while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {\r
- tmpLength = sizeof(subKeyName)/sizeof(WCHAR);\r
-\r
- /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */\r
- if (!strcmpW(subKeyName, FLAGSW)) continue;\r
- if (!strcmpW(subKeyName, HELPDIRW)) continue;\r
- deleteOtherStuff = FALSE;\r
- break;\r
- }\r
-\r
- /* only delete the other parts of the key if we're absolutely sure */\r
- if (deleteOtherStuff) {\r
- RegDeleteKeyW(key, FLAGSW);\r
- RegDeleteKeyW(key, HELPDIRW);\r
- RegCloseKey(key);\r
- key = NULL;\r
-\r
- RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);\r
- *strrchrW( keyName, '\\' ) = 0; /* remove last path component */\r
- RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);\r
- }\r
-\r
-end:\r
- if (tlibPath) SysFreeString(tlibPath);\r
- if (typeLib) ITypeLib_Release(typeLib);\r
- if (subKey) RegCloseKey(subKey);\r
- if (key) RegCloseKey(key);\r
- return result;\r
-}\r
-\r
-/*======================= ITypeLib implementation =======================*/\r
-\r
-typedef struct tagTLBCustData\r
-{\r
- GUID guid;\r
- VARIANT data;\r
- struct tagTLBCustData* next;\r
-} TLBCustData;\r
-\r
-/* data structure for import typelibs */\r
-typedef struct tagTLBImpLib\r
-{\r
- int offset; /* offset in the file (MSFT)\r
- offset in nametable (SLTG)\r
- just used to identify library while reading\r
- data from file */\r
- GUID guid; /* libid */\r
- BSTR name; /* name */\r
-\r
- LCID lcid; /* lcid of imported typelib */\r
-\r
- WORD wVersionMajor; /* major version number */\r
- WORD wVersionMinor; /* minor version number */\r
-\r
- struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or\r
- NULL if not yet loaded */\r
- struct tagTLBImpLib * next;\r
-} TLBImpLib;\r
-\r
-/* internal ITypeLib data */\r
-typedef struct tagITypeLibImpl\r
-{\r
- ITypeLib2Vtbl *lpVtbl;\r
- ITypeCompVtbl *lpVtblTypeComp;\r
- ULONG ref;\r
- TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */\r
-\r
- /* strings can be stored in tlb as multibyte strings BUT they are *always*\r
- * exported to the application as a UNICODE string.\r
- */\r
- BSTR Name;\r
- BSTR DocString;\r
- BSTR HelpFile;\r
- BSTR HelpStringDll;\r
- unsigned long dwHelpContext;\r
- int TypeInfoCount; /* nr of typeinfo's in librarry */\r
- struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */\r
- int ctCustData; /* number of items in cust data list */\r
- TLBCustData * pCustData; /* linked list to cust data */\r
- TLBImpLib * pImpLibs; /* linked list to all imported typelibs */\r
- TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the\r
- libary. Only used while read MSFT\r
- typelibs */\r
-\r
- /* typelibs are cached, keyed by path and index, so store the linked list info within them */\r
- struct tagITypeLibImpl *next, *prev;\r
- WCHAR *path;\r
- INT index;\r
-} ITypeLibImpl;\r
-\r
-static struct ITypeLib2Vtbl tlbvt;\r
-static struct ITypeCompVtbl tlbtcvt;\r
-\r
-#define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))\r
-#define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))\r
-\r
-/* ITypeLib methods */\r
-static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);\r
-static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);\r
-\r
-/*======================= ITypeInfo implementation =======================*/\r
-\r
-/* data for referenced types */\r
-typedef struct tagTLBRefType\r
-{\r
- INT index; /* Type index for internal ref or for external ref\r
- it the format is SLTG. -2 indicates to\r
- use guid */\r
-\r
- GUID guid; /* guid of the referenced type */\r
- /* if index == TLB_REF_USE_GUID */\r
-\r
- HREFTYPE reference; /* The href of this ref */\r
- TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data\r
- TLB_REF_INTERNAL for internal refs\r
- TLB_REF_NOT_FOUND for broken refs */\r
-\r
- struct tagTLBRefType * next;\r
-} TLBRefType;\r
-\r
-#define TLB_REF_USE_GUID -2\r
-\r
-#define TLB_REF_INTERNAL (void*)-2\r
-#define TLB_REF_NOT_FOUND (void*)-1\r
-\r
-/* internal Parameter data */\r
-typedef struct tagTLBParDesc\r
-{\r
- BSTR Name;\r
- int ctCustData;\r
- TLBCustData * pCustData; /* linked list to cust data */\r
-} TLBParDesc;\r
-\r
-/* internal Function data */\r
-typedef struct tagTLBFuncDesc\r
-{\r
- FUNCDESC funcdesc; /* lots of info on the function and its attributes. */\r
- BSTR Name; /* the name of this function */\r
- TLBParDesc *pParamDesc; /* array with param names and custom data */\r
- int helpcontext;\r
- int HelpStringContext;\r
- BSTR HelpString;\r
- BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/\r
- int ctCustData;\r
- TLBCustData * pCustData; /* linked list to cust data; */\r
- struct tagTLBFuncDesc * next;\r
-} TLBFuncDesc;\r
-\r
-/* internal Variable data */\r
-typedef struct tagTLBVarDesc\r
-{\r
- VARDESC vardesc; /* lots of info on the variable and its attributes. */\r
- BSTR Name; /* the name of this variable */\r
- int HelpContext;\r
- int HelpStringContext; /* FIXME: where? */\r
- BSTR HelpString;\r
- int ctCustData;\r
- TLBCustData * pCustData;/* linked list to cust data; */\r
- struct tagTLBVarDesc * next;\r
-} TLBVarDesc;\r
-\r
-/* internal implemented interface data */\r
-typedef struct tagTLBImplType\r
-{\r
- HREFTYPE hRef; /* hRef of interface */\r
- int implflags; /* IMPLFLAG_*s */\r
- int ctCustData;\r
- TLBCustData * pCustData;/* linked list to custom data; */\r
- struct tagTLBImplType *next;\r
-} TLBImplType;\r
-\r
-/* internal TypeInfo data */\r
-typedef struct tagITypeInfoImpl\r
-{\r
- ITypeInfo2Vtbl *lpVtbl;\r
- ITypeCompVtbl *lpVtblTypeComp;\r
- ULONG ref;\r
- TYPEATTR TypeAttr ; /* _lots_ of type information. */\r
- ITypeLibImpl * pTypeLib; /* back pointer to typelib */\r
- int index; /* index in this typelib; */\r
- /* type libs seem to store the doc strings in ascii\r
- * so why should we do it in unicode?\r
- */\r
- BSTR Name;\r
- BSTR DocString;\r
- unsigned long dwHelpContext;\r
- unsigned long dwHelpStringContext;\r
-\r
- /* functions */\r
- TLBFuncDesc * funclist; /* linked list with function descriptions */\r
-\r
- /* variables */\r
- TLBVarDesc * varlist; /* linked list with variable descriptions */\r
-\r
- /* Implemented Interfaces */\r
- TLBImplType * impltypelist;\r
-\r
- TLBRefType * reflist;\r
- int ctCustData;\r
- TLBCustData * pCustData; /* linked list to cust data; */\r
- struct tagITypeInfoImpl * next;\r
-} ITypeInfoImpl;\r
-\r
-static struct ITypeInfo2Vtbl tinfvt;\r
-static struct ITypeCompVtbl tcompvt;\r
-\r
-static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);\r
-\r
-typedef struct tagTLBContext\r
-{\r
- unsigned int oStart; /* start of TLB in file */\r
- unsigned int pos; /* current pos */\r
- unsigned int length; /* total length */\r
- void *mapping; /* memory mapping */\r
- MSFT_SegDir * pTblDir;\r
- ITypeLibImpl* pLibInfo;\r
-} TLBContext;\r
-\r
-\r
-static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);\r
-\r
-/*\r
- debug\r
-*/\r
-static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {\r
- if (pTD->vt & VT_RESERVED)\r
- szVarType += strlen(strcpy(szVarType, "reserved | "));\r
- if (pTD->vt & VT_BYREF)\r
- szVarType += strlen(strcpy(szVarType, "ref to "));\r
- if (pTD->vt & VT_ARRAY)\r
- szVarType += strlen(strcpy(szVarType, "array of "));\r
- if (pTD->vt & VT_VECTOR)\r
- szVarType += strlen(strcpy(szVarType, "vector of "));\r
- switch(pTD->vt & VT_TYPEMASK) {\r
- case VT_UI1: sprintf(szVarType, "VT_UI1"); break;\r
- case VT_I2: sprintf(szVarType, "VT_I2"); break;\r
- case VT_I4: sprintf(szVarType, "VT_I4"); break;\r
- case VT_R4: sprintf(szVarType, "VT_R4"); break;\r
- case VT_R8: sprintf(szVarType, "VT_R8"); break;\r
- case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;\r
- case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;\r
- case VT_CY: sprintf(szVarType, "VT_CY"); break;\r
- case VT_DATE: sprintf(szVarType, "VT_DATE"); break;\r
- case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;\r
- case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;\r
- case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;\r
- case VT_I1: sprintf(szVarType, "VT_I1"); break;\r
- case VT_UI2: sprintf(szVarType, "VT_UI2"); break;\r
- case VT_UI4: sprintf(szVarType, "VT_UI4"); break;\r
- case VT_INT: sprintf(szVarType, "VT_INT"); break;\r
- case VT_UINT: sprintf(szVarType, "VT_UINT"); break;\r
- case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;\r
- case VT_VOID: sprintf(szVarType, "VT_VOID"); break;\r
- case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;\r
- case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",\r
- pTD->u.hreftype); break;\r
- case VT_PTR: sprintf(szVarType, "ptr to ");\r
- dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);\r
- break;\r
- case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");\r
- dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);\r
- break;\r
- case VT_CARRAY: sprintf(szVarType, "%d dim array of ",\r
- pTD->u.lpadesc->cDims); /* FIXME print out sizes */\r
- dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));\r
- break;\r
-\r
- default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;\r
- }\r
-}\r
-\r
-void dump_ELEMDESC(ELEMDESC *edesc) {\r
- char buf[200];\r
- dump_TypeDesc(&edesc->tdesc,buf);\r
- MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);\r
- MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);\r
- MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);\r
-}\r
-void dump_FUNCDESC(FUNCDESC *funcdesc) {\r
- int i;\r
- MESSAGE("memid is %08lx\n",funcdesc->memid);\r
- for (i=0;i<funcdesc->cParams;i++) {\r
- MESSAGE("Param %d:\n",i);\r
- dump_ELEMDESC(funcdesc->lprgelemdescParam+i);\r
- }\r
- MESSAGE("\tfunckind: %d (",funcdesc->funckind);\r
- switch (funcdesc->funckind) {\r
- case FUNC_VIRTUAL: MESSAGE("virtual");break;\r
- case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;\r
- case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;\r
- case FUNC_STATIC: MESSAGE("static");break;\r
- case FUNC_DISPATCH: MESSAGE("dispatch");break;\r
- default: MESSAGE("unknown");break;\r
- }\r
- MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);\r
- switch (funcdesc->invkind) {\r
- case INVOKE_FUNC: MESSAGE("func");break;\r
- case INVOKE_PROPERTYGET: MESSAGE("property get");break;\r
- case INVOKE_PROPERTYPUT: MESSAGE("property put");break;\r
- case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;\r
- }\r
- MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);\r
- switch (funcdesc->callconv) {\r
- case CC_CDECL: MESSAGE("cdecl");break;\r
- case CC_PASCAL: MESSAGE("pascal");break;\r
- case CC_STDCALL: MESSAGE("stdcall");break;\r
- case CC_SYSCALL: MESSAGE("syscall");break;\r
- default:break;\r
- }\r
- MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);\r
- MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);\r
- MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);\r
-\r
- MESSAGE("\telemdescFunc (return value type):\n");\r
- dump_ELEMDESC(&funcdesc->elemdescFunc);\r
-}\r
-\r
-void dump_IDLDESC(IDLDESC *idl) {\r
- MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);\r
-}\r
-\r
-static const char * typekind_desc[] =\r
-{\r
- "TKIND_ENUM",\r
- "TKIND_RECORD",\r
- "TKIND_MODULE",\r
- "TKIND_INTERFACE",\r
- "TKIND_DISPATCH",\r
- "TKIND_COCLASS",\r
- "TKIND_ALIAS",\r
- "TKIND_UNION",\r
- "TKIND_MAX"\r
-};\r
-\r
-void dump_TYPEATTR(TYPEATTR *tattr) {\r
- char buf[200];\r
- MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));\r
- MESSAGE("\tlcid: %ld\n",tattr->lcid);\r
- MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);\r
- MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);\r
- MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));\r
- MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);\r
- MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);\r
- MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);\r
- MESSAGE("\tcVars: %d\n", tattr->cVars);\r
- MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);\r
- MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);\r
- MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);\r
- MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);\r
- MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);\r
- dump_TypeDesc(&tattr->tdescAlias,buf);\r
- MESSAGE("\ttypedesc: %s\n", buf);\r
- dump_IDLDESC(&tattr->idldescType);\r
-}\r
-\r
-static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)\r
-{\r
- int i;\r
- if (!TRACE_ON(typelib))\r
- return;\r
- MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);\r
- for (i=0;i<pfd->funcdesc.cParams;i++)\r
- MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));\r
-\r
-\r
- dump_FUNCDESC(&(pfd->funcdesc));\r
-\r
- MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));\r
- MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));\r
-}\r
-static void dump_TLBFuncDesc(TLBFuncDesc * pfd)\r
-{\r
- while (pfd)\r
- {\r
- dump_TLBFuncDescOne(pfd);\r
- pfd = pfd->next;\r
- };\r
-}\r
-static void dump_TLBVarDesc(TLBVarDesc * pvd)\r
-{\r
- while (pvd)\r
- {\r
- TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));\r
- pvd = pvd->next;\r
- };\r
-}\r
-\r
-static void dump_TLBImpLib(TLBImpLib *import)\r
-{\r
- TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),\r
- debugstr_w(import->name));\r
- TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,\r
- import->wVersionMinor, import->lcid, import->offset);\r
-}\r
-\r
-static void dump_TLBRefType(TLBRefType * prt)\r
-{\r
- while (prt)\r
- {\r
- TRACE_(typelib)("href:0x%08lx\n", prt->reference);\r
- if(prt->index == -1)\r
- TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));\r
- else\r
- TRACE_(typelib)("type no: %d\n", prt->index);\r
-\r
- if(prt->pImpTLInfo != TLB_REF_INTERNAL &&\r
- prt->pImpTLInfo != TLB_REF_NOT_FOUND) {\r
- TRACE_(typelib)("in lib\n");\r
- dump_TLBImpLib(prt->pImpTLInfo);\r
- }\r
- prt = prt->next;\r
- };\r
-}\r
-\r
-static void dump_TLBImplType(TLBImplType * impl)\r
-{\r
- while (impl) {\r
- TRACE_(typelib)(\r
- "implementing/inheriting interface hRef = %lx implflags %x\n",\r
- impl->hRef, impl->implflags);\r
- impl = impl->next;\r
- }\r
-}\r
-\r
-void dump_Variant(VARIANT * pvar)\r
-{\r
- SYSTEMTIME st;\r
-\r
- TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));\r
-\r
- if (pvar)\r
- {\r
- if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||\r
- V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)\r
- {\r
- TRACE(",%p", V_BYREF(pvar));\r
- }\r
- else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))\r
- {\r
- TRACE(",FIXME");\r
- }\r
- else switch (V_TYPE(pvar))\r
- {\r
- case VT_I1: TRACE(",%d", V_I1(pvar)); break;\r
- case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;\r
- case VT_I2: TRACE(",%d", V_I2(pvar)); break;\r
- case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;\r
- case VT_INT:\r
- case VT_I4: TRACE(",%ld", V_I4(pvar)); break;\r
- case VT_UINT:\r
- case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;\r
- case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),\r
- (ULONG)(V_I8(pvar) & 0xffffffff)); break;\r
- case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),\r
- (ULONG)(V_UI8(pvar) & 0xffffffff)); break;\r
- case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;\r
- case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;\r
- case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;\r
- case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;\r
- case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,\r
- V_CY(pvar).s.Lo); break;\r
- case VT_DATE:\r
- if(!VariantTimeToSystemTime(V_DATE(pvar), &st))\r
- TRACE(",<invalid>");\r
- else\r
- TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,\r
- st.wHour, st.wMinute, st.wSecond);\r
- break;\r
- case VT_ERROR:\r
- case VT_VOID:\r
- case VT_USERDEFINED:\r
- case VT_EMPTY:\r
- case VT_NULL: break;\r
- default: TRACE(",?"); break;\r
- }\r
- }\r
- TRACE("}\n");\r
-}\r
-\r
-static void dump_DispParms(DISPPARAMS * pdp)\r
-{\r
- int index = 0;\r
-\r
- TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);\r
-\r
- while (index < pdp->cArgs)\r
- {\r
- dump_Variant( &pdp->rgvarg[index] );\r
- ++index;\r
- }\r
-}\r
-\r
-static void dump_TypeInfo(ITypeInfoImpl * pty)\r
-{\r
- TRACE("%p ref=%lu\n", pty, pty->ref);\r
- TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));\r
- TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);\r
- TRACE("fct:%u var:%u impl:%u\n",\r
- pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);\r
- TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);\r
- TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));\r
- dump_TLBFuncDesc(pty->funclist);\r
- dump_TLBVarDesc(pty->varlist);\r
- dump_TLBImplType(pty->impltypelist);\r
-}\r
-\r
-void dump_VARDESC(VARDESC *v)\r
-{\r
- MESSAGE("memid %ld\n",v->memid);\r
- MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));\r
- MESSAGE("oInst %ld\n",v->u.oInst);\r
- dump_ELEMDESC(&(v->elemdescVar));\r
- MESSAGE("wVarFlags %x\n",v->wVarFlags);\r
- MESSAGE("varkind %d\n",v->varkind);\r
-}\r
-\r
-static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=\r
-{\r
- /* VT_LPWSTR is largest type that */\r
- /* may appear in type description*/\r
- {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},\r
- {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},\r
- {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},\r
- {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},\r
- {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},\r
- {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},\r
- {{0},30},{{0},31}\r
-};\r
-\r
-static void TLB_abort()\r
-{\r
- DebugBreak();\r
-}\r
-static void * TLB_Alloc(unsigned size)\r
-{\r
- void * ret;\r
- if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){\r
- /* FIXME */\r
- ERR("cannot allocate memory\n");\r
- }\r
- return ret;\r
-}\r
-\r
-static void TLB_Free(void * ptr)\r
-{\r
- HeapFree(GetProcessHeap(), 0, ptr);\r
-}\r
-\r
-/* deep copy a typedesc */\r
-static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)\r
-{\r
- out->vt = in->vt;\r
- switch(in->vt) {\r
- case VT_PTR:\r
- out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));\r
- copy_typedesc(out->u.lptdesc, in->u.lptdesc);\r
- break;\r
- case VT_USERDEFINED:\r
- out->u.hreftype = in->u.hreftype;\r
- break;\r
- case VT_CARRAY:\r
- out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +\r
- (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));\r
- copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);\r
- out->u.lpadesc->cDims = in->u.lpadesc->cDims;\r
- memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));\r
- break;\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-/* free()s any allocated memory pointed to by the tdesc. NB does not\r
- free the tdesc itself - this is because the tdesc is typically part\r
- of a larger structure */\r
-static void free_deep_typedesc(TYPEDESC *tdesc)\r
-{\r
- switch(tdesc->vt) {\r
- case VT_PTR:\r
- free_deep_typedesc(tdesc->u.lptdesc);\r
- HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);\r
- tdesc->u.lptdesc = NULL;\r
- break;\r
- case VT_CARRAY:\r
- free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);\r
- HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);\r
- tdesc->u.lpadesc = NULL;\r
- break;\r
- default:\r
- break;\r
- }\r
-}\r
-\r
-/**********************************************************************\r
- *\r
- * Functions for reading MSFT typelibs (those created by CreateTypeLib2)\r
- */\r
-/* read function */\r
-DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )\r
-{\r
- TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",\r
- pcx->pos, count, pcx->oStart, pcx->length, where);\r
-\r
- if (where != DO_NOT_SEEK)\r
- {\r
- where += pcx->oStart;\r
- if (where > pcx->length)\r
- {\r
- /* FIXME */\r
- ERR("seek beyond end (%ld/%d)\n", where, pcx->length );\r
- TLB_abort();\r
- }\r
- pcx->pos = where;\r
- }\r
- if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;\r
- memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );\r
- pcx->pos += count;\r
- return count;\r
-}\r
-\r
-static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,\r
- long where )\r
-{\r
- DWORD ret;\r
-\r
- ret = MSFT_Read(buffer, count, pcx, where);\r
- FromLEDWords(buffer, ret);\r
-\r
- return ret;\r
-}\r
-\r
-static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,\r
- long where )\r
-{\r
- DWORD ret;\r
-\r
- ret = MSFT_Read(buffer, count, pcx, where);\r
- FromLEWords(buffer, ret);\r
-\r
- return ret;\r
-}\r
-\r
-static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)\r
-{\r
- if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){\r
- memset(pGuid,0, sizeof(GUID));\r
- return;\r
- }\r
- MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );\r
- pGuid->Data1 = FromLEDWord(pGuid->Data1);\r
- pGuid->Data2 = FromLEWord(pGuid->Data2);\r
- pGuid->Data3 = FromLEWord(pGuid->Data3);\r
- TRACE_(typelib)("%s\n", debugstr_guid(pGuid));\r
-}\r
-\r
-BSTR MSFT_ReadName( TLBContext *pcx, int offset)\r
-{\r
- char * name;\r
- MSFT_NameIntro niName;\r
- int lengthInChars;\r
- WCHAR* pwstring = NULL;\r
- BSTR bstrName = NULL;\r
-\r
- MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,\r
- pcx->pTblDir->pNametab.offset+offset);\r
- niName.namelen &= 0xFF; /* FIXME: correct ? */\r
- name=TLB_Alloc((niName.namelen & 0xff) +1);\r
- MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);\r
- name[niName.namelen & 0xff]='\0';\r
-\r
- lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,\r
- name, -1, NULL, 0);\r
-\r
- /* no invalid characters in string */\r
- if (lengthInChars)\r
- {\r
- pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);\r
-\r
- /* don't check for invalid character since this has been done previously */\r
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);\r
-\r
- bstrName = SysAllocStringLen(pwstring, lengthInChars);\r
- lengthInChars = SysStringLen(bstrName);\r
- HeapFree(GetProcessHeap(), 0, pwstring);\r
- }\r
-\r
- TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);\r
- return bstrName;\r
-}\r
-\r
-BSTR MSFT_ReadString( TLBContext *pcx, int offset)\r
-{\r
- char * string;\r
- INT16 length;\r
- int lengthInChars;\r
- BSTR bstr = NULL;\r
-\r
- if(offset<0) return NULL;\r
- MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);\r
- if(length <= 0) return 0;\r
- string=TLB_Alloc(length +1);\r
- MSFT_Read(string, length, pcx, DO_NOT_SEEK);\r
- string[length]='\0';\r
-\r
- lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,\r
- string, -1, NULL, 0);\r
-\r
- /* no invalid characters in string */\r
- if (lengthInChars)\r
- {\r
- WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);\r
-\r
- /* don't check for invalid character since this has been done previously */\r
- MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);\r
-\r
- bstr = SysAllocStringLen(pwstring, lengthInChars);\r
- lengthInChars = SysStringLen(bstr);\r
- HeapFree(GetProcessHeap(), 0, pwstring);\r
- }\r
-\r
- TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);\r
- return bstr;\r
-}\r
-/*\r
- * read a value and fill a VARIANT structure\r
- */\r
-static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )\r
-{\r
- int size;\r
-\r
- TRACE_(typelib)("\n");\r
-\r
- if(offset <0) { /* data are packed in here */\r
- V_VT(pVar) = (offset & 0x7c000000 )>> 26;\r
- V_I2(pVar) = offset & 0x3ffffff;\r
- return;\r
- }\r
- MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,\r
- pcx->pTblDir->pCustData.offset + offset );\r
- TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));\r
- switch (V_VT(pVar)){\r
- case VT_EMPTY: /* FIXME: is this right? */\r
- case VT_NULL: /* FIXME: is this right? */\r
- case VT_I2 : /* this should not happen */\r
- case VT_I4 :\r
- case VT_R4 :\r
- case VT_ERROR :\r
- case VT_BOOL :\r
- case VT_I1 :\r
- case VT_UI1 :\r
- case VT_UI2 :\r
- case VT_UI4 :\r
- case VT_INT :\r
- case VT_UINT :\r
- case VT_VOID : /* FIXME: is this right? */\r
- case VT_HRESULT :\r
- size=4; break;\r
- case VT_R8 :\r
- case VT_CY :\r
- case VT_DATE :\r
- case VT_I8 :\r
- case VT_UI8 :\r
- case VT_DECIMAL : /* FIXME: is this right? */\r
- case VT_FILETIME :\r
- size=8;break;\r
- /* pointer types with known behaviour */\r
- case VT_BSTR :{\r
- char * ptr;\r
- MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );\r
- if(size < 0) {\r
- FIXME("BSTR length = %d?\n", size);\r
- } else {\r
- ptr=TLB_Alloc(size);/* allocate temp buffer */\r
- MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */\r
- V_BSTR(pVar)=SysAllocStringLen(NULL,size);\r
- /* FIXME: do we need a AtoW conversion here? */\r
- V_UNION(pVar, bstrVal[size])=L'\0';\r
- while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];\r
- TLB_Free(ptr);\r
- }\r
- }\r
- size=-4; break;\r
- /* FIXME: this will not work AT ALL when the variant contains a pointer */\r
- case VT_DISPATCH :\r
- case VT_VARIANT :\r
- case VT_UNKNOWN :\r
- case VT_PTR :\r
- case VT_SAFEARRAY :\r
- case VT_CARRAY :\r
- case VT_USERDEFINED :\r
- case VT_LPSTR :\r
- case VT_LPWSTR :\r
- case VT_BLOB :\r
- case VT_STREAM :\r
- case VT_STORAGE :\r
- case VT_STREAMED_OBJECT :\r
- case VT_STORED_OBJECT :\r
- case VT_BLOB_OBJECT :\r
- case VT_CF :\r
- case VT_CLSID :\r
- default:\r
- size=0;\r
- FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",\r
- V_VT(pVar));\r
- }\r
-\r
- if(size>0) /* (big|small) endian correct? */\r
- MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );\r
- return;\r
-}\r
-/*\r
- * create a linked list with custom data\r
- */\r
-static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )\r
-{\r
- MSFT_CDGuid entry;\r
- TLBCustData* pNew;\r
- int count=0;\r
-\r
- TRACE_(typelib)("\n");\r
-\r
- while(offset >=0){\r
- count++;\r
- pNew=TLB_Alloc(sizeof(TLBCustData));\r
- MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);\r
- MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);\r
- MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);\r
- /* add new custom data at head of the list */\r
- pNew->next=*ppCustData;\r
- *ppCustData=pNew;\r
- offset = entry.next;\r
- }\r
- return count;\r
-}\r
-\r
-static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,\r
- ITypeInfoImpl *pTI)\r
-{\r
- if(type <0)\r
- pTd->vt=type & VT_TYPEMASK;\r
- else\r
- *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];\r
-\r
- if(pTd->vt == VT_USERDEFINED)\r
- MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);\r
-\r
- TRACE_(typelib)("vt type = %X\n", pTd->vt);\r
-}\r
-\r
-static void\r
-MSFT_DoFuncs(TLBContext* pcx,\r
- ITypeInfoImpl* pTI,\r
- int cFuncs,\r
- int cVars,\r
- int offset,\r
- TLBFuncDesc** pptfd)\r
-{\r
- /*\r
- * member information is stored in a data structure at offset\r
- * indicated by the memoffset field of the typeinfo structure\r
- * There are several distinctive parts.\r
- * The first part starts with a field that holds the total length\r
- * of this (first) part excluding this field. Then follow the records,\r
- * for each member there is one record.\r
- *\r
- * The first entry is always the length of the record (including this\r
- * length word).\r
- * The rest of the record depends on the type of the member. If there is\r
- * a field indicating the member type (function, variable, interface, etc)\r
- * I have not found it yet. At this time we depend on the information\r
- * in the type info and the usual order how things are stored.\r
- *\r
- * Second follows an array sized nrMEM*sizeof(INT) with a member id\r
- * for each member;\r
- *\r
- * Third is an equal sized array with file offsets to the name entry\r
- * of each member.\r
- *\r
- * The fourth and last (?) part is an array with offsets to the records\r
- * in the first part of this file segment.\r
- */\r
-\r
- int infolen, nameoffset, reclength, nrattributes, i;\r
- int recoffset = offset + sizeof(INT);\r
-\r
- char recbuf[512];\r
- MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;\r
-\r
- TRACE_(typelib)("\n");\r
-\r
- MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);\r
-\r
- for ( i = 0; i < cFuncs ; i++ )\r
- {\r
- *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));\r
-\r
- /* name, eventually add to a hash table */\r
- MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,\r
- offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));\r
-\r
- (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);\r
-\r
- /* read the function information record */\r
- MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);\r
-\r
- reclength &= 0x1ff;\r
-\r
- MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);\r
-\r
- /* do the attributes */\r
- nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)\r
- / sizeof(int);\r
-\r
- if ( nrattributes > 0 )\r
- {\r
- (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;\r
-\r
- if ( nrattributes > 1 )\r
- {\r
- (*pptfd)->HelpString = MSFT_ReadString(pcx,\r
- pFuncRec->OptAttr[1]) ;\r
-\r
- if ( nrattributes > 2 )\r
- {\r
- if ( pFuncRec->FKCCIC & 0x2000 )\r
- {\r
- (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;\r
- }\r
- else\r
- {\r
- (*pptfd)->Entry = MSFT_ReadString(pcx,\r
- pFuncRec->OptAttr[2]);\r
- }\r
- if( nrattributes > 5 )\r
- {\r
- (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;\r
-\r
- if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )\r
- {\r
- MSFT_CustData(pcx,\r
- pFuncRec->OptAttr[6],\r
- &(*pptfd)->pCustData);\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- /* fill the FuncDesc Structure */\r
- MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,\r
- offset + infolen + ( i + 1) * sizeof(INT));\r
-\r
- (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;\r
- (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;\r
- (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;\r
- (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;\r
- (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;\r
- (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;\r
- (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;\r
-\r
- MSFT_GetTdesc(pcx,\r
- pFuncRec->DataType,\r
- &(*pptfd)->funcdesc.elemdescFunc.tdesc,\r
- pTI);\r
-\r
- /* do the parameters/arguments */\r
- if(pFuncRec->nrargs)\r
- {\r
- int j = 0;\r
- MSFT_ParameterInfo paraminfo;\r
-\r
- (*pptfd)->funcdesc.lprgelemdescParam =\r
- TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));\r
-\r
- (*pptfd)->pParamDesc =\r
- TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));\r
-\r
- MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,\r
- recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));\r
-\r
- for ( j = 0 ; j < pFuncRec->nrargs ; j++ )\r
- {\r
- TYPEDESC* lpArgTypeDesc = 0;\r
-\r
- MSFT_GetTdesc(pcx,\r
- paraminfo.DataType,\r
- &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,\r
- pTI);\r
-\r
- (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;\r
-\r
- (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;\r
-\r
- /* SEEK value = jump to offset,\r
- * from there jump to the end of record,\r
- * go back by (j-1) arguments\r
- */\r
- MSFT_ReadLEDWords( ¶minfo ,\r
- sizeof(MSFT_ParameterInfo), pcx,\r
- recoffset + reclength - ((pFuncRec->nrargs - j - 1)\r
- * sizeof(MSFT_ParameterInfo)));\r
- lpArgTypeDesc =\r
- & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);\r
-\r
- while ( lpArgTypeDesc != NULL )\r
- {\r
- switch ( lpArgTypeDesc->vt )\r
- {\r
- case VT_PTR:\r
- lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;\r
- break;\r
-\r
- case VT_CARRAY:\r
- lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);\r
- break;\r
-\r
- case VT_USERDEFINED:\r
- MSFT_DoRefType(pcx, pTI,\r
- lpArgTypeDesc->u.hreftype);\r
-\r
- lpArgTypeDesc = NULL;\r
- break;\r
-\r
- default:\r
- lpArgTypeDesc = NULL;\r
- }\r
- }\r
- }\r
-\r
-\r
- /* parameter is the return value! */\r
- if ( paraminfo.Flags & PARAMFLAG_FRETVAL )\r
- {\r
- TYPEDESC* lpArgTypeDesc;\r
-\r
- (*pptfd)->funcdesc.elemdescFunc =\r
- (*pptfd)->funcdesc.lprgelemdescParam[j];\r
-\r
- lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;\r
-\r
- while ( lpArgTypeDesc != NULL )\r
- {\r
- switch ( lpArgTypeDesc->vt )\r
- {\r
- case VT_PTR:\r
- lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;\r
- break;\r
- case VT_CARRAY:\r
- lpArgTypeDesc =\r
- & (lpArgTypeDesc->u.lpadesc->tdescElem);\r
-\r
- break;\r
-\r
- case VT_USERDEFINED:\r
- MSFT_DoRefType(pcx,\r
- pTI,\r
- lpArgTypeDesc->u.hreftype);\r
-\r
- lpArgTypeDesc = NULL;\r
- break;\r
-\r
- default:\r
- lpArgTypeDesc = NULL;\r
- }\r
- }\r
- }\r
-\r
- /* second time around */\r
- for(j=0;j<pFuncRec->nrargs;j++)\r
- {\r
- /* name */\r
- (*pptfd)->pParamDesc[j].Name =\r
- MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );\r
-\r
- /* default value */\r
- if ( (PARAMFLAG_FHASDEFAULT &\r
- (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&\r
- ((pFuncRec->FKCCIC) & 0x1000) )\r
- {\r
- INT* pInt = (INT *)((char *)pFuncRec +\r
- reclength -\r
- (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );\r
-\r
- PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;\r
-\r
- pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));\r
- pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);\r
-\r
- MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),\r
- pInt[j], pcx);\r
- }\r
- /* custom info */\r
- if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )\r
- {\r
- MSFT_CustData(pcx,\r
- pFuncRec->OptAttr[7+j],\r
- &(*pptfd)->pParamDesc[j].pCustData);\r
- }\r
- }\r
- }\r
-\r
- /* scode is not used: archaic win16 stuff FIXME: right? */\r
- (*pptfd)->funcdesc.cScodes = 0 ;\r
- (*pptfd)->funcdesc.lprgscode = NULL ;\r
-\r
- pptfd = & ((*pptfd)->next);\r
- recoffset += reclength;\r
- }\r
-}\r
-\r
-static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,\r
- int cVars, int offset, TLBVarDesc ** pptvd)\r
-{\r
- int infolen, nameoffset, reclength;\r
- char recbuf[256];\r
- MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;\r
- int i;\r
- int recoffset;\r
-\r
- TRACE_(typelib)("\n");\r
-\r
- MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);\r
- MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +\r
- ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));\r
- recoffset += offset+sizeof(INT);\r
- for(i=0;i<cVars;i++){\r
- *pptvd=TLB_Alloc(sizeof(TLBVarDesc));\r
- /* name, eventually add to a hash table */\r
- MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,\r
- offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));\r
- (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);\r
- /* read the variable information record */\r
- MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);\r
- reclength &=0xff;\r
- MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);\r
- /* Optional data */\r
- if(reclength >(6*sizeof(INT)) )\r
- (*pptvd)->HelpContext=pVarRec->HelpContext;\r
- if(reclength >(7*sizeof(INT)) )\r
- (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;\r
- if(reclength >(8*sizeof(INT)) )\r
- if(reclength >(9*sizeof(INT)) )\r
- (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;\r
- /* fill the VarDesc Structure */\r
- MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,\r
- offset + infolen + ( i + 1) * sizeof(INT));\r
- (*pptvd)->vardesc.varkind = pVarRec->VarKind;\r
- (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;\r
- MSFT_GetTdesc(pcx, pVarRec->DataType,\r
- &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);\r
-/* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */\r
- if(pVarRec->VarKind == VAR_CONST ){\r
- (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));\r
- MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,\r
- pVarRec->OffsValue, pcx);\r
- } else\r
- (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;\r
- pptvd=&((*pptvd)->next);\r
- recoffset += reclength;\r
- }\r
-}\r
-/* fill in data for a hreftype (offset). When the referenced type is contained\r
- * in the typelib, it's just an (file) offset in the type info base dir.\r
- * If comes from import, it's an offset+1 in the ImpInfo table\r
- * */\r
-static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,\r
- int offset)\r
-{\r
- int j;\r
- TLBRefType **ppRefType = &pTI->reflist;\r
-\r
- TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);\r
-\r
- while(*ppRefType) {\r
- if((*ppRefType)->reference == offset)\r
- return;\r
- ppRefType = &(*ppRefType)->next;\r
- }\r
-\r
- *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(**ppRefType));\r
-\r
- if(!MSFT_HREFTYPE_INTHISFILE( offset)) {\r
- /* external typelib */\r
- MSFT_ImpInfo impinfo;\r
- TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);\r
-\r
- TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));\r
-\r
- MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,\r
- pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));\r
- for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */\r
- if(pImpLib->offset==impinfo.oImpFile) break;\r
- pImpLib=pImpLib->next;\r
- }\r
- if(pImpLib){\r
- (*ppRefType)->reference=offset;\r
- (*ppRefType)->pImpTLInfo = pImpLib;\r
- MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);\r
- (*ppRefType)->index = TLB_REF_USE_GUID;\r
- }else{\r
- ERR("Cannot find a reference\n");\r
- (*ppRefType)->reference=-1;\r
- (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;\r
- }\r
- }else{\r
- /* in this typelib */\r
- (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);\r
- (*ppRefType)->reference=offset;\r
- (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;\r
- }\r
-}\r
-\r
-/* process Implemented Interfaces of a com class */\r
-static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,\r
- int offset)\r
-{\r
- int i;\r
- MSFT_RefRecord refrec;\r
- TLBImplType **ppImpl = &pTI->impltypelist;\r
-\r
- TRACE_(typelib)("\n");\r
-\r
- for(i=0;i<count;i++){\r
- if(offset<0) break; /* paranoia */\r
- *ppImpl=TLB_Alloc(sizeof(**ppImpl));\r
- MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);\r
- MSFT_DoRefType(pcx, pTI, refrec.reftype);\r
- (*ppImpl)->hRef = refrec.reftype;\r
- (*ppImpl)->implflags=refrec.flags;\r
- (*ppImpl)->ctCustData=\r
- MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);\r
- offset=refrec.onext;\r
- ppImpl=&((*ppImpl)->next);\r
- }\r
-}\r
-/*\r
- * process a typeinfo record\r
- */\r
-ITypeInfoImpl * MSFT_DoTypeInfo(\r
- TLBContext *pcx,\r
- int count,\r
- ITypeLibImpl * pLibInfo)\r
-{\r
- MSFT_TypeInfoBase tiBase;\r
- ITypeInfoImpl *ptiRet;\r
-\r
- TRACE_(typelib)("count=%u\n", count);\r
-\r
- ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();\r
- MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,\r
- pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));\r
-/* this is where we are coming from */\r
- ptiRet->pTypeLib = pLibInfo;\r
- ptiRet->index=count;\r
-/* fill in the typeattr fields */\r
- WARN("Assign constructor/destructor memid\n");\r
-\r
- MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);\r
- ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */\r
- ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */\r
- ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */\r
- ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */\r
- ptiRet->TypeAttr.cbSizeInstance=tiBase.size;\r
- ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;\r
- ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);\r
- ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);\r
- ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */\r
- ptiRet->TypeAttr.wTypeFlags=tiBase.flags;\r
- ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);\r
- ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);\r
- ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;\r
- ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */\r
- if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)\r
- MSFT_GetTdesc(pcx, tiBase.datatype1,\r
- &ptiRet->TypeAttr.tdescAlias, ptiRet);\r
-\r
-/* FIXME: */\r
-/* IDLDESC idldescType; *//* never saw this one != zero */\r
-\r
-/* name, eventually add to a hash table */\r
- ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);\r
- TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));\r
- /* help info */\r
- ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);\r
- ptiRet->dwHelpStringContext=tiBase.helpstringcontext;\r
- ptiRet->dwHelpContext=tiBase.helpcontext;\r
-/* note: InfoType's Help file and HelpStringDll come from the containing\r
- * library. Further HelpString and Docstring appear to be the same thing :(\r
- */\r
- /* functions */\r
- if(ptiRet->TypeAttr.cFuncs >0 )\r
- MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,\r
- ptiRet->TypeAttr.cVars,\r
- tiBase.memoffset, & ptiRet->funclist);\r
- /* variables */\r
- if(ptiRet->TypeAttr.cVars >0 )\r
- MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,\r
- ptiRet->TypeAttr.cVars,\r
- tiBase.memoffset, & ptiRet->varlist);\r
- if(ptiRet->TypeAttr.cImplTypes >0 ) {\r
- switch(ptiRet->TypeAttr.typekind)\r
- {\r
- case TKIND_COCLASS:\r
- MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,\r
- tiBase.datatype1);\r
- break;\r
- case TKIND_DISPATCH:\r
- ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));\r
-\r
- if (tiBase.datatype1 != -1)\r
- {\r
- MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);\r
- ptiRet->impltypelist->hRef = tiBase.datatype1;\r
- }\r
- else\r
- { /* FIXME: This is a really bad hack to add IDispatch */\r
- const char* szStdOle = "stdole2.tlb\0";\r
- int nStdOleLen = strlen(szStdOle);\r
- TLBRefType **ppRef = &ptiRet->reflist;\r
-\r
- while(*ppRef) {\r
- if((*ppRef)->reference == -1)\r
- break;\r
- ppRef = &(*ppRef)->next;\r
- }\r
- if(!*ppRef) {\r
- *ppRef = TLB_Alloc(sizeof(**ppRef));\r
- (*ppRef)->guid = IID_IDispatch;\r
- (*ppRef)->reference = -1;\r
- (*ppRef)->index = TLB_REF_USE_GUID;\r
- (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));\r
- (*ppRef)->pImpTLInfo->guid = IID_StdOle;\r
- (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,\r
- nStdOleLen + 1);\r
-\r
- MultiByteToWideChar(CP_ACP,\r
- MB_PRECOMPOSED,\r
- szStdOle,\r
- -1,\r
- (*ppRef)->pImpTLInfo->name,\r
- SysStringLen((*ppRef)->pImpTLInfo->name));\r
-\r
- (*ppRef)->pImpTLInfo->lcid = 0;\r
- (*ppRef)->pImpTLInfo->wVersionMajor = 2;\r
- (*ppRef)->pImpTLInfo->wVersionMinor = 0;\r
- }\r
- }\r
- break;\r
- default:\r
- ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));\r
- MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);\r
- ptiRet->impltypelist->hRef = tiBase.datatype1;\r
- break;\r
- }\r
- }\r
- ptiRet->ctCustData=\r
- MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);\r
-\r
- TRACE_(typelib)("%s guid: %s kind:%s\n",\r
- debugstr_w(ptiRet->Name),\r
- debugstr_guid(&ptiRet->TypeAttr.guid),\r
- typekind_desc[ptiRet->TypeAttr.typekind]);\r
-\r
- return ptiRet;\r
-}\r
-\r
-/* Because type library parsing has some degree of overhead, and some apps repeatedly load the same\r
- * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in\r
- * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable\r
- * tradeoff here.\r
- */\r
-static ITypeLibImpl *tlb_cache_first;\r
-static CRITICAL_SECTION cache_section;\r
-static CRITICAL_SECTION_DEBUG cache_section_debug =\r
-{\r
- 0, 0, &cache_section,\r
- { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },\r
- 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }\r
-};\r
-static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };\r
-\r
-\r
-/****************************************************************************\r
- * TLB_ReadTypeLib\r
- *\r
- * find the type of the typelib file and map the typelib resource into\r
- * the memory\r
- */\r
-#define MSFT_SIGNATURE 0x5446534D /* "MSFT" */\r
-#define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */\r
-int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)\r
-{\r
- ITypeLibImpl *entry;\r
- int ret = TYPE_E_CANTLOADLIBRARY;\r
- DWORD dwSignature = 0;\r
- HANDLE hFile;\r
-\r
- TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);\r
-\r
- *ppTypeLib = NULL;\r
-\r
- /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */\r
- EnterCriticalSection(&cache_section);\r
- for (entry = tlb_cache_first; entry != NULL; entry = entry->next)\r
- {\r
- if (!strcmpiW(entry->path, pszFileName) && entry->index == index)\r
- {\r
- TRACE("cache hit\n");\r
- *ppTypeLib = (ITypeLib2*)entry;\r
- ITypeLib_AddRef(*ppTypeLib);\r
- LeaveCriticalSection(&cache_section);\r
- return S_OK;\r
- }\r
- }\r
- LeaveCriticalSection(&cache_section);\r
-\r
- /* check the signature of the file */\r
- hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );\r
- if (INVALID_HANDLE_VALUE != hFile)\r
- {\r
- HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );\r
- if (hMapping)\r
- {\r
- LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);\r
- if(pBase)\r
- {\r
- /* retrieve file size */\r
- DWORD dwTLBLength = GetFileSize(hFile, NULL);\r
-\r
- /* first try to load as *.tlb */\r
- dwSignature = FromLEDWord(*((DWORD*) pBase));\r
- if ( dwSignature == MSFT_SIGNATURE)\r
- {\r
- *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);\r
- }\r
- else if ( dwSignature == SLTG_SIGNATURE)\r
- {\r
- *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);\r
- }\r
- UnmapViewOfFile(pBase);\r
- }\r
- CloseHandle(hMapping);\r
- }\r
- CloseHandle(hFile);\r
- }\r
- else\r
- {\r
- TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));\r
- }\r
-\r
- /* if the file is a DLL or not found, try loading it with LoadLibrary */\r
- if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))\r
- {\r
- /* find the typelibrary resource*/\r
- HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|\r
- LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);\r
- if (hinstDLL)\r
- {\r
- static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};\r
- HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);\r
- if (hrsrc)\r
- {\r
- HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);\r
- if (hGlobal)\r
- {\r
- LPVOID pBase = LockResource(hGlobal);\r
- DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);\r
-\r
- if (pBase)\r
- {\r
- /* try to load as incore resource */\r
- dwSignature = FromLEDWord(*((DWORD*) pBase));\r
- if ( dwSignature == MSFT_SIGNATURE)\r
- {\r
- *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);\r
- }\r
- else if ( dwSignature == SLTG_SIGNATURE)\r
- {\r
- *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);\r
- }\r
- else\r
- {\r
- FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);\r
- }\r
- }\r
- FreeResource( hGlobal );\r
- }\r
- }\r
- FreeLibrary(hinstDLL);\r
- }\r
- }\r
-\r
- if(*ppTypeLib) {\r
- ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;\r
-\r
- TRACE("adding to cache\n");\r
- impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));\r
- lstrcpyW(impl->path, pszFileName);\r
- /* We should really canonicalise the path here. */\r
- impl->index = index;\r
-\r
- /* FIXME: check if it has added already in the meantime */\r
- EnterCriticalSection(&cache_section);\r
- if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;\r
- impl->prev = NULL;\r
- tlb_cache_first = impl;\r
- LeaveCriticalSection(&cache_section);\r
- ret = S_OK;\r
- } else\r
- ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());\r
-\r
- return ret;\r
-}\r
-\r
-/*================== ITypeLib(2) Methods ===================================*/\r
-\r
-/****************************************************************************\r
- * ITypeLib2_Constructor_MSFT\r
- *\r
- * loading an MSFT typelib from an in-memory image\r
- */\r
-static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)\r
-{\r
- TLBContext cx;\r
- long lPSegDir;\r
- MSFT_Header tlbHeader;\r
- MSFT_SegDir tlbSegDir;\r
- ITypeLibImpl * pTypeLibImpl;\r
-\r
- TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);\r
-\r
- pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));\r
- if (!pTypeLibImpl) return NULL;\r
-\r
- pTypeLibImpl->lpVtbl = &tlbvt;\r
- pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;\r
- pTypeLibImpl->ref = 1;\r
-\r
- /* get pointer to beginning of typelib data */\r
- cx.pos = 0;\r
- cx.oStart=0;\r
- cx.mapping = pLib;\r
- cx.pLibInfo = pTypeLibImpl;\r
- cx.length = dwTLBLength;\r
-\r
- /* read header */\r
- MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);\r
- TRACE("header:\n");\r
- TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );\r
- if (tlbHeader.magic1 != MSFT_SIGNATURE) {\r
- FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);\r
- return NULL;\r
- }\r
- /* there is a small amount of information here until the next important\r
- * part:\r
- * the segment directory . Try to calculate the amount of data */\r
- lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);\r
-\r
- /* now read the segment directory */\r
- TRACE("read segment directory (at %ld)\n",lPSegDir);\r
- MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);\r
- cx.pTblDir = &tlbSegDir;\r
-\r
- /* just check two entries */\r
- if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)\r
- {\r
- ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);\r
- HeapFree(GetProcessHeap(),0,pTypeLibImpl);\r
- return NULL;\r
- }\r
-\r
- /* now fill our internal data */\r
- /* TLIBATTR fields */\r
- MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);\r
-\r
- /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/\r
- /* Windows seems to have zero here, is this correct? */\r
- if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)\r
- pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);\r
- else\r
- pTypeLibImpl->LibAttr.lcid = 0;\r
-\r
- pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */\r
- pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);\r
- pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);\r
- pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */\r
-\r
- /* name, eventually add to a hash table */\r
- pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);\r
-\r
- /* help info */\r
- pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);\r
- pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);\r
-\r
- if( tlbHeader.varflags & HELPDLLFLAG)\r
- {\r
- int offset;\r
- MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));\r
- pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);\r
- }\r
-\r
- pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;\r
-\r
- /* custom data */\r
- if(tlbHeader.CustomDataOffset >= 0)\r
- {\r
- pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);\r
- }\r
-\r
- /* fill in typedescriptions */\r
- if(tlbSegDir.pTypdescTab.length > 0)\r
- {\r
- int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));\r
- INT16 td[4];\r
- pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));\r
- MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);\r
- for(i=0; i<cTD; )\r
- {\r
- /* FIXME: add several sanity checks here */\r
- pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;\r
- if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)\r
- {\r
- /* FIXME: check safearray */\r
- if(td[3] < 0)\r
- pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];\r
- else\r
- pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];\r
- }\r
- else if(td[0] == VT_CARRAY)\r
- {\r
- /* array descr table here */\r
- pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/\r
- }\r
- else if(td[0] == VT_USERDEFINED)\r
- {\r
- pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);\r
- }\r
- if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);\r
- }\r
-\r
- /* second time around to fill the array subscript info */\r
- for(i=0;i<cTD;i++)\r
- {\r
- if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;\r
- if(tlbSegDir.pArrayDescriptions.offset>0)\r
- {\r
- MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);\r
- pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));\r
-\r
- if(td[1]<0)\r
- pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;\r
- else\r
- pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];\r
-\r
- pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];\r
-\r
- for(j = 0; j<td[2]; j++)\r
- {\r
- MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,\r
- sizeof(INT), &cx, DO_NOT_SEEK);\r
- MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,\r
- sizeof(INT), &cx, DO_NOT_SEEK);\r
- }\r
- }\r
- else\r
- {\r
- pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;\r
- ERR("didn't find array description data\n");\r
- }\r
- }\r
- }\r
-\r
- /* imported type libs */\r
- if(tlbSegDir.pImpFiles.offset>0)\r
- {\r
- TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);\r
- int oGuid, offset = tlbSegDir.pImpFiles.offset;\r
- UINT16 size;\r
-\r
- while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)\r
- {\r
- char *name;\r
- DWORD len;\r
-\r
- *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));\r
- (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;\r
- MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);\r
-\r
- MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);\r
- MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);\r
- MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);\r
- MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);\r
-\r
- size >>= 2;\r
- name = TLB_Alloc(size+1);\r
- MSFT_Read(name, size, &cx, DO_NOT_SEEK);\r
- len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );\r
- (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));\r
- MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );\r
- TLB_Free(name);\r
-\r
- MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);\r
- offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;\r
-\r
- ppImpLib = &(*ppImpLib)->next;\r
- }\r
- }\r
-\r
- /* type info's */\r
- if(tlbHeader.nrtypeinfos >= 0 )\r
- {\r
- /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */\r
- ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);\r
- int i;\r
-\r
- for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)\r
- {\r
- *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);\r
-\r
- ppTI = &((*ppTI)->next);\r
- (pTypeLibImpl->TypeInfoCount)++;\r
- }\r
- }\r
-\r
- TRACE("(%p)\n", pTypeLibImpl);\r
- return (ITypeLib2*) pTypeLibImpl;\r
-}\r
-\r
-\r
-static BSTR TLB_MultiByteToBSTR(char *ptr)\r
-{\r
- DWORD len;\r
- WCHAR *nameW;\r
- BSTR ret;\r
-\r
- len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);\r
- nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));\r
- MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);\r
- ret = SysAllocString(nameW);\r
- HeapFree(GetProcessHeap(), 0, nameW);\r
- return ret;\r
-}\r
-\r
-static BOOL TLB_GUIDFromString(char *str, GUID *guid)\r
-{\r
- char b[3];\r
- int i;\r
- short s;\r
-\r
- if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {\r
- FIXME("Can't parse guid %s\n", debugstr_guid(guid));\r
- return FALSE;\r
- }\r
-\r
- guid->Data4[0] = s >> 8;\r
- guid->Data4[1] = s & 0xff;\r
-\r
- b[2] = '\0';\r
- for(i = 0; i < 6; i++) {\r
- memcpy(b, str + 24 + 2 * i, 2);\r
- guid->Data4[i + 2] = strtol(b, NULL, 16);\r
- }\r
- return TRUE;\r
-}\r
-\r
-static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)\r
-{\r
- WORD bytelen;\r
- DWORD len;\r
- WCHAR *nameW;\r
-\r
- *pBstr = NULL;\r
- bytelen = *(WORD*)ptr;\r
- if(bytelen == 0xffff) return 2;\r
- len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);\r
- nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));\r
- len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);\r
- *pBstr = SysAllocStringLen(nameW, len);\r
- HeapFree(GetProcessHeap(), 0, nameW);\r
- return bytelen + 2;\r
-}\r
-\r
-static WORD SLTG_ReadStringA(char *ptr, char **str)\r
-{\r
- WORD bytelen;\r
-\r
- *str = NULL;\r
- bytelen = *(WORD*)ptr;\r
- if(bytelen == 0xffff) return 2;\r
- *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);\r
- memcpy(*str, ptr + 2, bytelen);\r
- (*str)[bytelen] = '\0';\r
- return bytelen + 2;\r
-}\r
-\r
-static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)\r
-{\r
- char *ptr = pLibBlk;\r
- WORD w;\r
-\r
- if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {\r
- FIXME("libblk magic = %04x\n", w);\r
- return 0;\r
- }\r
-\r
- ptr += 6;\r
- if((w = *(WORD*)ptr) != 0xffff) {\r
- FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);\r
- ptr += w;\r
- }\r
- ptr += 2;\r
-\r
- ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);\r
-\r
- ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);\r
-\r
- pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;\r
- ptr += 4;\r
-\r
- pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;\r
- ptr += 2;\r
-\r
- if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)\r
- pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);\r
- else\r
- pTypeLibImpl->LibAttr.lcid = 0;\r
- ptr += 2;\r
-\r
- ptr += 4; /* skip res12 */\r
-\r
- pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;\r
- ptr += 2;\r
-\r
- pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;\r
- ptr += 2;\r
-\r
- pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;\r
- ptr += 2;\r
-\r
- memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));\r
- ptr += sizeof(GUID);\r
-\r
- return ptr - (char*)pLibBlk;\r
-}\r
-\r
-static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)\r
-{\r
- BOOL done = FALSE;\r
- TYPEDESC *pTD = &pElem->tdesc;\r
-\r
- /* Handle [in/out] first */\r
- if((*pType & 0xc000) == 0xc000)\r
- pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;\r
- else if(*pType & 0x8000)\r
- pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;\r
- else if(*pType & 0x4000)\r
- pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;\r
- else\r
- pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;\r
-\r
- if(*pType & 0x2000)\r
- pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;\r
-\r
- if(*pType & 0x80)\r
- pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;\r
-\r
- while(!done) {\r
- if((*pType & 0xe00) == 0xe00) {\r
- pTD->vt = VT_PTR;\r
- pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(TYPEDESC));\r
- pTD = pTD->u.lptdesc;\r
- }\r
- switch(*pType & 0x7f) {\r
- case VT_PTR:\r
- pTD->vt = VT_PTR;\r
- pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(TYPEDESC));\r
- pTD = pTD->u.lptdesc;\r
- break;\r
-\r
- case VT_USERDEFINED:\r
- pTD->vt = VT_USERDEFINED;\r
- pTD->u.hreftype = *(++pType) / 4;\r
- done = TRUE;\r
- break;\r
-\r
- case VT_CARRAY:\r
- {\r
- /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of\r
- array */\r
-\r
- SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));\r
-\r
- pTD->vt = VT_CARRAY;\r
- pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(ARRAYDESC) +\r
- (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));\r
- pTD->u.lpadesc->cDims = pSA->cDims;\r
- memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,\r
- pSA->cDims * sizeof(SAFEARRAYBOUND));\r
-\r
- pTD = &pTD->u.lpadesc->tdescElem;\r
- break;\r
- }\r
-\r
- case VT_SAFEARRAY:\r
- {\r
- /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this\r
- useful? */\r
-\r
- pType++;\r
- pTD->vt = VT_SAFEARRAY;\r
- pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(TYPEDESC));\r
- pTD = pTD->u.lptdesc;\r
- break;\r
- }\r
- default:\r
- pTD->vt = *pType & 0x7f;\r
- done = TRUE;\r
- break;\r
- }\r
- pType++;\r
- }\r
- return pType;\r
-}\r
-\r
-\r
-static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,\r
- char *pNameTable)\r
-{\r
- int ref;\r
- char *name;\r
- TLBRefType **ppRefType;\r
-\r
- if(pRef->magic != SLTG_REF_MAGIC) {\r
- FIXME("Ref magic = %x\n", pRef->magic);\r
- return;\r
- }\r
- name = ( (char*)(&pRef->names) + pRef->number);\r
-\r
- ppRefType = &pTI->reflist;\r
- for(ref = 0; ref < pRef->number >> 3; ref++) {\r
- char *refname;\r
- unsigned int lib_offs, type_num;\r
-\r
- *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(**ppRefType));\r
-\r
- name += SLTG_ReadStringA(name, &refname);\r
- if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)\r
- FIXME("Can't sscanf ref\n");\r
- if(lib_offs != 0xffff) {\r
- TLBImpLib **import = &pTI->pTypeLib->pImpLibs;\r
-\r
- while(*import) {\r
- if((*import)->offset == lib_offs)\r
- break;\r
- import = &(*import)->next;\r
- }\r
- if(!*import) {\r
- char fname[MAX_PATH+1];\r
- int len;\r
-\r
- *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(**import));\r
- (*import)->offset = lib_offs;\r
- TLB_GUIDFromString( pNameTable + lib_offs + 4,\r
- &(*import)->guid);\r
- if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",\r
- &(*import)->wVersionMajor,\r
- &(*import)->wVersionMinor,\r
- &(*import)->lcid, fname) != 4) {\r
- FIXME("can't sscanf ref %s\n",\r
- pNameTable + lib_offs + 40);\r
- }\r
- len = strlen(fname);\r
- if(fname[len-1] != '#')\r
- FIXME("fname = %s\n", fname);\r
- fname[len-1] = '\0';\r
- (*import)->name = TLB_MultiByteToBSTR(fname);\r
- }\r
- (*ppRefType)->pImpTLInfo = *import;\r
- } else { /* internal ref */\r
- (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;\r
- }\r
- (*ppRefType)->reference = ref;\r
- (*ppRefType)->index = type_num;\r
-\r
- HeapFree(GetProcessHeap(), 0, refname);\r
- ppRefType = &(*ppRefType)->next;\r
- }\r
- if((BYTE)*name != SLTG_REF_MAGIC)\r
- FIXME("End of ref block magic = %x\n", *name);\r
- dump_TLBRefType(pTI->reflist);\r
-}\r
-\r
-static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,\r
- BOOL OneOnly)\r
-{\r
- SLTG_ImplInfo *info;\r
- TLBImplType **ppImplType = &pTI->impltypelist;\r
- /* I don't really get this structure, usually it's 0x16 bytes\r
- long, but iuser.tlb contains some that are 0x18 bytes long.\r
- That's ok because we can use the next ptr to jump to the next\r
- one. But how do we know the length of the last one? The WORD\r
- at offs 0x8 might be the clue. For now I'm just assuming that\r
- the last one is the regular 0x16 bytes. */\r
-\r
- info = (SLTG_ImplInfo*)pBlk;\r
- while(1) {\r
- *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(**ppImplType));\r
- (*ppImplType)->hRef = info->ref;\r
- (*ppImplType)->implflags = info->impltypeflags;\r
- pTI->TypeAttr.cImplTypes++;\r
- ppImplType = &(*ppImplType)->next;\r
-\r
- if(info->next == 0xffff)\r
- break;\r
- if(OneOnly)\r
- FIXME("Interface inheriting more than one interface\n");\r
- info = (SLTG_ImplInfo*)(pBlk + info->next);\r
- }\r
- info++; /* see comment at top of function */\r
- return (char*)info;\r
-}\r
-\r
-static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,\r
- char *pNameTable)\r
-{\r
- SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;\r
- SLTG_MemberHeader *pMemHeader;\r
- char *pFirstItem, *pNextItem;\r
-\r
- if(pTIHeader->href_table != 0xffffffff) {\r
- SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,\r
- pNameTable);\r
- }\r
-\r
-\r
- pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);\r
-\r
- pFirstItem = pNextItem = (char*)(pMemHeader + 1);\r
-\r
- if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {\r
- pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);\r
- }\r
-\r
- return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);\r
-}\r
-\r
-\r
-static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,\r
- char *pNameTable)\r
-{\r
- SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;\r
- SLTG_MemberHeader *pMemHeader;\r
- SLTG_Function *pFunc;\r
- char *pFirstItem, *pNextItem;\r
- TLBFuncDesc **ppFuncDesc = &pTI->funclist;\r
- int num = 0;\r
-\r
- if(pTIHeader->href_table != 0xffffffff) {\r
- SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,\r
- pNameTable);\r
- }\r
-\r
- pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);\r
-\r
- pFirstItem = pNextItem = (char*)(pMemHeader + 1);\r
-\r
- if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {\r
- pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);\r
- }\r
-\r
- for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;\r
- pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {\r
-\r
- int param;\r
- WORD *pType, *pArg;\r
-\r
- if(pFunc->magic != SLTG_FUNCTION_MAGIC &&\r
- pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {\r
- FIXME("func magic = %02x\n", pFunc->magic);\r
- return NULL;\r
- }\r
- *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(**ppFuncDesc));\r
- (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);\r
-\r
- (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;\r
- (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;\r
- (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;\r
- (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;\r
- (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;\r
- (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;\r
-\r
- if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)\r
- (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;\r
-\r
- if(pFunc->retnextopt & 0x80)\r
- pType = &pFunc->rettype;\r
- else\r
- pType = (WORD*)(pFirstItem + pFunc->rettype);\r
-\r
-\r
- SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);\r
-\r
- (*ppFuncDesc)->funcdesc.lprgelemdescParam =\r
- HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));\r
- (*ppFuncDesc)->pParamDesc =\r
- HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));\r
-\r
- pArg = (WORD*)(pFirstItem + pFunc->arg_off);\r
-\r
- for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {\r
- char *paramName = pNameTable + *pArg;\r
- BOOL HaveOffs;\r
- /* If arg type follows then paramName points to the 2nd\r
- letter of the name, else the next WORD is an offset to\r
- the arg type and paramName points to the first letter.\r
- So let's take one char off paramName and see if we're\r
- pointing at an alpha-numeric char. However if *pArg is\r
- 0xffff or 0xfffe then the param has no name, the former\r
- meaning that the next WORD is the type, the latter\r
- meaning the the next WORD is an offset to the type. */\r
-\r
- HaveOffs = FALSE;\r
- if(*pArg == 0xffff)\r
- paramName = NULL;\r
- else if(*pArg == 0xfffe) {\r
- paramName = NULL;\r
- HaveOffs = TRUE;\r
- }\r
- else if(!isalnum(*(paramName-1)))\r
- HaveOffs = TRUE;\r
-\r
- pArg++;\r
-\r
- if(HaveOffs) { /* the next word is an offset to type */\r
- pType = (WORD*)(pFirstItem + *pArg);\r
- SLTG_DoType(pType, pFirstItem,\r
- &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);\r
- pArg++;\r
- } else {\r
- if(paramName)\r
- paramName--;\r
- pArg = SLTG_DoType(pArg, pFirstItem,\r
- &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);\r
- }\r
-\r
- /* Are we an optional param ? */\r
- if((*ppFuncDesc)->funcdesc.cParams - param <=\r
- (*ppFuncDesc)->funcdesc.cParamsOpt)\r
- (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;\r
-\r
- if(paramName) {\r
- (*ppFuncDesc)->pParamDesc[param].Name =\r
- TLB_MultiByteToBSTR(paramName);\r
- }\r
- }\r
-\r
- ppFuncDesc = &((*ppFuncDesc)->next);\r
- if(pFunc->next == 0xffff) break;\r
- }\r
- pTI->TypeAttr.cFuncs = num;\r
- dump_TLBFuncDesc(pTI->funclist);\r
- return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);\r
-}\r
-\r
-static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,\r
- char *pNameTable)\r
-{\r
- SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;\r
- SLTG_MemberHeader *pMemHeader;\r
- SLTG_RecordItem *pItem;\r
- char *pFirstItem;\r
- TLBVarDesc **ppVarDesc = &pTI->varlist;\r
- int num = 0;\r
- WORD *pType;\r
- char buf[300];\r
-\r
- pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);\r
-\r
- pFirstItem = (char*)(pMemHeader + 1);\r
- for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;\r
- pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {\r
- if(pItem->magic != SLTG_RECORD_MAGIC) {\r
- FIXME("record magic = %02x\n", pItem->magic);\r
- return NULL;\r
- }\r
- *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(**ppVarDesc));\r
- (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);\r
- (*ppVarDesc)->vardesc.memid = pItem->memid;\r
- (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;\r
- (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;\r
-\r
- if(pItem->typepos == 0x02)\r
- pType = &pItem->type;\r
- else if(pItem->typepos == 0x00)\r
- pType = (WORD*)(pFirstItem + pItem->type);\r
- else {\r
- FIXME("typepos = %02x\n", pItem->typepos);\r
- break;\r
- }\r
-\r
- SLTG_DoType(pType, pFirstItem,\r
- &(*ppVarDesc)->vardesc.elemdescVar);\r
-\r
- /* FIXME("helpcontext, helpstring\n"); */\r
-\r
- dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);\r
-\r
- ppVarDesc = &((*ppVarDesc)->next);\r
- if(pItem->next == 0xffff) break;\r
- }\r
- pTI->TypeAttr.cVars = num;\r
- return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);\r
-}\r
-\r
-static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,\r
- char *pNameTable)\r
-{\r
- SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;\r
- SLTG_MemberHeader *pMemHeader;\r
- SLTG_AliasItem *pItem;\r
- int i, mustbelast;\r
-\r
- pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);\r
- pItem = (SLTG_AliasItem*)(pMemHeader + 1);\r
-\r
- mustbelast = 0;\r
- /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */\r
- for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {\r
- if (pItem->vt == 0xffff) {\r
- if (i<(pMemHeader->cbExtra/4-1))\r
- FIXME("Endmarker too early in process alias data!\n");\r
- break;\r
- }\r
- if (mustbelast) {\r
- FIXME("Chain extends over last entry?\n");\r
- break;\r
- }\r
- if (pItem->vt == VT_USERDEFINED) {\r
- pTI->TypeAttr.tdescAlias.vt = pItem->vt;\r
- /* guessing here ... */\r
- FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);\r
- pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;\r
- mustbelast = 1;\r
- } else {\r
- FIXME("alias %d: 0x%x\n",i,pItem->vt);\r
- FIXME("alias %d: 0x%x\n",i,pItem->res02);\r
- }\r
- pItem++;\r
- }\r
- return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);\r
-}\r
-\r
-static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,\r
- char *pNameTable)\r
-{\r
- SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;\r
- SLTG_MemberHeader *pMemHeader;\r
- SLTG_AliasItem *pItem;\r
-\r
- pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);\r
- pItem = (SLTG_AliasItem*)(pMemHeader + 1);\r
- FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);\r
- FIXME("offset 0 0x%x\n",*(WORD*)pItem);\r
- return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);\r
-}\r
-\r
-static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,\r
- char *pNameTable)\r
-{\r
- SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;\r
- SLTG_MemberHeader *pMemHeader;\r
- SLTG_EnumItem *pItem;\r
- char *pFirstItem;\r
- TLBVarDesc **ppVarDesc = &pTI->varlist;\r
- int num = 0;\r
-\r
- pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);\r
-\r
- pFirstItem = (char*)(pMemHeader + 1);\r
- for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;\r
- pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {\r
- if(pItem->magic != SLTG_ENUMITEM_MAGIC) {\r
- FIXME("enumitem magic = %04x\n", pItem->magic);\r
- return NULL;\r
- }\r
- *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(**ppVarDesc));\r
- (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);\r
- (*ppVarDesc)->vardesc.memid = pItem->memid;\r
- (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,\r
- sizeof(VARIANT));\r
- V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;\r
- V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =\r
- *(INT*)(pItem->value + pFirstItem);\r
- (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;\r
- (*ppVarDesc)->vardesc.varkind = VAR_CONST;\r
- /* FIXME("helpcontext, helpstring\n"); */\r
-\r
- ppVarDesc = &((*ppVarDesc)->next);\r
- if(pItem->next == 0xffff) break;\r
- }\r
- pTI->TypeAttr.cVars = num;\r
- return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);\r
-}\r
-\r
-/* Because SLTG_OtherTypeInfo is such a painful struct, we make a more\r
- managable copy of it into this */\r
-typedef struct {\r
- WORD small_no;\r
- char *index_name;\r
- char *other_name;\r
- WORD res1a;\r
- WORD name_offs;\r
- WORD more_bytes;\r
- char *extra;\r
- WORD res20;\r
- DWORD helpcontext;\r
- WORD res26;\r
- GUID uuid;\r
-} SLTG_InternalOtherTypeInfo;\r
-\r
-/****************************************************************************\r
- * ITypeLib2_Constructor_SLTG\r
- *\r
- * loading a SLTG typelib from an in-memory image\r
- */\r
-static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)\r
-{\r
- ITypeLibImpl *pTypeLibImpl;\r
- SLTG_Header *pHeader;\r
- SLTG_BlkEntry *pBlkEntry;\r
- SLTG_Magic *pMagic;\r
- SLTG_Index *pIndex;\r
- SLTG_Pad9 *pPad9;\r
- LPVOID pBlk, pFirstBlk;\r
- SLTG_LibBlk *pLibBlk;\r
- SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;\r
- char *pAfterOTIBlks = NULL;\r
- char *pNameTable, *ptr;\r
- int i;\r
- DWORD len, order;\r
- ITypeInfoImpl **ppTypeInfoImpl;\r
-\r
- TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);\r
-\r
- pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));\r
- if (!pTypeLibImpl) return NULL;\r
-\r
- pTypeLibImpl->lpVtbl = &tlbvt;\r
- pTypeLibImpl->ref = 1;\r
-\r
- pHeader = pLib;\r
-\r
- TRACE("header:\n");\r
- TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,\r
- pHeader->nrOfFileBlks );\r
- if (pHeader->SLTG_magic != SLTG_SIGNATURE) {\r
- FIXME("Header type magic 0x%08lx not supported.\n",\r
- pHeader->SLTG_magic);\r
- return NULL;\r
- }\r
-\r
- /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */\r
- pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;\r
-\r
- /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */\r
- pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);\r
-\r
- /* Next we have a magic block */\r
- pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);\r
-\r
- /* Let's see if we're still in sync */\r
- if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,\r
- sizeof(SLTG_COMPOBJ_MAGIC))) {\r
- FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);\r
- return NULL;\r
- }\r
- if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,\r
- sizeof(SLTG_DIR_MAGIC))) {\r
- FIXME("dir magic = %s\n", pMagic->dir_magic);\r
- return NULL;\r
- }\r
-\r
- pIndex = (SLTG_Index*)(pMagic+1);\r
-\r
- pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);\r
-\r
- pFirstBlk = (LPVOID)(pPad9 + 1);\r
-\r
- /* We'll set up a ptr to the main library block, which is the last one. */\r
-\r
- for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;\r
- pBlkEntry[order].next != 0;\r
- order = pBlkEntry[order].next - 1, i++) {\r
- pBlk = (char*)pBlk + pBlkEntry[order].len;\r
- }\r
- pLibBlk = pBlk;\r
-\r
- len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);\r
-\r
- /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount\r
- interspersed */\r
-\r
- len += 0x40;\r
-\r
- /* And now TypeInfoCount of SLTG_OtherTypeInfo */\r
-\r
- pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- sizeof(*pOtherTypeInfoBlks) *\r
- pTypeLibImpl->TypeInfoCount);\r
-\r
-\r
- ptr = (char*)pLibBlk + len;\r
-\r
- for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {\r
- WORD w, extra;\r
- len = 0;\r
-\r
- pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;\r
-\r
- w = *(WORD*)(ptr + 2);\r
- if(w != 0xffff) {\r
- len += w;\r
- pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,\r
- w+1);\r
- memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);\r
- pOtherTypeInfoBlks[i].index_name[w] = '\0';\r
- }\r
- w = *(WORD*)(ptr + 4 + len);\r
- if(w != 0xffff) {\r
- TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));\r
- len += w;\r
- pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,\r
- w+1);\r
- memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);\r
- pOtherTypeInfoBlks[i].other_name[w] = '\0';\r
- }\r
- pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);\r
- pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);\r
- extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);\r
- if(extra) {\r
- pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,\r
- extra);\r
- memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);\r
- len += extra;\r
- }\r
- pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);\r
- pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);\r
- pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);\r
- memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));\r
- len += sizeof(SLTG_OtherTypeInfo);\r
- ptr += len;\r
- }\r
-\r
- pAfterOTIBlks = ptr;\r
-\r
- /* Skip this WORD and get the next DWORD */\r
- len = *(DWORD*)(pAfterOTIBlks + 2);\r
-\r
- /* Now add this to pLibBLk look at what we're pointing at and\r
- possibly add 0x20, then add 0x216, sprinkle a bit a magic\r
- dust and we should be pointing at the beginning of the name\r
- table */\r
-\r
- pNameTable = (char*)pLibBlk + len;\r
-\r
- switch(*(WORD*)pNameTable) {\r
- case 0xffff:\r
- break;\r
- case 0x0200:\r
- pNameTable += 0x20;\r
- break;\r
- default:\r
- FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);\r
- break;\r
- }\r
-\r
- pNameTable += 0x216;\r
-\r
- pNameTable += 2;\r
-\r
- TRACE("Library name is %s\n", pNameTable + pLibBlk->name);\r
-\r
- pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);\r
-\r
-\r
- /* Hopefully we now have enough ptrs set up to actually read in\r
- some TypeInfos. It's not clear which order to do them in, so\r
- I'll just follow the links along the BlkEntry chain and read\r
- them in in the order in which they're in the file */\r
-\r
- ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);\r
-\r
- for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;\r
- pBlkEntry[order].next != 0;\r
- order = pBlkEntry[order].next - 1, i++) {\r
-\r
- SLTG_TypeInfoHeader *pTIHeader;\r
- SLTG_TypeInfoTail *pTITail;\r
-\r
- if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,\r
- pOtherTypeInfoBlks[i].index_name)) {\r
- FIXME("Index strings don't match\n");\r
- return NULL;\r
- }\r
-\r
- pTIHeader = pBlk;\r
- if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {\r
- FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);\r
- return NULL;\r
- }\r
- *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();\r
- (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;\r
- (*ppTypeInfoImpl)->index = i;\r
- (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(\r
- pOtherTypeInfoBlks[i].name_offs +\r
- pNameTable);\r
- (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;\r
- memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,\r
- sizeof(GUID));\r
- (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;\r
- (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;\r
- (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;\r
- (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =\r
- (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);\r
-\r
- if((pTIHeader->typeflags1 & 7) != 2)\r
- FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);\r
- if(pTIHeader->typeflags3 != 2)\r
- FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);\r
-\r
- TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",\r
- debugstr_w((*ppTypeInfoImpl)->Name),\r
- typekind_desc[pTIHeader->typekind],\r
- debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),\r
- (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);\r
-\r
- switch(pTIHeader->typekind) {\r
- case TKIND_ENUM:\r
- pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);\r
- break;\r
-\r
- case TKIND_RECORD:\r
- pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);\r
- break;\r
-\r
- case TKIND_INTERFACE:\r
- pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);\r
- break;\r
-\r
- case TKIND_COCLASS:\r
- pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);\r
- break;\r
-\r
- case TKIND_ALIAS:\r
- pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);\r
- if (pTITail->tdescalias_vt)\r
- (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;\r
- break;\r
-\r
- case TKIND_DISPATCH:\r
- pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);\r
- break;\r
-\r
- default:\r
- FIXME("Not processing typekind %d\n", pTIHeader->typekind);\r
- pTITail = NULL;\r
- break;\r
-\r
- }\r
-\r
- if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here\r
- but we've already set those */\r
- (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;\r
- (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;\r
- (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;\r
-\r
-#define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);\r
- X(06);\r
- X(08);\r
- X(0a);\r
- X(0c);\r
- X(0e);\r
- X(10);\r
- X(12);\r
- X(16);\r
- X(18);\r
- X(1a);\r
- X(1c);\r
- X(1e);\r
- X(24);\r
- X(26);\r
- X(2a);\r
- X(2c);\r
- X(2e);\r
- X(30);\r
- X(32);\r
- X(34);\r
- }\r
- ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);\r
- pBlk = (char*)pBlk + pBlkEntry[order].len;\r
- }\r
-\r
- if(i != pTypeLibImpl->TypeInfoCount) {\r
- FIXME("Somehow processed %d TypeInfos\n", i);\r
- return NULL;\r
- }\r
-\r
- HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);\r
- return (ITypeLib2*)pTypeLibImpl;\r
-}\r
-\r
-/* ITypeLib::QueryInterface\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnQueryInterface(\r
- ITypeLib2 * iface,\r
- REFIID riid,\r
- VOID **ppvObject)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
-\r
- TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));\r
-\r
- *ppvObject=NULL;\r
- if(IsEqualIID(riid, &IID_IUnknown) ||\r
- IsEqualIID(riid,&IID_ITypeLib)||\r
- IsEqualIID(riid,&IID_ITypeLib2))\r
- {\r
- *ppvObject = This;\r
- }\r
-\r
- if(*ppvObject)\r
- {\r
- ITypeLib2_AddRef(iface);\r
- TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);\r
- return S_OK;\r
- }\r
- TRACE("-- Interface: E_NOINTERFACE\n");\r
- return E_NOINTERFACE;\r
-}\r
-\r
-/* ITypeLib::AddRef\r
- */\r
-static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- ULONG ref = InterlockedIncrement(&This->ref);\r
-\r
- TRACE("(%p)->ref was %lu\n",This, ref - 1);\r
-\r
- return ref;\r
-}\r
-\r
-/* ITypeLib::Release\r
- */\r
-static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- ULONG ref = InterlockedDecrement(&This->ref);\r
-\r
- TRACE("(%p)->(%lu)\n",This, ref);\r
-\r
- if (!ref)\r
- {\r
- /* remove cache entry */\r
- TRACE("removing from cache list\n");\r
- EnterCriticalSection(&cache_section);\r
- if (This->next) This->next->prev = This->prev;\r
- if (This->prev) This->prev->next = This->next;\r
- else tlb_cache_first = This->next;\r
- LeaveCriticalSection(&cache_section);\r
-\r
- /* FIXME destroy child objects */\r
- TRACE(" destroying ITypeLib(%p)\n",This);\r
-\r
- if (This->Name)\r
- {\r
- SysFreeString(This->Name);\r
- This->Name = NULL;\r
- }\r
-\r
- if (This->DocString)\r
- {\r
- SysFreeString(This->DocString);\r
- This->DocString = NULL;\r
- }\r
-\r
- if (This->HelpFile)\r
- {\r
- SysFreeString(This->HelpFile);\r
- This->HelpFile = NULL;\r
- }\r
-\r
- if (This->HelpStringDll)\r
- {\r
- SysFreeString(This->HelpStringDll);\r
- This->HelpStringDll = NULL;\r
- }\r
-\r
- if (This->pTypeInfo) /* can be NULL */\r
- ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);\r
- HeapFree(GetProcessHeap(),0,This);\r
- return 0;\r
- }\r
-\r
- return ref;\r
-}\r
-\r
-/* ITypeLib::GetTypeInfoCount\r
- *\r
- * Returns the number of type descriptions in the type library\r
- */\r
-static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);\r
- return This->TypeInfoCount;\r
-}\r
-\r
-/* ITypeLib::GetTypeInfo\r
- *\r
- * retrieves the specified type description in the library.\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(\r
- ITypeLib2 *iface,\r
- UINT index,\r
- ITypeInfo **ppTInfo)\r
-{\r
- int i;\r
-\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- ITypeInfoImpl *pTypeInfo = This->pTypeInfo;\r
-\r
- TRACE("(%p)->(index=%d) \n", This, index);\r
-\r
- if (!ppTInfo) return E_INVALIDARG;\r
-\r
- /* search element n in list */\r
- for(i=0; i < index; i++)\r
- {\r
- pTypeInfo = pTypeInfo->next;\r
- if (!pTypeInfo)\r
- {\r
- TRACE("-- element not found\n");\r
- return TYPE_E_ELEMENTNOTFOUND;\r
- }\r
- }\r
-\r
- *ppTInfo = (ITypeInfo *) pTypeInfo;\r
-\r
- ITypeInfo_AddRef(*ppTInfo);\r
- TRACE("-- found (%p)\n",*ppTInfo);\r
- return S_OK;\r
-}\r
-\r
-\r
-/* ITypeLibs::GetTypeInfoType\r
- *\r
- * Retrieves the type of a type description.\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(\r
- ITypeLib2 *iface,\r
- UINT index,\r
- TYPEKIND *pTKind)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- int i;\r
- ITypeInfoImpl *pTInfo = This->pTypeInfo;\r
-\r
- TRACE("(%p) index %d \n",This, index);\r
-\r
- if(!pTKind) return E_INVALIDARG;\r
-\r
- /* search element n in list */\r
- for(i=0; i < index; i++)\r
- {\r
- if(!pTInfo)\r
- {\r
- TRACE("-- element not found\n");\r
- return TYPE_E_ELEMENTNOTFOUND;\r
- }\r
- pTInfo = pTInfo->next;\r
- }\r
-\r
- *pTKind = pTInfo->TypeAttr.typekind;\r
- TRACE("-- found Type (%d)\n", *pTKind);\r
- return S_OK;\r
-}\r
-\r
-/* ITypeLib::GetTypeInfoOfGuid\r
- *\r
- * Retrieves the type description that corresponds to the specified GUID.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(\r
- ITypeLib2 *iface,\r
- REFGUID guid,\r
- ITypeInfo **ppTInfo)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */\r
-\r
- TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));\r
-\r
- if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;\r
-\r
- /* search linked list for guid */\r
- while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )\r
- {\r
- pTypeInfo = pTypeInfo->next;\r
-\r
- if (!pTypeInfo)\r
- {\r
- /* end of list reached */\r
- TRACE("-- element not found\n");\r
- return TYPE_E_ELEMENTNOTFOUND;\r
- }\r
- }\r
-\r
- TRACE("-- found (%p, %s)\n",\r
- pTypeInfo,\r
- debugstr_w(pTypeInfo->Name));\r
-\r
- *ppTInfo = (ITypeInfo*)pTypeInfo;\r
- ITypeInfo_AddRef(*ppTInfo);\r
- return S_OK;\r
-}\r
-\r
-/* ITypeLib::GetLibAttr\r
- *\r
- * Retrieves the structure that contains the library's attributes.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetLibAttr(\r
- ITypeLib2 *iface,\r
- LPTLIBATTR *ppTLibAttr)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- TRACE("(%p)\n",This);\r
- *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));\r
- memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));\r
- return S_OK;\r
-}\r
-\r
-/* ITypeLib::GetTypeComp\r
- *\r
- * Enables a client compiler to bind to a library's types, variables,\r
- * constants, and global functions.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetTypeComp(\r
- ITypeLib2 *iface,\r
- ITypeComp **ppTComp)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
-\r
- TRACE("(%p)->(%p)\n",This,ppTComp);\r
- *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;\r
- ITypeComp_AddRef(*ppTComp);\r
-\r
- return S_OK;\r
-}\r
-\r
-/* ITypeLib::GetDocumentation\r
- *\r
- * Retrieves the library's documentation string, the complete Help file name\r
- * and path, and the context identifier for the library Help topic in the Help\r
- * file.\r
- *\r
- * On a successful return all non-null BSTR pointers will have been set,\r
- * possibly to NULL.\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetDocumentation(\r
- ITypeLib2 *iface,\r
- INT index,\r
- BSTR *pBstrName,\r
- BSTR *pBstrDocString,\r
- DWORD *pdwHelpContext,\r
- BSTR *pBstrHelpFile)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
-\r
- HRESULT result = E_INVALIDARG;\r
-\r
- ITypeInfo *pTInfo;\r
-\r
-\r
- TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",\r
- This, index,\r
- pBstrName, pBstrDocString,\r
- pdwHelpContext, pBstrHelpFile);\r
-\r
- if(index<0)\r
- {\r
- /* documentation for the typelib */\r
- if(pBstrName)\r
- {\r
- if (This->Name)\r
- if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;\r
- else\r
- *pBstrName = NULL;\r
- }\r
- if(pBstrDocString)\r
- {\r
- if (This->DocString)\r
- if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;\r
- else if (This->Name)\r
- if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;\r
- else\r
- *pBstrDocString = NULL;\r
- }\r
- if(pdwHelpContext)\r
- {\r
- *pdwHelpContext = This->dwHelpContext;\r
- }\r
- if(pBstrHelpFile)\r
- {\r
- if (This->HelpFile)\r
- if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;\r
- else\r
- *pBstrHelpFile = NULL;\r
- }\r
-\r
- result = S_OK;\r
- }\r
- else\r
- {\r
- /* for a typeinfo */\r
- result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);\r
-\r
- if(SUCCEEDED(result))\r
- {\r
- result = ITypeInfo_GetDocumentation(pTInfo,\r
- MEMBERID_NIL,\r
- pBstrName,\r
- pBstrDocString,\r
- pdwHelpContext, pBstrHelpFile);\r
-\r
- ITypeInfo_Release(pTInfo);\r
- }\r
- }\r
- return result;\r
-memerr3:\r
- if (pBstrDocString) SysFreeString (*pBstrDocString);\r
-memerr2:\r
- if (pBstrName) SysFreeString (*pBstrName);\r
-memerr1:\r
- return STG_E_INSUFFICIENTMEMORY;\r
-}\r
-\r
-/* ITypeLib::IsName\r
- *\r
- * Indicates whether a passed-in string contains the name of a type or member\r
- * described in the library.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnIsName(\r
- ITypeLib2 *iface,\r
- LPOLESTR szNameBuf,\r
- ULONG lHashVal,\r
- BOOL *pfName)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- ITypeInfoImpl *pTInfo;\r
- TLBFuncDesc *pFInfo;\r
- TLBVarDesc *pVInfo;\r
- int i;\r
- UINT nNameBufLen = SysStringLen(szNameBuf);\r
-\r
- TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,\r
- pfName);\r
-\r
- *pfName=TRUE;\r
- for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){\r
- if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;\r
- for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {\r
- if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;\r
- for(i=0;i<pFInfo->funcdesc.cParams;i++)\r
- if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))\r
- goto ITypeLib2_fnIsName_exit;\r
- }\r
- for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)\r
- if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;\r
-\r
- }\r
- *pfName=FALSE;\r
-\r
-ITypeLib2_fnIsName_exit:\r
- TRACE("(%p)slow! search for %s: %s found!\n", This,\r
- debugstr_w(szNameBuf), *pfName?"NOT":"");\r
-\r
- return S_OK;\r
-}\r
-\r
-/* ITypeLib::FindName\r
- *\r
- * Finds occurrences of a type description in a type library. This may be used\r
- * to quickly verify that a name exists in a type library.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnFindName(\r
- ITypeLib2 *iface,\r
- LPOLESTR szNameBuf,\r
- ULONG lHashVal,\r
- ITypeInfo **ppTInfo,\r
- MEMBERID *rgMemId,\r
- UINT16 *pcFound)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- ITypeInfoImpl *pTInfo;\r
- TLBFuncDesc *pFInfo;\r
- TLBVarDesc *pVInfo;\r
- int i,j = 0;\r
-\r
- UINT nNameBufLen = SysStringLen(szNameBuf);\r
-\r
- for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){\r
- if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;\r
- for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {\r
- if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;\r
- for(i=0;i<pFInfo->funcdesc.cParams;i++)\r
- if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))\r
- goto ITypeLib2_fnFindName_exit;\r
- }\r
- for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)\r
- if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;\r
- continue;\r
-ITypeLib2_fnFindName_exit:\r
- ITypeInfo_AddRef((ITypeInfo*)pTInfo);\r
- ppTInfo[j]=(LPTYPEINFO)pTInfo;\r
- j++;\r
- }\r
- TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",\r
- This, *pcFound, debugstr_w(szNameBuf), j);\r
-\r
- *pcFound=j;\r
-\r
- return S_OK;\r
-}\r
-\r
-/* ITypeLib::ReleaseTLibAttr\r
- *\r
- * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.\r
- *\r
- */\r
-static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(\r
- ITypeLib2 *iface,\r
- TLIBATTR *pTLibAttr)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- TRACE("freeing (%p)\n",This);\r
- HeapFree(GetProcessHeap(),0,pTLibAttr);\r
-\r
-}\r
-\r
-/* ITypeLib2::GetCustData\r
- *\r
- * gets the custom data\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetCustData(\r
- ITypeLib2 * iface,\r
- REFGUID guid,\r
- VARIANT *pVarVal)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- TLBCustData *pCData;\r
-\r
- for(pCData=This->pCustData; pCData; pCData = pCData->next)\r
- {\r
- if( IsEqualIID(guid, &pCData->guid)) break;\r
- }\r
-\r
- TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");\r
-\r
- if(pCData)\r
- {\r
- VariantInit( pVarVal);\r
- VariantCopy( pVarVal, &pCData->data);\r
- return S_OK;\r
- }\r
- return E_INVALIDARG; /* FIXME: correct? */\r
-}\r
-\r
-/* ITypeLib2::GetLibStatistics\r
- *\r
- * Returns statistics about a type library that are required for efficient\r
- * sizing of hash tables.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(\r
- ITypeLib2 * iface,\r
- ULONG *pcUniqueNames,\r
- ULONG *pcchUniqueNames)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
-\r
- FIXME("(%p): stub!\n", This);\r
-\r
- if(pcUniqueNames) *pcUniqueNames=1;\r
- if(pcchUniqueNames) *pcchUniqueNames=1;\r
- return S_OK;\r
-}\r
-\r
-/* ITypeLib2::GetDocumentation2\r
- *\r
- * Retrieves the library's documentation string, the complete Help file name\r
- * and path, the localization context to use, and the context ID for the\r
- * library Help topic in the Help file.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(\r
- ITypeLib2 * iface,\r
- INT index,\r
- LCID lcid,\r
- BSTR *pbstrHelpString,\r
- DWORD *pdwHelpStringContext,\r
- BSTR *pbstrHelpStringDll)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- HRESULT result;\r
- ITypeInfo *pTInfo;\r
-\r
- FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);\r
-\r
- /* the help string should be obtained from the helpstringdll,\r
- * using the _DLLGetDocumentation function, based on the supplied\r
- * lcid. Nice to do sometime...\r
- */\r
- if(index<0)\r
- {\r
- /* documentation for the typelib */\r
- if(pbstrHelpString)\r
- *pbstrHelpString=SysAllocString(This->DocString);\r
- if(pdwHelpStringContext)\r
- *pdwHelpStringContext=This->dwHelpContext;\r
- if(pbstrHelpStringDll)\r
- *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);\r
-\r
- result = S_OK;\r
- }\r
- else\r
- {\r
- /* for a typeinfo */\r
- result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);\r
-\r
- if(SUCCEEDED(result))\r
- {\r
- ITypeInfo2 * pTInfo2;\r
- result = ITypeInfo_QueryInterface(pTInfo,\r
- &IID_ITypeInfo2,\r
- (LPVOID*) &pTInfo2);\r
-\r
- if(SUCCEEDED(result))\r
- {\r
- result = ITypeInfo2_GetDocumentation2(pTInfo2,\r
- MEMBERID_NIL,\r
- lcid,\r
- pbstrHelpString,\r
- pdwHelpStringContext,\r
- pbstrHelpStringDll);\r
-\r
- ITypeInfo2_Release(pTInfo2);\r
- }\r
-\r
- ITypeInfo_Release(pTInfo);\r
- }\r
- }\r
- return result;\r
-}\r
-\r
-/* ITypeLib2::GetAllCustData\r
- *\r
- * Gets all custom data items for the library.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeLib2_fnGetAllCustData(\r
- ITypeLib2 * iface,\r
- CUSTDATA *pCustData)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
- TLBCustData *pCData;\r
- int i;\r
- TRACE("(%p) returning %d items\n", This, This->ctCustData);\r
- pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));\r
- if(pCustData->prgCustData ){\r
- pCustData->cCustData=This->ctCustData;\r
- for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){\r
- pCustData->prgCustData[i].guid=pCData->guid;\r
- VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);\r
- }\r
- }else{\r
- ERR(" OUT OF MEMORY! \n");\r
- return E_OUTOFMEMORY;\r
- }\r
- return S_OK;\r
-}\r
-\r
-static ITypeLib2Vtbl tlbvt = {\r
- ITypeLib2_fnQueryInterface,\r
- ITypeLib2_fnAddRef,\r
- ITypeLib2_fnRelease,\r
- ITypeLib2_fnGetTypeInfoCount,\r
- ITypeLib2_fnGetTypeInfo,\r
- ITypeLib2_fnGetTypeInfoType,\r
- ITypeLib2_fnGetTypeInfoOfGuid,\r
- ITypeLib2_fnGetLibAttr,\r
- ITypeLib2_fnGetTypeComp,\r
- ITypeLib2_fnGetDocumentation,\r
- ITypeLib2_fnIsName,\r
- ITypeLib2_fnFindName,\r
- ITypeLib2_fnReleaseTLibAttr,\r
-\r
- ITypeLib2_fnGetCustData,\r
- ITypeLib2_fnGetLibStatistics,\r
- ITypeLib2_fnGetDocumentation2,\r
- ITypeLib2_fnGetAllCustData\r
- };\r
-\r
-\r
-static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)\r
-{\r
- ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);\r
-\r
- return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);\r
-}\r
-\r
-static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)\r
-{\r
- ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);\r
-\r
- return ITypeInfo_AddRef((ITypeInfo *)This);\r
-}\r
-\r
-static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)\r
-{\r
- ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);\r
-\r
- return ITypeInfo_Release((ITypeInfo *)This);\r
-}\r
-\r
-static HRESULT WINAPI ITypeLibComp_fnBind(\r
- ITypeComp * iface,\r
- OLECHAR * szName,\r
- ULONG lHash,\r
- WORD wFlags,\r
- ITypeInfo ** ppTInfo,\r
- DESCKIND * pDescKind,\r
- BINDPTR * pBindPtr)\r
-{\r
- FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);\r
- return E_NOTIMPL;\r
-}\r
-\r
-static HRESULT WINAPI ITypeLibComp_fnBindType(\r
- ITypeComp * iface,\r
- OLECHAR * szName,\r
- ULONG lHash,\r
- ITypeInfo ** ppTInfo,\r
- ITypeComp ** ppTComp)\r
-{\r
- FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);\r
- return E_NOTIMPL;\r
-}\r
-\r
-static ITypeCompVtbl tlbtcvt =\r
-{\r
-\r
- ITypeLibComp_fnQueryInterface,\r
- ITypeLibComp_fnAddRef,\r
- ITypeLibComp_fnRelease,\r
-\r
- ITypeLibComp_fnBind,\r
- ITypeLibComp_fnBindType\r
-};\r
-\r
-/*================== ITypeInfo(2) Methods ===================================*/\r
-static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)\r
-{\r
- ITypeInfoImpl * pTypeInfoImpl;\r
-\r
- pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));\r
- if (pTypeInfoImpl)\r
- {\r
- pTypeInfoImpl->lpVtbl = &tinfvt;\r
- pTypeInfoImpl->lpVtblTypeComp = &tcompvt;\r
- pTypeInfoImpl->ref=1;\r
- }\r
- TRACE("(%p)\n", pTypeInfoImpl);\r
- return (ITypeInfo2*) pTypeInfoImpl;\r
-}\r
-\r
-/* ITypeInfo::QueryInterface\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnQueryInterface(\r
- ITypeInfo2 *iface,\r
- REFIID riid,\r
- VOID **ppvObject)\r
-{\r
- ITypeLibImpl *This = (ITypeLibImpl *)iface;\r
-\r
- TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));\r
-\r
- *ppvObject=NULL;\r
- if(IsEqualIID(riid, &IID_IUnknown) ||\r
- IsEqualIID(riid,&IID_ITypeInfo)||\r
- IsEqualIID(riid,&IID_ITypeInfo2))\r
- *ppvObject = This;\r
-\r
- if(*ppvObject){\r
- ITypeInfo_AddRef(iface);\r
- TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);\r
- return S_OK;\r
- }\r
- TRACE("-- Interface: E_NOINTERFACE\n");\r
- return E_NOINTERFACE;\r
-}\r
-\r
-/* ITypeInfo::AddRef\r
- */\r
-static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- ULONG ref = InterlockedIncrement(&This->ref);\r
-\r
- ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);\r
-\r
- TRACE("(%p)->ref is %lu\n",This, ref);\r
- return ref;\r
-}\r
-\r
-/* ITypeInfo::Release\r
- */\r
-static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- ULONG ref = InterlockedDecrement(&This->ref);\r
-\r
- TRACE("(%p)->(%lu)\n",This, ref);\r
-\r
- if (ref) {\r
- /* We don't release ITypeLib when ref=0 because\r
- it means that function is called by ITypeLib2_Release */\r
- ITypeLib2_Release((ITypeLib2*)This->pTypeLib);\r
- } else {\r
- FIXME("destroy child objects\n");\r
-\r
- TRACE("destroying ITypeInfo(%p)\n",This);\r
- if (This->Name)\r
- {\r
- SysFreeString(This->Name);\r
- This->Name = 0;\r
- }\r
-\r
- if (This->DocString)\r
- {\r
- SysFreeString(This->DocString);\r
- This->DocString = 0;\r
- }\r
-\r
- if (This->next)\r
- {\r
- ITypeInfo_Release((ITypeInfo*)This->next);\r
- }\r
-\r
- HeapFree(GetProcessHeap(),0,This);\r
- return 0;\r
- }\r
- return ref;\r
-}\r
-\r
-/* ITypeInfo::GetTypeAttr\r
- *\r
- * Retrieves a TYPEATTR structure that contains the attributes of the type\r
- * description.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,\r
- LPTYPEATTR *ppTypeAttr)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TRACE("(%p)\n",This);\r
- *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));\r
- memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));\r
-\r
- if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */\r
- copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);\r
-\r
- if((*ppTypeAttr)->typekind == TKIND_DISPATCH && (*ppTypeAttr)->wTypeFlags & TYPEFLAG_FDUAL) {\r
- (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited\r
- funcs */\r
- (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */\r
- (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;\r
- }\r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo::GetTypeComp\r
- *\r
- * Retrieves the ITypeComp interface for the type description, which enables a\r
- * client compiler to bind to the type description's members.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,\r
- ITypeComp * *ppTComp)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
-\r
- TRACE("(%p)->(%p) stub!\n", This, ppTComp);\r
-\r
- *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;\r
- ITypeComp_AddRef(*ppTComp);\r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo::GetFuncDesc\r
- *\r
- * Retrieves the FUNCDESC structure that contains information about a\r
- * specified function.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,\r
- LPFUNCDESC *ppFuncDesc)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- int i;\r
- TLBFuncDesc * pFDesc;\r
- TRACE("(%p) index %d\n", This, index);\r
- for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)\r
- ;\r
- if(pFDesc){\r
- /* FIXME: must do a copy here */\r
- *ppFuncDesc=&pFDesc->funcdesc;\r
- return S_OK;\r
- }\r
- return E_INVALIDARG;\r
-}\r
-\r
-/* ITypeInfo::GetVarDesc\r
- *\r
- * Retrieves a VARDESC structure that describes the specified variable.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,\r
- LPVARDESC *ppVarDesc)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- int i;\r
- TLBVarDesc * pVDesc;\r
- TRACE("(%p) index %d\n", This, index);\r
- for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)\r
- ;\r
- if(pVDesc){\r
- /* FIXME: must do a copy here */\r
- *ppVarDesc=&pVDesc->vardesc;\r
- return S_OK;\r
- }\r
- return E_INVALIDARG;\r
-}\r
-\r
-/* ITypeInfo_GetNames\r
- *\r
- * Retrieves the variable with the specified member ID (or the name of the\r
- * property or method and its parameters) that correspond to the specified\r
- * function ID.\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,\r
- BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBFuncDesc * pFDesc;\r
- TLBVarDesc * pVDesc;\r
- int i;\r
- TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);\r
- for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);\r
- if(pFDesc)\r
- {\r
- /* function found, now return function and parameter names */\r
- for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)\r
- {\r
- if(!i)\r
- *rgBstrNames=SysAllocString(pFDesc->Name);\r
- else\r
- rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);\r
- }\r
- *pcNames=i;\r
- }\r
- else\r
- {\r
- for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);\r
- if(pVDesc)\r
- {\r
- *rgBstrNames=SysAllocString(pVDesc->Name);\r
- *pcNames=1;\r
- }\r
- else\r
- {\r
- if(This->TypeAttr.cImplTypes &&\r
- (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {\r
- /* recursive search */\r
- ITypeInfo *pTInfo;\r
- HRESULT result;\r
- result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,\r
- &pTInfo);\r
- if(SUCCEEDED(result))\r
- {\r
- result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);\r
- ITypeInfo_Release(pTInfo);\r
- return result;\r
- }\r
- WARN("Could not search inherited interface!\n");\r
- }\r
- else\r
- {\r
- WARN("no names found\n");\r
- }\r
- *pcNames=0;\r
- return TYPE_E_ELEMENTNOTFOUND;\r
- }\r
- }\r
- return S_OK;\r
-}\r
-\r
-\r
-/* ITypeInfo::GetRefTypeOfImplType\r
- *\r
- * If a type description describes a COM class, it retrieves the type\r
- * description of the implemented interface types. For an interface,\r
- * GetRefTypeOfImplType returns the type information for inherited interfaces,\r
- * if any exist.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(\r
- ITypeInfo2 *iface,\r
- UINT index,\r
- HREFTYPE *pRefType)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- int(i);\r
- TLBImplType *pImpl = This->impltypelist;\r
-\r
- TRACE("(%p) index %d\n", This, index);\r
- if (TRACE_ON(ole)) dump_TypeInfo(This);\r
-\r
- if(index==(UINT)-1)\r
- {\r
- /* only valid on dual interfaces;\r
- retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH\r
- */\r
- if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;\r
-\r
- if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&\r
- This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )\r
- {\r
- *pRefType = -1;\r
- }\r
- else\r
- {\r
- if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;\r
- *pRefType = pImpl->hRef;\r
- }\r
- }\r
- else\r
- {\r
- /* get element n from linked list */\r
- for(i=0; pImpl && i<index; i++)\r
- {\r
- pImpl = pImpl->next;\r
- }\r
-\r
- if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;\r
-\r
- *pRefType = pImpl->hRef;\r
-\r
- TRACE("-- 0x%08lx\n", pImpl->hRef );\r
- }\r
-\r
- return S_OK;\r
-\r
-}\r
-\r
-/* ITypeInfo::GetImplTypeFlags\r
- *\r
- * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface\r
- * or base interface in a type description.\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,\r
- UINT index, INT *pImplTypeFlags)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- int i;\r
- TLBImplType *pImpl;\r
-\r
- TRACE("(%p) index %d\n", This, index);\r
- for(i=0, pImpl=This->impltypelist; i<index && pImpl;\r
- i++, pImpl=pImpl->next)\r
- ;\r
- if(i==index && pImpl){\r
- *pImplTypeFlags=pImpl->implflags;\r
- return S_OK;\r
- }\r
- *pImplTypeFlags=0;\r
- return TYPE_E_ELEMENTNOTFOUND;\r
-}\r
-\r
-/* GetIDsOfNames\r
- * Maps between member names and member IDs, and parameter names and\r
- * parameter IDs.\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,\r
- LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBFuncDesc * pFDesc;\r
- TLBVarDesc * pVDesc;\r
- HRESULT ret=S_OK;\r
-\r
- TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),\r
- cNames);\r
- for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {\r
- int i, j;\r
- if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {\r
- if(cNames) *pMemId=pFDesc->funcdesc.memid;\r
- for(i=1; i < cNames; i++){\r
- for(j=0; j<pFDesc->funcdesc.cParams; j++)\r
- if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))\r
- break;\r
- if( j<pFDesc->funcdesc.cParams)\r
- pMemId[i]=j;\r
- else\r
- ret=DISP_E_UNKNOWNNAME;\r
- };\r
- return ret;\r
- }\r
- }\r
- for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {\r
- if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {\r
- if(cNames) *pMemId=pVDesc->vardesc.memid;\r
- return ret;\r
- }\r
- }\r
- /* not found, see if this is and interface with an inheritance */\r
- if(This->TypeAttr.cImplTypes &&\r
- (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {\r
- /* recursive search */\r
- ITypeInfo *pTInfo;\r
- ret=ITypeInfo_GetRefTypeInfo(iface,\r
- This->impltypelist->hRef, &pTInfo);\r
- if(SUCCEEDED(ret)){\r
- ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );\r
- ITypeInfo_Release(pTInfo);\r
- return ret;\r
- }\r
- WARN("Could not search inherited interface!\n");\r
- } else\r
- WARN("no names found\n");\r
- return DISP_E_UNKNOWNNAME;\r
-}\r
-\r
-/* ITypeInfo::Invoke\r
- *\r
- * Invokes a method, or accesses a property of an object, that implements the\r
- * interface described by the type description.\r
- */\r
-DWORD\r
-_invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {\r
- DWORD res;\r
-\r
- if (TRACE_ON(ole)) {\r
- int i;\r
- TRACE("Calling %p(",func);\r
- for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);\r
- TRACE(")\n");\r
- }\r
-\r
- switch (callconv) {\r
- case CC_STDCALL:\r
-\r
- switch (nrargs) {\r
- case 0:\r
- res = func();\r
- break;\r
- case 1:\r
- res = func(args[0]);\r
- break;\r
- case 2:\r
- res = func(args[0],args[1]);\r
- break;\r
- case 3:\r
- res = func(args[0],args[1],args[2]);\r
- break;\r
- case 4:\r
- res = func(args[0],args[1],args[2],args[3]);\r
- break;\r
- case 5:\r
- res = func(args[0],args[1],args[2],args[3],args[4]);\r
- break;\r
- case 6:\r
- res = func(args[0],args[1],args[2],args[3],args[4],args[5]);\r
- break;\r
- case 7:\r
- res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);\r
- break;\r
- case 8:\r
- res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);\r
- break;\r
- case 9:\r
- res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);\r
- break;\r
- case 10:\r
- res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);\r
- break;\r
- case 11:\r
- res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);\r
- break;\r
- default:\r
- FIXME("unsupported number of arguments %d in stdcall\n",nrargs);\r
- res = -1;\r
- break;\r
- }\r
- break;\r
- default:\r
- FIXME("unsupported calling convention %d\n",callconv);\r
- res = -1;\r
- break;\r
- }\r
- TRACE("returns %08lx\n",res);\r
- return res;\r
-}\r
-\r
-extern int _argsize(DWORD vt);\r
-\r
-/****************************************************************************\r
- * Helper functions for Dispcall / Invoke, which copies one variant\r
- * with target type onto the argument stack.\r
- */\r
-static HRESULT\r
-_copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,\r
- DWORD *argpos, VARIANT *arg, VARTYPE vt\r
-) {\r
- UINT arglen = _argsize(vt)*sizeof(DWORD);\r
- VARIANT va;\r
-\r
- if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {\r
- memcpy(argpos,&arg,sizeof(void*));\r
- return S_OK;\r
- }\r
-\r
- if (V_VT(arg) == vt) {\r
- memcpy(argpos, &V_I4(arg), arglen);\r
- return S_OK;\r
- }\r
-\r
- if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {\r
- memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));\r
- return S_OK;\r
- }\r
-\r
- if (vt == VT_VARIANT) {\r
- memcpy(argpos, arg, arglen);\r
- return S_OK;\r
- }\r
- /* Deref BYREF vars if there is need */\r
- if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {\r
- memcpy(argpos,(void*)V_I4(arg), arglen);\r
- return S_OK;\r
- }\r
- if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {\r
- /* in this context, if the type lib specifies IUnknown*, giving an\r
- IDispatch* is correct; so, don't invoke VariantChangeType */\r
- memcpy(argpos,&V_I4(arg), arglen);\r
- return S_OK;\r
- }\r
- if ((vt == VT_PTR) && tdesc)\r
- return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);\r
-\r
- if ((vt == VT_USERDEFINED) && tdesc && tinfo) {\r
- ITypeInfo *tinfo2 = NULL;\r
- TYPEATTR *tattr = NULL;\r
- HRESULT hres;\r
-\r
- hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);\r
- if (hres) {\r
- FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "\r
- "while coercing from vt 0x%x. Copying 4 byte.\n",\r
- tdesc->u.hreftype,V_VT(arg));\r
- memcpy(argpos, &V_I4(arg), 4);\r
- return S_OK;\r
- }\r
- hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);\r
- if( hres )\r
- {\r
- ERR("GetTypeAttr failed\n");\r
- ITypeInfo_Release(tinfo2);\r
- return hres;\r
- }\r
- switch (tattr->typekind) {\r
- case TKIND_ENUM:\r
- switch ( V_VT( arg ) ) {\r
- case VT_I2:\r
- *argpos = V_I2(arg);\r
- hres = S_OK;\r
- break;\r
- case VT_I4:\r
- memcpy(argpos, &V_I4(arg), 4);\r
- hres = S_OK;\r
- break;\r
- default:\r
- FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));\r
- hres = E_FAIL;\r
- break;\r
- }\r
- break;\r
-\r
- case TKIND_ALIAS:\r
- tdesc = &(tattr->tdescAlias);\r
- hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);\r
- break;\r
-\r
- case TKIND_INTERFACE:\r
- if (V_VT(arg) == VT_DISPATCH) {\r
- IDispatch *disp;\r
- if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {\r
- memcpy(argpos, &V_DISPATCH(arg), 4);\r
- hres = S_OK;\r
- break;\r
- }\r
- hres=IUnknown_QueryInterface(V_DISPATCH(arg),\r
- &IID_IDispatch,(LPVOID*)&disp);\r
- if (SUCCEEDED(hres)) {\r
- memcpy(argpos,&disp,4);\r
- IUnknown_Release(V_DISPATCH(arg));\r
- hres = S_OK;\r
- break;\r
- }\r
- FIXME("Failed to query IDispatch interface from %s while "\r
- "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));\r
- hres = E_FAIL;\r
- break;\r
- }\r
- if (V_VT(arg) == VT_UNKNOWN) {\r
- memcpy(argpos, &V_UNKNOWN(arg), 4);\r
- hres = S_OK;\r
- break;\r
- }\r
- FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",\r
- V_VT(arg),debugstr_guid(&(tattr->guid)));\r
- hres = E_FAIL;\r
- break;\r
-\r
- case TKIND_DISPATCH:\r
- if (V_VT(arg) == VT_DISPATCH) {\r
- memcpy(argpos, &V_DISPATCH(arg), 4);\r
- hres = S_OK;\r
- }\r
- else {\r
- hres = E_FAIL;\r
- FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));\r
- }\r
- break;\r
- case TKIND_RECORD:\r
- FIXME("TKIND_RECORD unhandled.\n");\r
- hres = E_FAIL;\r
- break;\r
- default:\r
- FIXME("TKIND %d unhandled.\n",tattr->typekind);\r
- hres = E_FAIL;\r
- break;\r
- }\r
- ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);\r
- ITypeInfo_Release(tinfo2);\r
- return hres;\r
- }\r
-\r
- VariantInit(&va);\r
- if (VariantChangeType(&va,arg,0,vt)==S_OK) {\r
- memcpy(argpos,&V_I4(&va), arglen);\r
- FIXME("Should not use VariantChangeType here."\r
- " (conversion from 0x%x -> 0x%x) %08lx\n",\r
- V_VT(arg), vt, *argpos\r
- );\r
- return S_OK;\r
- }\r
- ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);\r
- return E_FAIL;\r
-}\r
-\r
-/***********************************************************************\r
- * DispCallFunc (OLEAUT32.@)\r
- */\r
-HRESULT WINAPI\r
-DispCallFunc(\r
- void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,\r
- VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult\r
-) {\r
- int i, argsize, argspos;\r
- DWORD *args;\r
- HRESULT hres;\r
-\r
- TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",\r
- pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)\r
- );\r
- /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.\r
- So we need to add a first parameter to the list of arguments, to supply the interface pointer */\r
- argsize = 1;\r
- for (i=0;i<cActuals;i++) {\r
- TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));\r
- dump_Variant(prgpvarg[i]);\r
- argsize += _argsize(prgvt[i]);\r
- }\r
- args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);\r
- args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */\r
- argspos = 1;\r
- for (i=0;i<cActuals;i++) {\r
- VARIANT *arg = prgpvarg[i];\r
- TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);\r
- _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);\r
- argspos += _argsize(prgvt[i]);\r
- }\r
-\r
- if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)\r
- {\r
- _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);\r
- hres=S_OK;\r
- }\r
- else\r
- {\r
- FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);\r
- hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);\r
- FIXME("Method returned %lx\n",hres);\r
- }\r
- HeapFree(GetProcessHeap(),0,args);\r
- return hres;\r
-}\r
-\r
-static HRESULT WINAPI ITypeInfo_fnInvoke(\r
- ITypeInfo2 *iface,\r
- VOID *pIUnk,\r
- MEMBERID memid,\r
- UINT16 dwFlags,\r
- DISPPARAMS *pDispParams,\r
- VARIANT *pVarResult,\r
- EXCEPINFO *pExcepInfo,\r
- UINT *pArgErr)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- int i;\r
- unsigned int func_index, var_index;\r
- TYPEKIND type_kind;\r
- HRESULT hres;\r
-\r
- TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",\r
- This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr\r
- );\r
- dump_DispParms(pDispParams);\r
-\r
- hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);\r
- if (SUCCEEDED(hres)) {\r
- FUNCDESC *func_desc;\r
-\r
- hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);\r
- if(FAILED(hres)) return hres;\r
- \r
- switch (func_desc->funckind) {\r
- case FUNC_PUREVIRTUAL:\r
- case FUNC_VIRTUAL: {\r
- DWORD res;\r
- int numargs, numargs2, argspos, args2pos;\r
- DWORD *args , *args2;\r
- VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);\r
- memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);\r
-\r
- hres = S_OK;\r
- numargs = 1; numargs2 = 0;\r
- for (i = 0; i < func_desc->cParams; i++) {\r
- if (i<pDispParams->cArgs)\r
- numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);\r
- else {\r
- numargs += 1; /* sizeof(lpvoid) */\r
- numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);\r
- }\r
- }\r
-\r
- args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);\r
- args2 = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);\r
-\r
- args[0] = (DWORD)pIUnk;\r
- argspos = 1; args2pos = 0;\r
- for (i = 0; i < func_desc->cParams; i++) {\r
- int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);\r
- if (i<pDispParams->cArgs) {\r
- VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];\r
- TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;\r
- USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;\r
- if (paramFlags & PARAMFLAG_FOPT) {\r
- if(i < func_desc->cParams - func_desc->cParamsOpt)\r
- ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");\r
- if(V_VT(arg) == VT_EMPTY\r
- || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {\r
- /* FIXME: Documentation says that we do this when parameter is left unspecified.\r
- How to determine it? */\r
-\r
- if(paramFlags & PARAMFLAG_FHASDEFAULT)\r
- FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");\r
- V_VT(arg) = VT_ERROR;\r
- V_ERROR(arg) = DISP_E_PARAMNOTFOUND;\r
- arglen = _argsize(VT_ERROR);\r
- }\r
- }\r
- hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);\r
- if (FAILED(hres)) goto func_fail;\r
- argspos += arglen;\r
- } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {\r
- VARIANT *arg = &rgvarg[i];\r
- TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;\r
- if(i < func_desc->cParams - func_desc->cParamsOpt)\r
- ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");\r
- if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)\r
- FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");\r
- V_VT(arg) = VT_ERROR;\r
- V_ERROR(arg) = DISP_E_PARAMNOTFOUND;\r
- arglen = _argsize(VT_ERROR);\r
- hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);\r
- if (FAILED(hres)) goto func_fail;\r
- argspos += arglen;\r
- } else {\r
- TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);\r
- if (tdesc->vt != VT_PTR)\r
- FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);\r
- /*FIXME: give pointers for the rest, so propertyget works*/\r
- args[argspos] = (DWORD)&args2[args2pos];\r
-\r
- /* If pointer to variant, pass reference it. */\r
- if ((tdesc->vt == VT_PTR) &&\r
- (tdesc->u.lptdesc->vt == VT_VARIANT) &&\r
- pVarResult\r
- )\r
- args[argspos]= (DWORD)pVarResult;\r
- argspos += 1;\r
- args2pos += arglen;\r
- }\r
- }\r
- if (func_desc->cParamsOpt < 0)\r
- FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);\r
-\r
- res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],\r
- func_desc->callconv,\r
- numargs,\r
- args\r
- );\r
-\r
- if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {\r
- args2pos = 0;\r
- for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {\r
- int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);\r
- TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);\r
- TYPEDESC i4_tdesc;\r
- i4_tdesc.vt = VT_I4;\r
-\r
- /* If we are a pointer to a variant, we are done already */\r
- if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))\r
- continue;\r
-\r
- VariantInit(pVarResult);\r
- memcpy(&V_INT(pVarResult),&args2[args2pos],arglen*sizeof(DWORD));\r
-\r
- if (tdesc->vt == VT_PTR)\r
- tdesc = tdesc->u.lptdesc;\r
- if (tdesc->vt == VT_USERDEFINED) {\r
- ITypeInfo *tinfo2;\r
- TYPEATTR *tattr;\r
-\r
- hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);\r
- if (FAILED(hres)) {\r
- FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);\r
- goto func_fail;\r
- }\r
- ITypeInfo_GetTypeAttr(tinfo2,&tattr);\r
- switch (tattr->typekind) {\r
- case TKIND_ENUM:\r
- /* force the return type to be VT_I4 */\r
- tdesc = &i4_tdesc;\r
- break;\r
- case TKIND_ALIAS:\r
- TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);\r
- tdesc = &(tattr->tdescAlias);\r
- break;\r
-\r
- case TKIND_INTERFACE:\r
- FIXME("TKIND_INTERFACE unhandled.\n");\r
- break;\r
- case TKIND_DISPATCH:\r
- FIXME("TKIND_DISPATCH unhandled.\n");\r
- break;\r
- case TKIND_RECORD:\r
- FIXME("TKIND_RECORD unhandled.\n");\r
- break;\r
- default:\r
- FIXME("TKIND %d unhandled.\n",tattr->typekind);\r
- break;\r
- }\r
- ITypeInfo_Release(tinfo2);\r
- }\r
- V_VT(pVarResult) = tdesc->vt;\r
-\r
- /* HACK: VB5 likes this.\r
- * I do not know why. There is 1 example in MSDN which uses\r
- * this which appears broken (mixes int vals and\r
- * IDispatch*.).\r
- */\r
- if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))\r
- V_VT(pVarResult) = VT_DISPATCH;\r
- TRACE("storing into variant:\n");\r
- dump_Variant(pVarResult);\r
- args2pos += arglen;\r
- }\r
- }\r
-func_fail:\r
- HeapFree(GetProcessHeap(), 0, rgvarg);\r
- HeapFree(GetProcessHeap(),0,args2);\r
- HeapFree(GetProcessHeap(),0,args);\r
- break;\r
- }\r
- case FUNC_DISPATCH: {\r
- IDispatch *disp;\r
-\r
- hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);\r
- if (SUCCEEDED(hres)) {\r
- FIXME("Calling Invoke in IDispatch iface. untested!\n");\r
- hres = IDispatch_Invoke(\r
- disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,\r
- pVarResult,pExcepInfo,pArgErr\r
- );\r
- if (FAILED(hres))\r
- FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);\r
- IDispatch_Release(disp);\r
- } else\r
- FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");\r
- break;\r
- }\r
- default:\r
- FIXME("Unknown function invocation type %d\n", func_desc->funckind);\r
- hres = E_FAIL;\r
- break;\r
- }\r
-\r
- ITypeInfo2_ReleaseFuncDesc(iface, func_desc);\r
- return hres;\r
-\r
- } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {\r
- VARDESC *var_desc;\r
-\r
- hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);\r
- if(FAILED(hres)) return hres;\r
- \r
- FIXME("varseek: Found memid, but variable-based invoking not supported\n");\r
- dump_VARDESC(var_desc);\r
- ITypeInfo2_ReleaseVarDesc(iface, var_desc);\r
- return E_NOTIMPL;\r
- }\r
-\r
- /* not found, look for it in inherited interfaces */\r
- ITypeInfo2_GetTypeKind(iface, &type_kind);\r
- if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {\r
- HREFTYPE ref_type;\r
- if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {\r
- /* recursive search */\r
- ITypeInfo *pTInfo;\r
- hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);\r
- if(SUCCEEDED(hres)){\r
- hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);\r
- ITypeInfo_Release(pTInfo);\r
- return hres;\r
- }\r
- WARN("Could not search inherited interface!\n");\r
- }\r
- }\r
- ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);\r
- return DISP_E_MEMBERNOTFOUND;\r
-}\r
-\r
-/* ITypeInfo::GetDocumentation\r
- *\r
- * Retrieves the documentation string, the complete Help file name and path,\r
- * and the context ID for the Help topic for a specified type description.\r
- *\r
- * (Can be tested by the Visual Basic Editor in Word for instance.)\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,\r
- MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,\r
- DWORD *pdwHelpContext, BSTR *pBstrHelpFile)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBFuncDesc * pFDesc;\r
- TLBVarDesc * pVDesc;\r
- TRACE("(%p) memid %ld Name(%p) DocString(%p)"\r
- " HelpContext(%p) HelpFile(%p)\n",\r
- This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);\r
- if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */\r
- if(pBstrName)\r
- *pBstrName=SysAllocString(This->Name);\r
- if(pBstrDocString)\r
- *pBstrDocString=SysAllocString(This->DocString);\r
- if(pdwHelpContext)\r
- *pdwHelpContext=This->dwHelpContext;\r
- if(pBstrHelpFile)\r
- *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */\r
- return S_OK;\r
- }else {/* for a member */\r
- for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)\r
- if(pFDesc->funcdesc.memid==memid){\r
- if(pBstrName)\r
- *pBstrName = SysAllocString(pFDesc->Name);\r
- if(pBstrDocString)\r
- *pBstrDocString=SysAllocString(pFDesc->HelpString);\r
- if(pdwHelpContext)\r
- *pdwHelpContext=pFDesc->helpcontext;\r
- return S_OK;\r
- }\r
- for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)\r
- if(pVDesc->vardesc.memid==memid){\r
- if(pBstrName)\r
- *pBstrName = SysAllocString(pVDesc->Name);\r
- if(pBstrDocString)\r
- *pBstrDocString=SysAllocString(pVDesc->HelpString);\r
- if(pdwHelpContext)\r
- *pdwHelpContext=pVDesc->HelpContext;\r
- return S_OK;\r
- }\r
- }\r
- return TYPE_E_ELEMENTNOTFOUND;\r
-}\r
-\r
-/* ITypeInfo::GetDllEntry\r
- *\r
- * Retrieves a description or specification of an entry point for a function\r
- * in a DLL.\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,\r
- INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,\r
- WORD *pwOrdinal)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBFuncDesc *pFDesc;\r
-\r
- FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);\r
-\r
- for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)\r
- if(pFDesc->funcdesc.memid==memid){\r
- dump_TypeInfo(This);\r
- dump_TLBFuncDescOne(pFDesc);\r
-\r
- /* FIXME: This is wrong, but how do you find that out? */\r
- if (pBstrDllName) {\r
- static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};\r
- *pBstrDllName = SysAllocString(oleaut32W);\r
- }\r
-\r
- if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {\r
- if (pBstrName)\r
- *pBstrName = SysAllocString(pFDesc->Entry);\r
- if (pwOrdinal)\r
- *pwOrdinal = -1;\r
- return S_OK;\r
- }\r
- if (pBstrName)\r
- *pBstrName = NULL;\r
- if (pwOrdinal)\r
- *pwOrdinal = (DWORD)pFDesc->Entry;\r
- return S_OK;\r
- }\r
- return E_FAIL;\r
-}\r
-\r
-/* ITypeInfo::GetRefTypeInfo\r
- *\r
- * If a type description references other type descriptions, it retrieves\r
- * the referenced type descriptions.\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(\r
- ITypeInfo2 *iface,\r
- HREFTYPE hRefType,\r
- ITypeInfo **ppTInfo)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- HRESULT result = E_FAIL;\r
-\r
-\r
- if (hRefType == -1 &&\r
- (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&\r
- (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))\r
- {\r
- /* when we meet a DUAL dispinterface, we must create the interface\r
- * version of it.\r
- */\r
- ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();\r
-\r
-\r
- /* the interface version contains the same information as the dispinterface\r
- * copy the contents of the structs.\r
- */\r
- *pTypeInfoImpl = *This;\r
- pTypeInfoImpl->ref = 1;\r
-\r
- /* change the type to interface */\r
- pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;\r
-\r
- *ppTInfo = (ITypeInfo*) pTypeInfoImpl;\r
-\r
- ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);\r
-\r
- result = S_OK;\r
-\r
- } else {\r
- TLBRefType *pRefType;\r
- for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {\r
- if(pRefType->reference == hRefType)\r
- break;\r
- }\r
- if(!pRefType)\r
- FIXME("Can't find pRefType for ref %lx\n", hRefType);\r
- if(pRefType && hRefType != -1) {\r
- ITypeLib *pTLib = NULL;\r
-\r
- if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {\r
- int Index;\r
- result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);\r
- } else {\r
- if(pRefType->pImpTLInfo->pImpTypeLib) {\r
- TRACE("typeinfo in imported typelib that is already loaded\n");\r
- pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;\r
- ITypeLib2_AddRef((ITypeLib*) pTLib);\r
- result = S_OK;\r
- } else {\r
- TRACE("typeinfo in imported typelib that isn't already loaded\n");\r
- result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,\r
- pRefType->pImpTLInfo->wVersionMajor,\r
- pRefType->pImpTLInfo->wVersionMinor,\r
- pRefType->pImpTLInfo->lcid,\r
- &pTLib);\r
-\r
- if(!SUCCEEDED(result)) {\r
- BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);\r
- result=LoadTypeLib(libnam, &pTLib);\r
- SysFreeString(libnam);\r
- }\r
- if(SUCCEEDED(result)) {\r
- pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;\r
- ITypeLib2_AddRef(pTLib);\r
- }\r
- }\r
- }\r
- if(SUCCEEDED(result)) {\r
- if(pRefType->index == TLB_REF_USE_GUID)\r
- result = ITypeLib2_GetTypeInfoOfGuid(pTLib,\r
- &pRefType->guid,\r
- ppTInfo);\r
- else\r
- result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,\r
- ppTInfo);\r
- }\r
- if (pTLib != NULL)\r
- ITypeLib2_Release(pTLib);\r
- }\r
- }\r
-\r
- TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,\r
- SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);\r
- return result;\r
-}\r
-\r
-/* ITypeInfo::AddressOfMember\r
- *\r
- * Retrieves the addresses of static functions or variables, such as those\r
- * defined in a DLL.\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,\r
- MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- FIXME("(%p) stub!\n", This);\r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo::CreateInstance\r
- *\r
- * Creates a new instance of a type that describes a component object class\r
- * (coclass).\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,\r
- IUnknown *pUnk, REFIID riid, VOID **ppvObj)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- FIXME("(%p) stub!\n", This);\r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo::GetMops\r
- *\r
- * Retrieves marshalling information.\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,\r
- BSTR *pBstrMops)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- FIXME("(%p) stub!\n", This);\r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo::GetContainingTypeLib\r
- *\r
- * Retrieves the containing type library and the index of the type description\r
- * within that type library.\r
- */\r
-static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,\r
- ITypeLib * *ppTLib, UINT *pIndex)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- \r
- /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */\r
- if (pIndex) {\r
- *pIndex=This->index;\r
- TRACE("returning pIndex=%d\n", *pIndex);\r
- }\r
- \r
- if (ppTLib) {\r
- *ppTLib=(LPTYPELIB )(This->pTypeLib);\r
- ITypeLib2_AddRef(*ppTLib);\r
- TRACE("returning ppTLib=%p\n", *ppTLib);\r
- }\r
- \r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo::ReleaseTypeAttr\r
- *\r
- * Releases a TYPEATTR previously returned by GetTypeAttr.\r
- *\r
- */\r
-static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,\r
- TYPEATTR* pTypeAttr)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TRACE("(%p)->(%p)\n", This, pTypeAttr);\r
- if(This->TypeAttr.typekind == TKIND_ALIAS)\r
- free_deep_typedesc(&pTypeAttr->tdescAlias);\r
- HeapFree(GetProcessHeap(), 0, pTypeAttr);\r
-}\r
-\r
-/* ITypeInfo::ReleaseFuncDesc\r
- *\r
- * Releases a FUNCDESC previously returned by GetFuncDesc. *\r
- */\r
-static void WINAPI ITypeInfo_fnReleaseFuncDesc(\r
- ITypeInfo2 *iface,\r
- FUNCDESC *pFuncDesc)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TRACE("(%p)->(%p)\n", This, pFuncDesc);\r
-}\r
-\r
-/* ITypeInfo::ReleaseVarDesc\r
- *\r
- * Releases a VARDESC previously returned by GetVarDesc.\r
- */\r
-static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,\r
- VARDESC *pVarDesc)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TRACE("(%p)->(%p)\n", This, pVarDesc);\r
-}\r
-\r
-/* ITypeInfo2::GetTypeKind\r
- *\r
- * Returns the TYPEKIND enumeration quickly, without doing any allocations.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,\r
- TYPEKIND *pTypeKind)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- *pTypeKind=This->TypeAttr.typekind;\r
- TRACE("(%p) type 0x%0x\n", This,*pTypeKind);\r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo2::GetTypeFlags\r
- *\r
- * Returns the type flags without any allocations. This returns a DWORD type\r
- * flag, which expands the type flags without growing the TYPEATTR (type\r
- * attribute).\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- *pTypeFlags=This->TypeAttr.wTypeFlags;\r
- TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);\r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo2::GetFuncIndexOfMemId\r
- * Binds to a specific member based on a known DISPID, where the member name\r
- * is not known (for example, when binding to a default member).\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,\r
- MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBFuncDesc *pFuncInfo;\r
- int i;\r
- HRESULT result;\r
-\r
- for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)\r
- if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))\r
- break;\r
- if(pFuncInfo) {\r
- *pFuncIndex = i;\r
- result = S_OK;\r
- } else\r
- result = TYPE_E_ELEMENTNOTFOUND;\r
-\r
- TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,\r
- memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");\r
- return result;\r
-}\r
-\r
-/* TypeInfo2::GetVarIndexOfMemId\r
- *\r
- * Binds to a specific member based on a known DISPID, where the member name\r
- * is not known (for example, when binding to a default member).\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,\r
- MEMBERID memid, UINT *pVarIndex)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBVarDesc *pVarInfo;\r
- int i;\r
- HRESULT result;\r
- for(i=0, pVarInfo=This->varlist; pVarInfo &&\r
- memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)\r
- ;\r
- if(pVarInfo) {\r
- *pVarIndex = i;\r
- result = S_OK;\r
- } else\r
- result = TYPE_E_ELEMENTNOTFOUND;\r
-\r
- TRACE("(%p) memid 0x%08lx -> %s\n", This,\r
- memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");\r
- return result;\r
-}\r
-\r
-/* ITypeInfo2::GetCustData\r
- *\r
- * Gets the custom data\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetCustData(\r
- ITypeInfo2 * iface,\r
- REFGUID guid,\r
- VARIANT *pVarVal)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData;\r
-\r
- for(pCData=This->pCustData; pCData; pCData = pCData->next)\r
- if( IsEqualIID(guid, &pCData->guid)) break;\r
-\r
- TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");\r
-\r
- if(pCData)\r
- {\r
- VariantInit( pVarVal);\r
- VariantCopy( pVarVal, &pCData->data);\r
- return S_OK;\r
- }\r
- return E_INVALIDARG; /* FIXME: correct? */\r
-}\r
-\r
-/* ITypeInfo2::GetFuncCustData\r
- *\r
- * Gets the custom data\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(\r
- ITypeInfo2 * iface,\r
- UINT index,\r
- REFGUID guid,\r
- VARIANT *pVarVal)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData=NULL;\r
- TLBFuncDesc * pFDesc;\r
- int i;\r
- for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,\r
- pFDesc=pFDesc->next);\r
-\r
- if(pFDesc)\r
- for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)\r
- if( IsEqualIID(guid, &pCData->guid)) break;\r
-\r
- TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");\r
-\r
- if(pCData){\r
- VariantInit( pVarVal);\r
- VariantCopy( pVarVal, &pCData->data);\r
- return S_OK;\r
- }\r
- return E_INVALIDARG; /* FIXME: correct? */\r
-}\r
-\r
-/* ITypeInfo2::GetParamCustData\r
- *\r
- * Gets the custom data\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(\r
- ITypeInfo2 * iface,\r
- UINT indexFunc,\r
- UINT indexParam,\r
- REFGUID guid,\r
- VARIANT *pVarVal)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData=NULL;\r
- TLBFuncDesc * pFDesc;\r
- int i;\r
-\r
- for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);\r
-\r
- if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)\r
- for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;\r
- pCData = pCData->next)\r
- if( IsEqualIID(guid, &pCData->guid)) break;\r
-\r
- TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");\r
-\r
- if(pCData)\r
- {\r
- VariantInit( pVarVal);\r
- VariantCopy( pVarVal, &pCData->data);\r
- return S_OK;\r
- }\r
- return E_INVALIDARG; /* FIXME: correct? */\r
-}\r
-\r
-/* ITypeInfo2::GetVarCustData\r
- *\r
- * Gets the custom data\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(\r
- ITypeInfo2 * iface,\r
- UINT index,\r
- REFGUID guid,\r
- VARIANT *pVarVal)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData=NULL;\r
- TLBVarDesc * pVDesc;\r
- int i;\r
-\r
- for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);\r
-\r
- if(pVDesc)\r
- {\r
- for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)\r
- {\r
- if( IsEqualIID(guid, &pCData->guid)) break;\r
- }\r
- }\r
-\r
- TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");\r
-\r
- if(pCData)\r
- {\r
- VariantInit( pVarVal);\r
- VariantCopy( pVarVal, &pCData->data);\r
- return S_OK;\r
- }\r
- return E_INVALIDARG; /* FIXME: correct? */\r
-}\r
-\r
-/* ITypeInfo2::GetImplCustData\r
- *\r
- * Gets the custom data\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(\r
- ITypeInfo2 * iface,\r
- UINT index,\r
- REFGUID guid,\r
- VARIANT *pVarVal)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData=NULL;\r
- TLBImplType * pRDesc;\r
- int i;\r
-\r
- for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);\r
-\r
- if(pRDesc)\r
- {\r
- for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)\r
- {\r
- if( IsEqualIID(guid, &pCData->guid)) break;\r
- }\r
- }\r
-\r
- TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");\r
-\r
- if(pCData)\r
- {\r
- VariantInit( pVarVal);\r
- VariantCopy( pVarVal, &pCData->data);\r
- return S_OK;\r
- }\r
- return E_INVALIDARG; /* FIXME: correct? */\r
-}\r
-\r
-/* ITypeInfo2::GetDocumentation2\r
- *\r
- * Retrieves the documentation string, the complete Help file name and path,\r
- * the localization context to use, and the context ID for the library Help\r
- * topic in the Help file.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(\r
- ITypeInfo2 * iface,\r
- MEMBERID memid,\r
- LCID lcid,\r
- BSTR *pbstrHelpString,\r
- DWORD *pdwHelpStringContext,\r
- BSTR *pbstrHelpStringDll)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBFuncDesc * pFDesc;\r
- TLBVarDesc * pVDesc;\r
- TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "\r
- "HelpStringContext(%p) HelpStringDll(%p)\n",\r
- This, memid, lcid, pbstrHelpString, pdwHelpStringContext,\r
- pbstrHelpStringDll );\r
- /* the help string should be obtained from the helpstringdll,\r
- * using the _DLLGetDocumentation function, based on the supplied\r
- * lcid. Nice to do sometime...\r
- */\r
- if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */\r
- if(pbstrHelpString)\r
- *pbstrHelpString=SysAllocString(This->Name);\r
- if(pdwHelpStringContext)\r
- *pdwHelpStringContext=This->dwHelpStringContext;\r
- if(pbstrHelpStringDll)\r
- *pbstrHelpStringDll=\r
- SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */\r
- return S_OK;\r
- }else {/* for a member */\r
- for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)\r
- if(pFDesc->funcdesc.memid==memid){\r
- if(pbstrHelpString)\r
- *pbstrHelpString=SysAllocString(pFDesc->HelpString);\r
- if(pdwHelpStringContext)\r
- *pdwHelpStringContext=pFDesc->HelpStringContext;\r
- if(pbstrHelpStringDll)\r
- *pbstrHelpStringDll=\r
- SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */\r
- return S_OK;\r
- }\r
- for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)\r
- if(pVDesc->vardesc.memid==memid){\r
- if(pbstrHelpString)\r
- *pbstrHelpString=SysAllocString(pVDesc->HelpString);\r
- if(pdwHelpStringContext)\r
- *pdwHelpStringContext=pVDesc->HelpStringContext;\r
- if(pbstrHelpStringDll)\r
- *pbstrHelpStringDll=\r
- SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */\r
- return S_OK;\r
- }\r
- }\r
- return TYPE_E_ELEMENTNOTFOUND;\r
-}\r
-\r
-/* ITypeInfo2::GetAllCustData\r
- *\r
- * Gets all custom data items for the Type info.\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(\r
- ITypeInfo2 * iface,\r
- CUSTDATA *pCustData)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData;\r
- int i;\r
-\r
- TRACE("(%p) returning %d items\n", This, This->ctCustData);\r
-\r
- pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));\r
- if(pCustData->prgCustData ){\r
- pCustData->cCustData=This->ctCustData;\r
- for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){\r
- pCustData->prgCustData[i].guid=pCData->guid;\r
- VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);\r
- }\r
- }else{\r
- ERR(" OUT OF MEMORY! \n");\r
- return E_OUTOFMEMORY;\r
- }\r
- return S_OK;\r
-}\r
-\r
-/* ITypeInfo2::GetAllFuncCustData\r
- *\r
- * Gets all custom data items for the specified Function\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(\r
- ITypeInfo2 * iface,\r
- UINT index,\r
- CUSTDATA *pCustData)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData;\r
- TLBFuncDesc * pFDesc;\r
- int i;\r
- TRACE("(%p) index %d\n", This, index);\r
- for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,\r
- pFDesc=pFDesc->next)\r
- ;\r
- if(pFDesc){\r
- pCustData->prgCustData =\r
- TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));\r
- if(pCustData->prgCustData ){\r
- pCustData->cCustData=pFDesc->ctCustData;\r
- for(i=0, pCData=pFDesc->pCustData; pCData; i++,\r
- pCData = pCData->next){\r
- pCustData->prgCustData[i].guid=pCData->guid;\r
- VariantCopy(& pCustData->prgCustData[i].varValue,\r
- & pCData->data);\r
- }\r
- }else{\r
- ERR(" OUT OF MEMORY! \n");\r
- return E_OUTOFMEMORY;\r
- }\r
- return S_OK;\r
- }\r
- return TYPE_E_ELEMENTNOTFOUND;\r
-}\r
-\r
-/* ITypeInfo2::GetAllParamCustData\r
- *\r
- * Gets all custom data items for the Functions\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,\r
- UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData=NULL;\r
- TLBFuncDesc * pFDesc;\r
- int i;\r
- TRACE("(%p) index %d\n", This, indexFunc);\r
- for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,\r
- pFDesc=pFDesc->next)\r
- ;\r
- if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){\r
- pCustData->prgCustData =\r
- TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *\r
- sizeof(CUSTDATAITEM));\r
- if(pCustData->prgCustData ){\r
- pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;\r
- for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;\r
- pCData; i++, pCData = pCData->next){\r
- pCustData->prgCustData[i].guid=pCData->guid;\r
- VariantCopy(& pCustData->prgCustData[i].varValue,\r
- & pCData->data);\r
- }\r
- }else{\r
- ERR(" OUT OF MEMORY! \n");\r
- return E_OUTOFMEMORY;\r
- }\r
- return S_OK;\r
- }\r
- return TYPE_E_ELEMENTNOTFOUND;\r
-}\r
-\r
-/* ITypeInfo2::GetAllVarCustData\r
- *\r
- * Gets all custom data items for the specified Variable\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,\r
- UINT index, CUSTDATA *pCustData)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData;\r
- TLBVarDesc * pVDesc;\r
- int i;\r
- TRACE("(%p) index %d\n", This, index);\r
- for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,\r
- pVDesc=pVDesc->next)\r
- ;\r
- if(pVDesc){\r
- pCustData->prgCustData =\r
- TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));\r
- if(pCustData->prgCustData ){\r
- pCustData->cCustData=pVDesc->ctCustData;\r
- for(i=0, pCData=pVDesc->pCustData; pCData; i++,\r
- pCData = pCData->next){\r
- pCustData->prgCustData[i].guid=pCData->guid;\r
- VariantCopy(& pCustData->prgCustData[i].varValue,\r
- & pCData->data);\r
- }\r
- }else{\r
- ERR(" OUT OF MEMORY! \n");\r
- return E_OUTOFMEMORY;\r
- }\r
- return S_OK;\r
- }\r
- return TYPE_E_ELEMENTNOTFOUND;\r
-}\r
-\r
-/* ITypeInfo2::GetAllImplCustData\r
- *\r
- * Gets all custom data items for the specified implementation type\r
- *\r
- */\r
-static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(\r
- ITypeInfo2 * iface,\r
- UINT index,\r
- CUSTDATA *pCustData)\r
-{\r
- ITypeInfoImpl *This = (ITypeInfoImpl *)iface;\r
- TLBCustData *pCData;\r
- TLBImplType * pRDesc;\r
- int i;\r
- TRACE("(%p) index %d\n", This, index);\r
- for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,\r
- pRDesc=pRDesc->next)\r
- ;\r
- if(pRDesc){\r
- pCustData->prgCustData =\r
- TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));\r
- if(pCustData->prgCustData ){\r
- pCustData->cCustData=pRDesc->ctCustData;\r
- for(i=0, pCData=pRDesc->pCustData; pCData; i++,\r
- pCData = pCData->next){\r
- pCustData->prgCustData[i].guid=pCData->guid;\r
- VariantCopy(& pCustData->prgCustData[i].varValue,\r
- & pCData->data);\r
- }\r
- }else{\r
- ERR(" OUT OF MEMORY! \n");\r
- return E_OUTOFMEMORY;\r
- }\r
- return S_OK;\r
- }\r
- return TYPE_E_ELEMENTNOTFOUND;\r
-}\r
-\r
-static ITypeInfo2Vtbl tinfvt =\r
-{\r
-\r
- ITypeInfo_fnQueryInterface,\r
- ITypeInfo_fnAddRef,\r
- ITypeInfo_fnRelease,\r
-\r
- ITypeInfo_fnGetTypeAttr,\r
- ITypeInfo_fnGetTypeComp,\r
- ITypeInfo_fnGetFuncDesc,\r
- ITypeInfo_fnGetVarDesc,\r
- ITypeInfo_fnGetNames,\r
- ITypeInfo_fnGetRefTypeOfImplType,\r
- ITypeInfo_fnGetImplTypeFlags,\r
- ITypeInfo_fnGetIDsOfNames,\r
- ITypeInfo_fnInvoke,\r
- ITypeInfo_fnGetDocumentation,\r
- ITypeInfo_fnGetDllEntry,\r
- ITypeInfo_fnGetRefTypeInfo,\r
- ITypeInfo_fnAddressOfMember,\r
- ITypeInfo_fnCreateInstance,\r
- ITypeInfo_fnGetMops,\r
- ITypeInfo_fnGetContainingTypeLib,\r
- ITypeInfo_fnReleaseTypeAttr,\r
- ITypeInfo_fnReleaseFuncDesc,\r
- ITypeInfo_fnReleaseVarDesc,\r
-\r
- ITypeInfo2_fnGetTypeKind,\r
- ITypeInfo2_fnGetTypeFlags,\r
- ITypeInfo2_fnGetFuncIndexOfMemId,\r
- ITypeInfo2_fnGetVarIndexOfMemId,\r
- ITypeInfo2_fnGetCustData,\r
- ITypeInfo2_fnGetFuncCustData,\r
- ITypeInfo2_fnGetParamCustData,\r
- ITypeInfo2_fnGetVarCustData,\r
- ITypeInfo2_fnGetImplTypeCustData,\r
- ITypeInfo2_fnGetDocumentation2,\r
- ITypeInfo2_fnGetAllCustData,\r
- ITypeInfo2_fnGetAllFuncCustData,\r
- ITypeInfo2_fnGetAllParamCustData,\r
- ITypeInfo2_fnGetAllVarCustData,\r
- ITypeInfo2_fnGetAllImplTypeCustData,\r
-};\r
-\r
-/******************************************************************************\r
- * CreateDispTypeInfo [OLEAUT32.31]\r
- *\r
- * Build type information for an object so it can be called through an\r
- * IDispatch interface.\r
- *\r
- * RETURNS\r
- * Success: S_OK. pptinfo contains the created ITypeInfo object.\r
- * Failure: E_INVALIDARG, if one or more arguments is invalid.\r
- *\r
- * NOTES\r
- * This call allows an objects methods to be accessed through IDispatch, by\r
- * building an ITypeInfo object that IDispatch can use to call through.\r
- */\r
-HRESULT WINAPI CreateDispTypeInfo(\r
- INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */\r
- LCID lcid, /* [I] Locale Id */\r
- ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */\r
-{\r
- ITypeInfoImpl *pTIImpl;\r
- int param, func;\r
- TLBFuncDesc **ppFuncDesc;\r
-\r
- pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();\r
- pTIImpl->pTypeLib = NULL;\r
- pTIImpl->index = 0;\r
- pTIImpl->Name = NULL;\r
- pTIImpl->dwHelpContext = -1;\r
- memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));\r
- pTIImpl->TypeAttr.lcid = lcid;\r
- pTIImpl->TypeAttr.typekind = TKIND_COCLASS;\r
- pTIImpl->TypeAttr.wMajorVerNum = 0;\r
- pTIImpl->TypeAttr.wMinorVerNum = 0;\r
- pTIImpl->TypeAttr.cbAlignment = 2;\r
- pTIImpl->TypeAttr.cbSizeInstance = -1;\r
- pTIImpl->TypeAttr.cbSizeVft = -1;\r
- pTIImpl->TypeAttr.cFuncs = 0;\r
- pTIImpl->TypeAttr.cImplTypes = 1;\r
- pTIImpl->TypeAttr.cVars = 0;\r
- pTIImpl->TypeAttr.wTypeFlags = 0;\r
-\r
- ppFuncDesc = &pTIImpl->funclist;\r
- for(func = 0; func < pidata->cMembers; func++) {\r
- METHODDATA *md = pidata->pmethdata + func;\r
- *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));\r
- (*ppFuncDesc)->Name = SysAllocString(md->szName);\r
- (*ppFuncDesc)->funcdesc.memid = md->dispid;\r
- (*ppFuncDesc)->funcdesc.invkind = md->wFlags;\r
- (*ppFuncDesc)->funcdesc.callconv = md->cc;\r
- (*ppFuncDesc)->funcdesc.cParams = md->cArgs;\r
- (*ppFuncDesc)->funcdesc.cParamsOpt = 0;\r
- (*ppFuncDesc)->funcdesc.oVft = md->iMeth;\r
- (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/\r
- (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;\r
- (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- md->cArgs * sizeof(ELEMDESC));\r
- (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
- md->cArgs * sizeof(TLBParDesc));\r
- for(param = 0; param < md->cArgs; param++) {\r
- (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;\r
- (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);\r
- }\r
- ppFuncDesc = &(*ppFuncDesc)->next;\r
- } \r
- *pptinfo = (ITypeInfo*)pTIImpl;\r
- return S_OK;\r
-\r
-}\r
-\r
-static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)\r
-{\r
- ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);\r
-\r
- return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);\r
-}\r
-\r
-static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)\r
-{\r
- ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);\r
-\r
- return ITypeInfo_AddRef((ITypeInfo *)This);\r
-}\r
-\r
-static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)\r
-{\r
- ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);\r
-\r
- return ITypeInfo_Release((ITypeInfo *)This);\r
-}\r
-\r
-static HRESULT WINAPI ITypeComp_fnBind(\r
- ITypeComp * iface,\r
- OLECHAR * szName,\r
- ULONG lHash,\r
- WORD wFlags,\r
- ITypeInfo ** ppTInfo,\r
- DESCKIND * pDescKind,\r
- BINDPTR * pBindPtr)\r
-{\r
- ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);\r
- TLBFuncDesc * pFDesc;\r
- TLBVarDesc * pVDesc;\r
-\r
- TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);\r
-\r
- for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)\r
- if (pFDesc->funcdesc.invkind & wFlags)\r
- if (!strcmpW(pFDesc->Name, szName)) {\r
- break;\r
- }\r
-\r
- if (pFDesc)\r
- {\r
- *pDescKind = DESCKIND_FUNCDESC;\r
- pBindPtr->lpfuncdesc = &pFDesc->funcdesc;\r
- *ppTInfo = (ITypeInfo *)&This->lpVtbl;\r
- return S_OK;\r
- } else {\r
- if (!(wFlags & ~(INVOKE_PROPERTYGET)))\r
- {\r
- for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {\r
- if (!strcmpW(pVDesc->Name, szName)) {\r
- *pDescKind = DESCKIND_VARDESC;\r
- pBindPtr->lpvardesc = &pVDesc->vardesc;\r
- *ppTInfo = (ITypeInfo *)&This->lpVtbl;\r
- return S_OK;\r
- }\r
- }\r
- }\r
- }\r
- /* not found, look for it in inherited interfaces */\r
- if (This->TypeAttr.cImplTypes &&\r
- (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {\r
- /* recursive search */\r
- ITypeInfo *pTInfo;\r
- ITypeComp *pTComp;\r
- HRESULT hr;\r
- hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);\r
- if (SUCCEEDED(hr))\r
- {\r
- hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);\r
- ITypeInfo_Release(pTInfo);\r
- }\r
- if (SUCCEEDED(hr))\r
- {\r
- hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);\r
- ITypeComp_Release(pTComp);\r
- return hr;\r
- }\r
- WARN("Could not search inherited interface!\n");\r
- }\r
- ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);\r
- *pDescKind = DESCKIND_NONE;\r
- pBindPtr->lpfuncdesc = NULL;\r
- *ppTInfo = NULL;\r
- return DISP_E_MEMBERNOTFOUND;\r
-}\r
-\r
-static HRESULT WINAPI ITypeComp_fnBindType(\r
- ITypeComp * iface,\r
- OLECHAR * szName,\r
- ULONG lHash,\r
- ITypeInfo ** ppTInfo,\r
- ITypeComp ** ppTComp)\r
-{\r
- TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);\r
-\r
- /* strange behaviour (does nothing) but like the\r
- * original */\r
-\r
- if (!ppTInfo || !ppTComp)\r
- return E_POINTER;\r
-\r
- *ppTInfo = NULL;\r
- *ppTComp = NULL;\r
-\r
- return S_OK;\r
-}\r
-\r
-static ITypeCompVtbl tcompvt =\r
-{\r
-\r
- ITypeComp_fnQueryInterface,\r
- ITypeComp_fnAddRef,\r
- ITypeComp_fnRelease,\r
-\r
- ITypeComp_fnBind,\r
- ITypeComp_fnBindType\r
-};\r
+/*
+ * TYPELIB
+ *
+ * Copyright 1997 Marcus Meissner
+ * 1999 Rein Klazes
+ * 2000 Francois Jacques
+ * 2001 Huw D M Davies for CodeWeavers
+ * 2005 Robert Shearman, for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * --------------------------------------------------------------------------------------
+ * Known problems (2000, Francois Jacques)
+ *
+ * - Tested using OLEVIEW (Platform SDK tool) only.
+ *
+ * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
+ * creating by doing a straight copy of the dispinterface instance and just changing
+ * its typekind. Pointed structures aren't copied - only the address of the pointers.
+ * So when you release the dispinterface, you delete the vtable-interface structures
+ * as well... fortunately, clean up of structures is not implemented.
+ *
+ * - locale stuff is partially implemented but hasn't been tested.
+ *
+ * - typelib file is still read in its entirety, but it is released now.
+ * - some garbage is read from function names on some very rare occasions.
+ *
+ * --------------------------------------------------------------------------------------
+ * Known problems left from previous implementation (1999, Rein Klazes) :
+ *
+ * -. Data structures are straightforward, but slow for look-ups.
+ * -. (related) nothing is hashed
+ * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
+ * of them I don't know yet how to implement them.
+ * -. Most error return values are just guessed not checked with windows
+ * behaviour.
+ * -. didn't bother with a c++ interface
+ * -. lousy fatal error handling
+ * -. some methods just return pointers to internal data structures, this is
+ * partly laziness, partly I want to check how windows does it.
+ *
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#define COBJMACROS
+#define NONAMELESSUNION
+#define NONAMELESSSTRUCT
+
+#include "winerror.h"
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "winreg.h"
+#include "winuser.h"
+
+#include "wine/unicode.h"
+#include "objbase.h"
+#include "typelib.h"
+#include "wine/debug.h"
+#include "variant.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
+WINE_DECLARE_DEBUG_CHANNEL(typelib);
+
+/* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
+const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
+
+static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt);
+static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
+
+/****************************************************************************
+ * FromLExxx
+ *
+ * Takes p_iVal (which is in little endian) and returns it
+ * in the host machine's byte order.
+ */
+#ifdef WORDS_BIGENDIAN
+static WORD FromLEWord(WORD p_iVal)
+{
+ return (((p_iVal & 0x00FF) << 8) |
+ ((p_iVal & 0xFF00) >> 8));
+}
+
+
+static DWORD FromLEDWord(DWORD p_iVal)
+{
+ return (((p_iVal & 0x000000FF) << 24) |
+ ((p_iVal & 0x0000FF00) << 8) |
+ ((p_iVal & 0x00FF0000) >> 8) |
+ ((p_iVal & 0xFF000000) >> 24));
+}
+#else
+#define FromLEWord(X) (X)
+#define FromLEDWord(X) (X)
+#endif
+
+
+/****************************************************************************
+ * FromLExxx
+ *
+ * Fix byte order in any structure if necessary
+ */
+#ifdef WORDS_BIGENDIAN
+static void FromLEWords(void *p_Val, int p_iSize)
+{
+ WORD *Val = p_Val;
+
+ p_iSize /= sizeof(WORD);
+
+ while (p_iSize) {
+ *Val = FromLEWord(*Val);
+ Val++;
+ p_iSize--;
+ }
+}
+
+
+static void FromLEDWords(void *p_Val, int p_iSize)
+{
+ DWORD *Val = p_Val;
+
+ p_iSize /= sizeof(DWORD);
+
+ while (p_iSize) {
+ *Val = FromLEDWord(*Val);
+ Val++;
+ p_iSize--;
+ }
+}
+#else
+#define FromLEWords(X,Y) /*nothing*/
+#define FromLEDWords(X,Y) /*nothing*/
+#endif
+
+/* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
+/* buffer must be at least 60 characters long */
+static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
+{
+ static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
+ static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
+
+ memcpy( buffer, TypelibW, sizeof(TypelibW) );
+ StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
+ sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
+ return buffer;
+}
+
+/* get the path of an interface key, in the form "Interface\\<guid>" */
+/* buffer must be at least 50 characters long */
+static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
+{
+ static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
+
+ memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
+ StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
+ return buffer;
+}
+
+/* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
+/* buffer must be at least 16 characters long */
+static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
+{
+ static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
+ static const WCHAR win16W[] = {'w','i','n','1','6',0};
+ static const WCHAR win32W[] = {'w','i','n','3','2',0};
+
+ sprintfW( buffer, LcidFormatW, lcid );
+ switch(syskind)
+ {
+ case SYS_WIN16: strcatW( buffer, win16W ); break;
+ case SYS_WIN32: strcatW( buffer, win32W ); break;
+ default:
+ TRACE("Typelib is for unsupported syskind %i\n", syskind);
+ return NULL;
+ }
+ return buffer;
+}
+
+int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
+
+
+/****************************************************************************
+ * QueryPathOfRegTypeLib [OLEAUT32.164]
+ *
+ * Gets the path to a registered type library.
+ *
+ * PARAMS
+ * guid [I] referenced guid
+ * wMaj [I] major version
+ * wMin [I] minor version
+ * lcid [I] locale id
+ * path [O] path of typelib
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
+ * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
+ * opened.
+ */
+HRESULT WINAPI QueryPathOfRegTypeLib(
+ REFGUID guid,
+ WORD wMaj,
+ WORD wMin,
+ LCID lcid,
+ LPBSTR path )
+{
+ HRESULT hr = TYPE_E_LIBNOTREGISTERED;
+ LCID myLCID = lcid;
+ HKEY hkey;
+ WCHAR buffer[60];
+ WCHAR Path[MAX_PATH];
+ LONG res;
+
+ TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
+
+ get_typelib_key( guid, wMaj, wMin, buffer );
+
+ res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
+ if (res == ERROR_FILE_NOT_FOUND)
+ {
+ TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
+ return TYPE_E_LIBNOTREGISTERED;
+ }
+ else if (res != ERROR_SUCCESS)
+ {
+ TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
+ return TYPE_E_REGISTRYACCESS;
+ }
+
+ while (hr != S_OK)
+ {
+ LONG dwPathLen = sizeof(Path);
+
+ get_lcid_subkey( myLCID, SYS_WIN32, buffer );
+
+ if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
+ {
+ if (!lcid)
+ break;
+ else if (myLCID == lcid)
+ {
+ /* try with sub-langid */
+ myLCID = SUBLANGID(lcid);
+ }
+ else if ((myLCID == SUBLANGID(lcid)) && myLCID)
+ {
+ /* try with system langid */
+ myLCID = 0;
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ *path = SysAllocString( Path );
+ hr = S_OK;
+ }
+ }
+ RegCloseKey( hkey );
+ TRACE_(typelib)("-- 0x%08lx\n", hr);
+ return hr;
+}
+
+/******************************************************************************
+ * CreateTypeLib [OLEAUT32.160] creates a typelib
+ *
+ * RETURNS
+ * Success: S_OK
+ * Failure: Status
+ */
+HRESULT WINAPI CreateTypeLib(
+ SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
+) {
+ FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
+ return E_FAIL;
+}
+
+/******************************************************************************
+ * LoadTypeLib [OLEAUT32.161]
+ *
+ * Loads a type library
+ *
+ * PARAMS
+ * szFile [I] Name of file to load from.
+ * pptLib [O] Pointer that receives ITypeLib object on success.
+ *
+ * RETURNS
+ * Success: S_OK
+ * Failure: Status
+ *
+ * SEE
+ * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
+ */
+HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
+{
+ TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
+ return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
+}
+
+/******************************************************************************
+ * LoadTypeLibEx [OLEAUT32.183]
+ *
+ * Loads and optionally registers a type library
+ *
+ * RETURNS
+ * Success: S_OK
+ * Failure: Status
+ */
+HRESULT WINAPI LoadTypeLibEx(
+ LPCOLESTR szFile, /* [in] Name of file to load from */
+ REGKIND regkind, /* [in] Specify kind of registration */
+ ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
+{
+ WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
+ WCHAR *pIndexStr;
+ HRESULT res;
+ INT index = 1;
+
+ TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
+
+ /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
+ memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
+
+ *pptLib = NULL;
+ if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
+ NULL)) {
+
+ /* Look for a trailing '\\' followed by an index */
+ pIndexStr = strrchrW(szFile, '\\');
+ if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
+ index = atoiW(pIndexStr);
+ memcpy(szFileCopy, szFile,
+ (pIndexStr - szFile - 1) * sizeof(WCHAR));
+ szFileCopy[pIndexStr - szFile - 1] = '\0';
+ if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
+ szPath,NULL))
+ return TYPE_E_CANTLOADLIBRARY;
+ if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
+ return TYPE_E_CANTLOADLIBRARY;
+ }
+ }
+
+ TRACE("File %s index %d\n", debugstr_w(szPath), index);
+
+ res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
+
+ if (SUCCEEDED(res))
+ switch(regkind)
+ {
+ case REGKIND_DEFAULT:
+ /* don't register typelibs supplied with full path. Experimentation confirms the following */
+ if ((!szFile) ||
+ ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
+ (szFile[0] && (szFile[1] == ':'))) break;
+ /* else fall-through */
+
+ case REGKIND_REGISTER:
+ if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
+ {
+ IUnknown_Release(*pptLib);
+ *pptLib = 0;
+ }
+ break;
+ case REGKIND_NONE:
+ break;
+ }
+
+ TRACE(" returns %08lx\n",res);
+ return res;
+}
+
+/******************************************************************************
+ * LoadRegTypeLib [OLEAUT32.162]
+ *
+ * Loads a registered type library.
+ *
+ * PARAMS
+ * rguid [I] GUID of the registered type library.
+ * wVerMajor [I] major version.
+ * wVerMinor [I] minor version.
+ * lcid [I] locale ID.
+ * ppTLib [O] pointer that receives an ITypeLib object on success.
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
+ * LoadTypeLib.
+ */
+HRESULT WINAPI LoadRegTypeLib(
+ REFGUID rguid,
+ WORD wVerMajor,
+ WORD wVerMinor,
+ LCID lcid,
+ ITypeLib **ppTLib)
+{
+ BSTR bstr=NULL;
+ HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
+
+ if(SUCCEEDED(res))
+ {
+ res= LoadTypeLib(bstr, ppTLib);
+ SysFreeString(bstr);
+ }
+
+ TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
+
+ return res;
+}
+
+
+/* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
+static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
+static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
+static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
+static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
+static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
+
+/******************************************************************************
+ * RegisterTypeLib [OLEAUT32.163]
+ * Adds information about a type library to the System Registry
+ * NOTES
+ * Docs: ITypeLib FAR * ptlib
+ * Docs: OLECHAR FAR* szFullPath
+ * Docs: OLECHAR FAR* szHelpDir
+ *
+ * RETURNS
+ * Success: S_OK
+ * Failure: Status
+ */
+HRESULT WINAPI RegisterTypeLib(
+ ITypeLib * ptlib, /* [in] Pointer to the library*/
+ OLECHAR * szFullPath, /* [in] full Path of the library*/
+ OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
+ may be NULL*/
+{
+ static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
+ '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
+ '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
+ HRESULT res;
+ TLIBATTR *attr;
+ WCHAR keyName[60];
+ WCHAR tmp[16];
+ HKEY key, subKey;
+ UINT types, tidx;
+ TYPEKIND kind;
+ DWORD disposition;
+
+ if (ptlib == NULL || szFullPath == NULL)
+ return E_INVALIDARG;
+
+ if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
+ return E_FAIL;
+
+ get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
+
+ res = S_OK;
+ if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
+ KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
+ {
+ LPOLESTR doc;
+
+ /* Set the human-readable name of the typelib */
+ if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
+ {
+ if (RegSetValueExW(key, NULL, 0, REG_SZ,
+ (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
+ res = E_FAIL;
+
+ SysFreeString(doc);
+ }
+ else
+ res = E_FAIL;
+
+ /* Make up the name of the typelib path subkey */
+ if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
+
+ /* Create the typelib path subkey */
+ if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
+ KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
+ {
+ if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
+ (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
+ res = E_FAIL;
+
+ RegCloseKey(subKey);
+ }
+ else
+ res = E_FAIL;
+
+ /* Create the flags subkey */
+ if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
+ KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
+ {
+ /* FIXME: is %u correct? */
+ static const WCHAR formatW[] = {'%','u',0};
+ WCHAR buf[20];
+ sprintfW(buf, formatW, attr->wLibFlags);
+ if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
+ (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
+ res = E_FAIL;
+
+ RegCloseKey(subKey);
+ }
+ else
+ res = E_FAIL;
+
+ /* create the helpdir subkey */
+ if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
+ KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
+ {
+ BOOL freeHelpDir = FALSE;
+ OLECHAR* pIndexStr;
+
+ /* if we created a new key, and helpDir was null, set the helpdir
+ to the directory which contains the typelib. However,
+ if we just opened an existing key, we leave the helpdir alone */
+ if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
+ szHelpDir = SysAllocString(szFullPath);
+ pIndexStr = strrchrW(szHelpDir, '\\');
+ if (pIndexStr) {
+ *pIndexStr = 0;
+ }
+ freeHelpDir = TRUE;
+ }
+
+ /* if we have an szHelpDir, set it! */
+ if (szHelpDir != NULL) {
+ if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
+ (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
+ res = E_FAIL;
+ }
+ }
+
+ /* tidy up */
+ if (freeHelpDir) SysFreeString(szHelpDir);
+ RegCloseKey(subKey);
+
+ } else {
+ res = E_FAIL;
+ }
+
+ RegCloseKey(key);
+ }
+ else
+ res = E_FAIL;
+
+ /* register OLE Automation-compatible interfaces for this typelib */
+ types = ITypeLib_GetTypeInfoCount(ptlib);
+ for (tidx=0; tidx<types; tidx++) {
+ if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
+ LPOLESTR name = NULL;
+ ITypeInfo *tinfo = NULL;
+
+ ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
+
+ switch (kind) {
+ case TKIND_INTERFACE:
+ TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
+ ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
+ break;
+
+ case TKIND_DISPATCH:
+ TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
+ ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
+ break;
+
+ default:
+ TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
+ break;
+ }
+
+ if (tinfo) {
+ TYPEATTR *tattr = NULL;
+ ITypeInfo_GetTypeAttr(tinfo, &tattr);
+
+ if (tattr) {
+ TRACE_(typelib)("guid=%s, flags=%04x (",
+ debugstr_guid(&tattr->guid),
+ tattr->wTypeFlags);
+
+ if (TRACE_ON(typelib)) {
+#define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
+ XX(FAPPOBJECT);
+ XX(FCANCREATE);
+ XX(FLICENSED);
+ XX(FPREDECLID);
+ XX(FHIDDEN);
+ XX(FCONTROL);
+ XX(FDUAL);
+ XX(FNONEXTENSIBLE);
+ XX(FOLEAUTOMATION);
+ XX(FRESTRICTED);
+ XX(FAGGREGATABLE);
+ XX(FREPLACEABLE);
+ XX(FDISPATCHABLE);
+ XX(FREVERSEBIND);
+ XX(FPROXY);
+#undef XX
+ MESSAGE("\n");
+ }
+
+ if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
+ {
+ /* register interface<->typelib coupling */
+ get_interface_key( &tattr->guid, keyName );
+ if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
+ KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
+ {
+ if (name)
+ RegSetValueExW(key, NULL, 0, REG_SZ,
+ (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
+
+ if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
+ KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
+ RegSetValueExW(subKey, NULL, 0, REG_SZ,
+ (BYTE*)PSOA, sizeof PSOA);
+ RegCloseKey(subKey);
+ }
+
+ if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
+ KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
+ RegSetValueExW(subKey, NULL, 0, REG_SZ,
+ (BYTE*)PSOA, sizeof PSOA);
+ RegCloseKey(subKey);
+ }
+
+ if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
+ KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
+ {
+ WCHAR buffer[40];
+ static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
+ static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
+
+ StringFromGUID2(&attr->guid, buffer, 40);
+ RegSetValueExW(subKey, NULL, 0, REG_SZ,
+ (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
+ sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
+ RegSetValueExW(subKey, VersionW, 0, REG_SZ,
+ (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
+ RegCloseKey(subKey);
+ }
+
+ RegCloseKey(key);
+ }
+ }
+
+ ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
+ }
+
+ ITypeInfo_Release(tinfo);
+ }
+
+ SysFreeString(name);
+ }
+ }
+
+ ITypeLib_ReleaseTLibAttr(ptlib, attr);
+
+ return res;
+}
+
+
+/******************************************************************************
+ * UnRegisterTypeLib [OLEAUT32.186]
+ * Removes information about a type library from the System Registry
+ * NOTES
+ *
+ * RETURNS
+ * Success: S_OK
+ * Failure: Status
+ */
+HRESULT WINAPI UnRegisterTypeLib(
+ REFGUID libid, /* [in] Guid of the library */
+ WORD wVerMajor, /* [in] major version */
+ WORD wVerMinor, /* [in] minor version */
+ LCID lcid, /* [in] locale id */
+ SYSKIND syskind)
+{
+ BSTR tlibPath = NULL;
+ DWORD tmpLength;
+ WCHAR keyName[60];
+ WCHAR subKeyName[50];
+ int result = S_OK;
+ DWORD i = 0;
+ BOOL deleteOtherStuff;
+ HKEY key = NULL;
+ HKEY subKey = NULL;
+ TYPEATTR* typeAttr = NULL;
+ TYPEKIND kind;
+ ITypeInfo* typeInfo = NULL;
+ ITypeLib* typeLib = NULL;
+ int numTypes;
+
+ TRACE("(IID: %s): stub\n",debugstr_guid(libid));
+
+ /* Create the path to the key */
+ get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
+
+ if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
+ {
+ TRACE("Unsupported syskind %i\n", syskind);
+ result = E_INVALIDARG;
+ goto end;
+ }
+
+ /* get the path to the typelib on disk */
+ if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
+ result = E_INVALIDARG;
+ goto end;
+ }
+
+ /* Try and open the key to the type library. */
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
+ result = E_INVALIDARG;
+ goto end;
+ }
+
+ /* Try and load the type library */
+ if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
+ result = TYPE_E_INVALIDSTATE;
+ goto end;
+ }
+
+ /* remove any types registered with this typelib */
+ numTypes = ITypeLib_GetTypeInfoCount(typeLib);
+ for (i=0; i<numTypes; i++) {
+ /* get the kind of type */
+ if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
+ goto enddeleteloop;
+ }
+
+ /* skip non-interfaces, and get type info for the type */
+ if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
+ goto enddeleteloop;
+ }
+ if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
+ goto enddeleteloop;
+ }
+ if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
+ goto enddeleteloop;
+ }
+
+ /* the path to the type */
+ get_interface_key( &typeAttr->guid, subKeyName );
+
+ /* Delete its bits */
+ if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
+ goto enddeleteloop;
+ }
+ RegDeleteKeyW(subKey, ProxyStubClsidW);
+ RegDeleteKeyW(subKey, ProxyStubClsid32W);
+ RegDeleteKeyW(subKey, TypeLibW);
+ RegCloseKey(subKey);
+ subKey = NULL;
+ RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
+
+enddeleteloop:
+ if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
+ typeAttr = NULL;
+ if (typeInfo) ITypeInfo_Release(typeInfo);
+ typeInfo = NULL;
+ }
+
+ /* Now, delete the type library path subkey */
+ get_lcid_subkey( lcid, syskind, subKeyName );
+ RegDeleteKeyW(key, subKeyName);
+ *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
+ RegDeleteKeyW(key, subKeyName);
+
+ /* check if there is anything besides the FLAGS/HELPDIR keys.
+ If there is, we don't delete them */
+ tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
+ deleteOtherStuff = TRUE;
+ i = 0;
+ while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
+ tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
+
+ /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
+ if (!strcmpW(subKeyName, FLAGSW)) continue;
+ if (!strcmpW(subKeyName, HELPDIRW)) continue;
+ deleteOtherStuff = FALSE;
+ break;
+ }
+
+ /* only delete the other parts of the key if we're absolutely sure */
+ if (deleteOtherStuff) {
+ RegDeleteKeyW(key, FLAGSW);
+ RegDeleteKeyW(key, HELPDIRW);
+ RegCloseKey(key);
+ key = NULL;
+
+ RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
+ *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
+ RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
+ }
+
+end:
+ if (tlibPath) SysFreeString(tlibPath);
+ if (typeLib) ITypeLib_Release(typeLib);
+ if (subKey) RegCloseKey(subKey);
+ if (key) RegCloseKey(key);
+ return result;
+}
+
+/*======================= ITypeLib implementation =======================*/
+
+typedef struct tagTLBCustData
+{
+ GUID guid;
+ VARIANT data;
+ struct tagTLBCustData* next;
+} TLBCustData;
+
+/* data structure for import typelibs */
+typedef struct tagTLBImpLib
+{
+ int offset; /* offset in the file (MSFT)
+ offset in nametable (SLTG)
+ just used to identify library while reading
+ data from file */
+ GUID guid; /* libid */
+ BSTR name; /* name */
+
+ LCID lcid; /* lcid of imported typelib */
+
+ WORD wVersionMajor; /* major version number */
+ WORD wVersionMinor; /* minor version number */
+
+ struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
+ NULL if not yet loaded */
+ struct tagTLBImpLib * next;
+} TLBImpLib;
+
+/* internal ITypeLib data */
+typedef struct tagITypeLibImpl
+{
+ const ITypeLib2Vtbl *lpVtbl;
+ const ITypeCompVtbl *lpVtblTypeComp;
+ LONG ref;
+ TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
+
+ /* strings can be stored in tlb as multibyte strings BUT they are *always*
+ * exported to the application as a UNICODE string.
+ */
+ BSTR Name;
+ BSTR DocString;
+ BSTR HelpFile;
+ BSTR HelpStringDll;
+ unsigned long dwHelpContext;
+ int TypeInfoCount; /* nr of typeinfo's in librarry */
+ struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
+ int ctCustData; /* number of items in cust data list */
+ TLBCustData * pCustData; /* linked list to cust data */
+ TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
+ TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
+ libary. Only used while read MSFT
+ typelibs */
+
+ /* typelibs are cached, keyed by path and index, so store the linked list info within them */
+ struct tagITypeLibImpl *next, *prev;
+ WCHAR *path;
+ INT index;
+} ITypeLibImpl;
+
+static const ITypeLib2Vtbl tlbvt;
+static const ITypeCompVtbl tlbtcvt;
+
+static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
+{
+ return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
+}
+
+/* ITypeLib methods */
+static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
+static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
+
+/*======================= ITypeInfo implementation =======================*/
+
+/* data for referenced types */
+typedef struct tagTLBRefType
+{
+ INT index; /* Type index for internal ref or for external ref
+ it the format is SLTG. -2 indicates to
+ use guid */
+
+ GUID guid; /* guid of the referenced type */
+ /* if index == TLB_REF_USE_GUID */
+
+ HREFTYPE reference; /* The href of this ref */
+ TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
+ TLB_REF_INTERNAL for internal refs
+ TLB_REF_NOT_FOUND for broken refs */
+
+ struct tagTLBRefType * next;
+} TLBRefType;
+
+#define TLB_REF_USE_GUID -2
+
+#define TLB_REF_INTERNAL (void*)-2
+#define TLB_REF_NOT_FOUND (void*)-1
+
+/* internal Parameter data */
+typedef struct tagTLBParDesc
+{
+ BSTR Name;
+ int ctCustData;
+ TLBCustData * pCustData; /* linked list to cust data */
+} TLBParDesc;
+
+/* internal Function data */
+typedef struct tagTLBFuncDesc
+{
+ FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
+ BSTR Name; /* the name of this function */
+ TLBParDesc *pParamDesc; /* array with param names and custom data */
+ int helpcontext;
+ int HelpStringContext;
+ BSTR HelpString;
+ BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
+ int ctCustData;
+ TLBCustData * pCustData; /* linked list to cust data; */
+ struct tagTLBFuncDesc * next;
+} TLBFuncDesc;
+
+/* internal Variable data */
+typedef struct tagTLBVarDesc
+{
+ VARDESC vardesc; /* lots of info on the variable and its attributes. */
+ BSTR Name; /* the name of this variable */
+ int HelpContext;
+ int HelpStringContext; /* FIXME: where? */
+ BSTR HelpString;
+ int ctCustData;
+ TLBCustData * pCustData;/* linked list to cust data; */
+ struct tagTLBVarDesc * next;
+} TLBVarDesc;
+
+/* internal implemented interface data */
+typedef struct tagTLBImplType
+{
+ HREFTYPE hRef; /* hRef of interface */
+ int implflags; /* IMPLFLAG_*s */
+ int ctCustData;
+ TLBCustData * pCustData;/* linked list to custom data; */
+ struct tagTLBImplType *next;
+} TLBImplType;
+
+/* internal TypeInfo data */
+typedef struct tagITypeInfoImpl
+{
+ const ITypeInfo2Vtbl *lpVtbl;
+ const ITypeCompVtbl *lpVtblTypeComp;
+ LONG ref;
+ TYPEATTR TypeAttr ; /* _lots_ of type information. */
+ ITypeLibImpl * pTypeLib; /* back pointer to typelib */
+ int index; /* index in this typelib; */
+ HREFTYPE hreftype; /* hreftype for app object binding */
+ /* type libs seem to store the doc strings in ascii
+ * so why should we do it in unicode?
+ */
+ BSTR Name;
+ BSTR DocString;
+ BSTR DllName;
+ unsigned long dwHelpContext;
+ unsigned long dwHelpStringContext;
+
+ /* functions */
+ TLBFuncDesc * funclist; /* linked list with function descriptions */
+
+ /* variables */
+ TLBVarDesc * varlist; /* linked list with variable descriptions */
+
+ /* Implemented Interfaces */
+ TLBImplType * impltypelist;
+
+ TLBRefType * reflist;
+ int ctCustData;
+ TLBCustData * pCustData; /* linked list to cust data; */
+ struct tagITypeInfoImpl * next;
+} ITypeInfoImpl;
+
+static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
+{
+ return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
+}
+
+static const ITypeInfo2Vtbl tinfvt;
+static const ITypeCompVtbl tcompvt;
+
+static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
+
+typedef struct tagTLBContext
+{
+ unsigned int oStart; /* start of TLB in file */
+ unsigned int pos; /* current pos */
+ unsigned int length; /* total length */
+ void *mapping; /* memory mapping */
+ MSFT_SegDir * pTblDir;
+ ITypeLibImpl* pLibInfo;
+} TLBContext;
+
+
+static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
+
+/*
+ debug
+*/
+static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
+ if (pTD->vt & VT_RESERVED)
+ szVarType += strlen(strcpy(szVarType, "reserved | "));
+ if (pTD->vt & VT_BYREF)
+ szVarType += strlen(strcpy(szVarType, "ref to "));
+ if (pTD->vt & VT_ARRAY)
+ szVarType += strlen(strcpy(szVarType, "array of "));
+ if (pTD->vt & VT_VECTOR)
+ szVarType += strlen(strcpy(szVarType, "vector of "));
+ switch(pTD->vt & VT_TYPEMASK) {
+ case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
+ case VT_I2: sprintf(szVarType, "VT_I2"); break;
+ case VT_I4: sprintf(szVarType, "VT_I4"); break;
+ case VT_R4: sprintf(szVarType, "VT_R4"); break;
+ case VT_R8: sprintf(szVarType, "VT_R8"); break;
+ case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
+ case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
+ case VT_CY: sprintf(szVarType, "VT_CY"); break;
+ case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
+ case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
+ case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
+ case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
+ case VT_I1: sprintf(szVarType, "VT_I1"); break;
+ case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
+ case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
+ case VT_INT: sprintf(szVarType, "VT_INT"); break;
+ case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
+ case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
+ case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
+ case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
+ case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
+ pTD->u.hreftype); break;
+ case VT_PTR: sprintf(szVarType, "ptr to ");
+ dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
+ break;
+ case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
+ dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
+ break;
+ case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
+ pTD->u.lpadesc->cDims); /* FIXME print out sizes */
+ dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
+ break;
+
+ default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
+ }
+}
+
+static void dump_ELEMDESC(const ELEMDESC *edesc) {
+ char buf[200];
+ USHORT flags = edesc->u.paramdesc.wParamFlags;
+ dump_TypeDesc(&edesc->tdesc,buf);
+ MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
+ MESSAGE("\t\tu.paramdesc.wParamFlags");
+ if (!flags) MESSAGE(" PARAMFLAGS_NONE");
+ if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
+ if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
+ if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
+ if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
+ if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
+ if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
+ if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
+ MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
+}
+static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
+ int i;
+ MESSAGE("memid is %08lx\n",funcdesc->memid);
+ for (i=0;i<funcdesc->cParams;i++) {
+ MESSAGE("Param %d:\n",i);
+ dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
+ }
+ MESSAGE("\tfunckind: %d (",funcdesc->funckind);
+ switch (funcdesc->funckind) {
+ case FUNC_VIRTUAL: MESSAGE("virtual");break;
+ case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
+ case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
+ case FUNC_STATIC: MESSAGE("static");break;
+ case FUNC_DISPATCH: MESSAGE("dispatch");break;
+ default: MESSAGE("unknown");break;
+ }
+ MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
+ switch (funcdesc->invkind) {
+ case INVOKE_FUNC: MESSAGE("func");break;
+ case INVOKE_PROPERTYGET: MESSAGE("property get");break;
+ case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
+ case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
+ }
+ MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
+ switch (funcdesc->callconv) {
+ case CC_CDECL: MESSAGE("cdecl");break;
+ case CC_PASCAL: MESSAGE("pascal");break;
+ case CC_STDCALL: MESSAGE("stdcall");break;
+ case CC_SYSCALL: MESSAGE("syscall");break;
+ default:break;
+ }
+ MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
+ MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
+ MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
+
+ MESSAGE("\telemdescFunc (return value type):\n");
+ dump_ELEMDESC(&funcdesc->elemdescFunc);
+}
+
+static const char * typekind_desc[] =
+{
+ "TKIND_ENUM",
+ "TKIND_RECORD",
+ "TKIND_MODULE",
+ "TKIND_INTERFACE",
+ "TKIND_DISPATCH",
+ "TKIND_COCLASS",
+ "TKIND_ALIAS",
+ "TKIND_UNION",
+ "TKIND_MAX"
+};
+
+static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
+{
+ int i;
+ if (!TRACE_ON(typelib))
+ return;
+ MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
+ for (i=0;i<pfd->funcdesc.cParams;i++)
+ MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
+
+
+ dump_FUNCDESC(&(pfd->funcdesc));
+
+ MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
+ MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
+}
+static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
+{
+ while (pfd)
+ {
+ dump_TLBFuncDescOne(pfd);
+ pfd = pfd->next;
+ };
+}
+static void dump_TLBVarDesc(const TLBVarDesc * pvd)
+{
+ while (pvd)
+ {
+ TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
+ pvd = pvd->next;
+ };
+}
+
+static void dump_TLBImpLib(const TLBImpLib *import)
+{
+ TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
+ debugstr_w(import->name));
+ TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
+ import->wVersionMinor, import->lcid, import->offset);
+}
+
+static void dump_TLBRefType(const TLBRefType * prt)
+{
+ while (prt)
+ {
+ TRACE_(typelib)("href:0x%08lx\n", prt->reference);
+ if(prt->index == -1)
+ TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
+ else
+ TRACE_(typelib)("type no: %d\n", prt->index);
+
+ if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
+ prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
+ TRACE_(typelib)("in lib\n");
+ dump_TLBImpLib(prt->pImpTLInfo);
+ }
+ prt = prt->next;
+ };
+}
+
+static void dump_TLBImplType(const TLBImplType * impl)
+{
+ while (impl) {
+ TRACE_(typelib)(
+ "implementing/inheriting interface hRef = %lx implflags %x\n",
+ impl->hRef, impl->implflags);
+ impl = impl->next;
+ }
+}
+
+void dump_Variant(const VARIANT * pvar)
+{
+ SYSTEMTIME st;
+
+ TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
+
+ if (pvar)
+ {
+ if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
+ V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
+ {
+ TRACE(",%p", V_BYREF(pvar));
+ }
+ else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
+ {
+ TRACE(",FIXME");
+ }
+ else switch (V_TYPE(pvar))
+ {
+ case VT_I1: TRACE(",%d", V_I1(pvar)); break;
+ case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
+ case VT_I2: TRACE(",%d", V_I2(pvar)); break;
+ case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
+ case VT_INT:
+ case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
+ case VT_UINT:
+ case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
+ case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
+ (ULONG)(V_I8(pvar) & 0xffffffff)); break;
+ case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
+ (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
+ case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
+ case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
+ case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
+ case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
+ case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
+ V_CY(pvar).s.Lo); break;
+ case VT_DATE:
+ if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
+ TRACE(",<invalid>");
+ else
+ TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
+ st.wHour, st.wMinute, st.wSecond);
+ break;
+ case VT_ERROR:
+ case VT_VOID:
+ case VT_USERDEFINED:
+ case VT_EMPTY:
+ case VT_NULL: break;
+ default: TRACE(",?"); break;
+ }
+ }
+ TRACE("}\n");
+}
+
+static void dump_DispParms(const DISPPARAMS * pdp)
+{
+ int index = 0;
+
+ TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
+
+ while (index < pdp->cArgs)
+ {
+ dump_Variant( &pdp->rgvarg[index] );
+ ++index;
+ }
+}
+
+static void dump_TypeInfo(const ITypeInfoImpl * pty)
+{
+ TRACE("%p ref=%lu\n", pty, pty->ref);
+ TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
+ TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
+ TRACE("fct:%u var:%u impl:%u\n",
+ pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
+ TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
+ TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
+ if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
+ dump_TLBFuncDesc(pty->funclist);
+ dump_TLBVarDesc(pty->varlist);
+ dump_TLBImplType(pty->impltypelist);
+}
+
+static void dump_VARDESC(const VARDESC *v)
+{
+ MESSAGE("memid %ld\n",v->memid);
+ MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
+ MESSAGE("oInst %ld\n",v->u.oInst);
+ dump_ELEMDESC(&(v->elemdescVar));
+ MESSAGE("wVarFlags %x\n",v->wVarFlags);
+ MESSAGE("varkind %d\n",v->varkind);
+}
+
+static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
+{
+ /* VT_LPWSTR is largest type that */
+ /* may appear in type description*/
+ {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
+ {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
+ {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
+ {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
+ {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
+ {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
+ {{0},30},{{0},31}
+};
+
+static void TLB_abort(void)
+{
+ DebugBreak();
+}
+static void * TLB_Alloc(unsigned size)
+{
+ void * ret;
+ if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
+ /* FIXME */
+ ERR("cannot allocate memory\n");
+ }
+ return ret;
+}
+
+static void TLB_Free(void * ptr)
+{
+ HeapFree(GetProcessHeap(), 0, ptr);
+}
+
+/* returns the size required for a deep copy of a typedesc into a
+ * flat buffer */
+static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
+{
+ SIZE_T size = 0;
+
+ if (alloc_initial_space)
+ size += sizeof(TYPEDESC);
+
+ switch (tdesc->vt)
+ {
+ case VT_PTR:
+ case VT_SAFEARRAY:
+ size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
+ break;
+ case VT_CARRAY:
+ size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
+ size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
+ break;
+ }
+ return size;
+}
+
+/* deep copy a typedesc into a flat buffer */
+static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
+{
+ if (!dest)
+ {
+ dest = buffer;
+ buffer = (char *)buffer + sizeof(TYPEDESC);
+ }
+
+ *dest = *src;
+
+ switch (src->vt)
+ {
+ case VT_PTR:
+ case VT_SAFEARRAY:
+ dest->u.lptdesc = buffer;
+ buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
+ break;
+ case VT_CARRAY:
+ dest->u.lpadesc = buffer;
+ memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
+ buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
+ buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
+ break;
+ }
+ return buffer;
+}
+
+/**********************************************************************
+ *
+ * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
+ */
+/* read function */
+static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
+{
+ TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
+ pcx->pos, count, pcx->oStart, pcx->length, where);
+
+ if (where != DO_NOT_SEEK)
+ {
+ where += pcx->oStart;
+ if (where > pcx->length)
+ {
+ /* FIXME */
+ ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
+ TLB_abort();
+ }
+ pcx->pos = where;
+ }
+ if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
+ memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
+ pcx->pos += count;
+ return count;
+}
+
+static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
+ long where )
+{
+ DWORD ret;
+
+ ret = MSFT_Read(buffer, count, pcx, where);
+ FromLEDWords(buffer, ret);
+
+ return ret;
+}
+
+static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
+ long where )
+{
+ DWORD ret;
+
+ ret = MSFT_Read(buffer, count, pcx, where);
+ FromLEWords(buffer, ret);
+
+ return ret;
+}
+
+static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
+{
+ if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
+ memset(pGuid,0, sizeof(GUID));
+ return;
+ }
+ MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
+ pGuid->Data1 = FromLEDWord(pGuid->Data1);
+ pGuid->Data2 = FromLEWord(pGuid->Data2);
+ pGuid->Data3 = FromLEWord(pGuid->Data3);
+ TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
+}
+
+static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
+{
+ MSFT_NameIntro niName;
+
+ if (offset < 0)
+ {
+ ERR_(typelib)("bad offset %d\n", offset);
+ return -1;
+ }
+
+ MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
+ pcx->pTblDir->pNametab.offset+offset);
+
+ return niName.hreftype;
+}
+
+static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
+{
+ char * name;
+ MSFT_NameIntro niName;
+ int lengthInChars;
+ WCHAR* pwstring = NULL;
+ BSTR bstrName = NULL;
+
+ if (offset < 0)
+ {
+ ERR_(typelib)("bad offset %d\n", offset);
+ return NULL;
+ }
+ MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
+ pcx->pTblDir->pNametab.offset+offset);
+ niName.namelen &= 0xFF; /* FIXME: correct ? */
+ name=TLB_Alloc((niName.namelen & 0xff) +1);
+ MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
+ name[niName.namelen & 0xff]='\0';
+
+ lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
+ name, -1, NULL, 0);
+
+ /* no invalid characters in string */
+ if (lengthInChars)
+ {
+ pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
+
+ /* don't check for invalid character since this has been done previously */
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
+
+ bstrName = SysAllocStringLen(pwstring, lengthInChars);
+ lengthInChars = SysStringLen(bstrName);
+ HeapFree(GetProcessHeap(), 0, pwstring);
+ }
+
+ TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
+ return bstrName;
+}
+
+static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
+{
+ char * string;
+ INT16 length;
+ int lengthInChars;
+ BSTR bstr = NULL;
+
+ if(offset<0) return NULL;
+ MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
+ if(length <= 0) return 0;
+ string=TLB_Alloc(length +1);
+ MSFT_Read(string, length, pcx, DO_NOT_SEEK);
+ string[length]='\0';
+
+ lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
+ string, -1, NULL, 0);
+
+ /* no invalid characters in string */
+ if (lengthInChars)
+ {
+ WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
+
+ /* don't check for invalid character since this has been done previously */
+ MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
+
+ bstr = SysAllocStringLen(pwstring, lengthInChars);
+ lengthInChars = SysStringLen(bstr);
+ HeapFree(GetProcessHeap(), 0, pwstring);
+ }
+
+ TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
+ return bstr;
+}
+/*
+ * read a value and fill a VARIANT structure
+ */
+static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
+{
+ int size;
+
+ TRACE_(typelib)("\n");
+
+ if(offset <0) { /* data are packed in here */
+ V_VT(pVar) = (offset & 0x7c000000 )>> 26;
+ V_I4(pVar) = offset & 0x3ffffff;
+ return;
+ }
+ MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
+ pcx->pTblDir->pCustData.offset + offset );
+ TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
+ switch (V_VT(pVar)){
+ case VT_EMPTY: /* FIXME: is this right? */
+ case VT_NULL: /* FIXME: is this right? */
+ case VT_I2 : /* this should not happen */
+ case VT_I4 :
+ case VT_R4 :
+ case VT_ERROR :
+ case VT_BOOL :
+ case VT_I1 :
+ case VT_UI1 :
+ case VT_UI2 :
+ case VT_UI4 :
+ case VT_INT :
+ case VT_UINT :
+ case VT_VOID : /* FIXME: is this right? */
+ case VT_HRESULT :
+ size=4; break;
+ case VT_R8 :
+ case VT_CY :
+ case VT_DATE :
+ case VT_I8 :
+ case VT_UI8 :
+ case VT_DECIMAL : /* FIXME: is this right? */
+ case VT_FILETIME :
+ size=8;break;
+ /* pointer types with known behaviour */
+ case VT_BSTR :{
+ char * ptr;
+ MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
+ if(size < 0) {
+ FIXME("BSTR length = %d?\n", size);
+ } else {
+ ptr=TLB_Alloc(size);/* allocate temp buffer */
+ MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
+ V_BSTR(pVar)=SysAllocStringLen(NULL,size);
+ /* FIXME: do we need a AtoW conversion here? */
+ V_UNION(pVar, bstrVal[size])=L'\0';
+ while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
+ TLB_Free(ptr);
+ }
+ }
+ size=-4; break;
+ /* FIXME: this will not work AT ALL when the variant contains a pointer */
+ case VT_DISPATCH :
+ case VT_VARIANT :
+ case VT_UNKNOWN :
+ case VT_PTR :
+ case VT_SAFEARRAY :
+ case VT_CARRAY :
+ case VT_USERDEFINED :
+ case VT_LPSTR :
+ case VT_LPWSTR :
+ case VT_BLOB :
+ case VT_STREAM :
+ case VT_STORAGE :
+ case VT_STREAMED_OBJECT :
+ case VT_STORED_OBJECT :
+ case VT_BLOB_OBJECT :
+ case VT_CF :
+ case VT_CLSID :
+ default:
+ size=0;
+ FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
+ V_VT(pVar));
+ }
+
+ if(size>0) /* (big|small) endian correct? */
+ MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
+ return;
+}
+/*
+ * create a linked list with custom data
+ */
+static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
+{
+ MSFT_CDGuid entry;
+ TLBCustData* pNew;
+ int count=0;
+
+ TRACE_(typelib)("\n");
+
+ while(offset >=0){
+ count++;
+ pNew=TLB_Alloc(sizeof(TLBCustData));
+ MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
+ MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
+ MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
+ /* add new custom data at head of the list */
+ pNew->next=*ppCustData;
+ *ppCustData=pNew;
+ offset = entry.next;
+ }
+ return count;
+}
+
+static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
+ ITypeInfoImpl *pTI)
+{
+ if(type <0)
+ pTd->vt=type & VT_TYPEMASK;
+ else
+ *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
+
+ if(pTd->vt == VT_USERDEFINED)
+ MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
+
+ TRACE_(typelib)("vt type = %X\n", pTd->vt);
+}
+
+static void
+MSFT_DoFuncs(TLBContext* pcx,
+ ITypeInfoImpl* pTI,
+ int cFuncs,
+ int cVars,
+ int offset,
+ TLBFuncDesc** pptfd)
+{
+ /*
+ * member information is stored in a data structure at offset
+ * indicated by the memoffset field of the typeinfo structure
+ * There are several distinctive parts.
+ * The first part starts with a field that holds the total length
+ * of this (first) part excluding this field. Then follow the records,
+ * for each member there is one record.
+ *
+ * The first entry is always the length of the record (including this
+ * length word).
+ * The rest of the record depends on the type of the member. If there is
+ * a field indicating the member type (function, variable, interface, etc)
+ * I have not found it yet. At this time we depend on the information
+ * in the type info and the usual order how things are stored.
+ *
+ * Second follows an array sized nrMEM*sizeof(INT) with a member id
+ * for each member;
+ *
+ * Third is an equal sized array with file offsets to the name entry
+ * of each member.
+ *
+ * The fourth and last (?) part is an array with offsets to the records
+ * in the first part of this file segment.
+ */
+
+ int infolen, nameoffset, reclength, nrattributes, i;
+ int recoffset = offset + sizeof(INT);
+
+ char recbuf[512];
+ MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
+ TLBFuncDesc *ptfd_prev = NULL;
+
+ TRACE_(typelib)("\n");
+
+ MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
+
+ for ( i = 0; i < cFuncs ; i++ )
+ {
+ *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
+
+ /* name, eventually add to a hash table */
+ MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
+ offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
+
+ /* nameoffset is sometimes -1 on the second half of a propget/propput
+ * pair of functions */
+ if ((nameoffset == -1) && (i > 0))
+ (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
+ else
+ (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
+
+ /* read the function information record */
+ MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
+
+ reclength &= 0x1ff;
+
+ MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
+
+ /* do the attributes */
+ nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
+ / sizeof(int);
+
+ if ( nrattributes > 0 )
+ {
+ (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
+
+ if ( nrattributes > 1 )
+ {
+ (*pptfd)->HelpString = MSFT_ReadString(pcx,
+ pFuncRec->OptAttr[1]) ;
+
+ if ( nrattributes > 2 )
+ {
+ if ( pFuncRec->FKCCIC & 0x2000 )
+ {
+ (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
+ }
+ else
+ {
+ (*pptfd)->Entry = MSFT_ReadString(pcx,
+ pFuncRec->OptAttr[2]);
+ }
+ if( nrattributes > 5 )
+ {
+ (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
+
+ if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
+ {
+ MSFT_CustData(pcx,
+ pFuncRec->OptAttr[6],
+ &(*pptfd)->pCustData);
+ }
+ }
+ }
+ }
+ }
+
+ /* fill the FuncDesc Structure */
+ MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
+ offset + infolen + ( i + 1) * sizeof(INT));
+
+ (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
+ (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
+ (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
+ (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
+ (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
+ (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
+ (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
+
+ MSFT_GetTdesc(pcx,
+ pFuncRec->DataType,
+ &(*pptfd)->funcdesc.elemdescFunc.tdesc,
+ pTI);
+
+ /* do the parameters/arguments */
+ if(pFuncRec->nrargs)
+ {
+ int j = 0;
+ MSFT_ParameterInfo paraminfo;
+
+ (*pptfd)->funcdesc.lprgelemdescParam =
+ TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
+
+ (*pptfd)->pParamDesc =
+ TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
+
+ MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
+ recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
+
+ for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
+ {
+ TYPEDESC *lpArgTypeDesc;
+ ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
+
+ MSFT_GetTdesc(pcx,
+ paraminfo.DataType,
+ &elemdesc->tdesc,
+ pTI);
+
+ elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
+
+ /* name */
+ if (paraminfo.oName == -1)
+ /* this occurs for [propput] or [propget] methods, so
+ * we should just set the name of the parameter to the
+ * name of the method. */
+ (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
+ else
+ (*pptfd)->pParamDesc[j].Name =
+ MSFT_ReadName( pcx, paraminfo.oName );
+ TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
+
+ lpArgTypeDesc = &elemdesc->tdesc;
+
+ /* resolve referenced type if any */
+ while ( lpArgTypeDesc != NULL )
+ {
+ switch ( lpArgTypeDesc->vt )
+ {
+ case VT_PTR:
+ lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
+ break;
+
+ case VT_CARRAY:
+ lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
+ break;
+
+ case VT_USERDEFINED:
+ MSFT_DoRefType(pcx, pTI,
+ lpArgTypeDesc->u.hreftype);
+
+ lpArgTypeDesc = NULL;
+ break;
+
+ default:
+ lpArgTypeDesc = NULL;
+ }
+ }
+
+ /* default value */
+ if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
+ (pFuncRec->FKCCIC & 0x1000) )
+ {
+ INT* pInt = (INT *)((char *)pFuncRec +
+ reclength -
+ (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
+
+ PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
+
+ pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
+ pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
+
+ MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
+ pInt[j], pcx);
+ }
+ else
+ elemdesc->u.paramdesc.pparamdescex = NULL;
+ /* custom info */
+ if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
+ {
+ MSFT_CustData(pcx,
+ pFuncRec->OptAttr[7+j],
+ &(*pptfd)->pParamDesc[j].pCustData);
+ }
+
+ /* SEEK value = jump to offset,
+ * from there jump to the end of record,
+ * go back by (j-1) arguments
+ */
+ MSFT_ReadLEDWords( ¶minfo ,
+ sizeof(MSFT_ParameterInfo), pcx,
+ recoffset + reclength - ((pFuncRec->nrargs - j - 1)
+ * sizeof(MSFT_ParameterInfo)));
+ }
+ }
+
+ /* scode is not used: archaic win16 stuff FIXME: right? */
+ (*pptfd)->funcdesc.cScodes = 0 ;
+ (*pptfd)->funcdesc.lprgscode = NULL ;
+
+ ptfd_prev = *pptfd;
+ pptfd = & ((*pptfd)->next);
+ recoffset += reclength;
+ }
+}
+
+static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
+ int cVars, int offset, TLBVarDesc ** pptvd)
+{
+ int infolen, nameoffset, reclength;
+ char recbuf[256];
+ MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
+ int i;
+ int recoffset;
+
+ TRACE_(typelib)("\n");
+
+ MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
+ MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
+ ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
+ recoffset += offset+sizeof(INT);
+ for(i=0;i<cVars;i++){
+ *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
+ /* name, eventually add to a hash table */
+ MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
+ offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
+ (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
+ /* read the variable information record */
+ MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
+ reclength &=0xff;
+ MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
+ /* Optional data */
+ if(reclength >(6*sizeof(INT)) )
+ (*pptvd)->HelpContext=pVarRec->HelpContext;
+ if(reclength >(7*sizeof(INT)) )
+ (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
+ if(reclength >(8*sizeof(INT)) )
+ if(reclength >(9*sizeof(INT)) )
+ (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
+ /* fill the VarDesc Structure */
+ MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
+ offset + infolen + ( i + 1) * sizeof(INT));
+ (*pptvd)->vardesc.varkind = pVarRec->VarKind;
+ (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
+ MSFT_GetTdesc(pcx, pVarRec->DataType,
+ &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
+/* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
+ if(pVarRec->VarKind == VAR_CONST ){
+ (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
+ MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
+ pVarRec->OffsValue, pcx);
+ } else
+ (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
+ pptvd=&((*pptvd)->next);
+ recoffset += reclength;
+ }
+}
+/* fill in data for a hreftype (offset). When the referenced type is contained
+ * in the typelib, it's just an (file) offset in the type info base dir.
+ * If comes from import, it's an offset+1 in the ImpInfo table
+ * */
+static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
+ int offset)
+{
+ int j;
+ TLBRefType **ppRefType = &pTI->reflist;
+
+ TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
+
+ while(*ppRefType) {
+ if((*ppRefType)->reference == offset)
+ return;
+ ppRefType = &(*ppRefType)->next;
+ }
+
+ *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(**ppRefType));
+
+ if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
+ /* external typelib */
+ MSFT_ImpInfo impinfo;
+ TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
+
+ TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
+
+ MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
+ pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
+ for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
+ if(pImpLib->offset==impinfo.oImpFile) break;
+ pImpLib=pImpLib->next;
+ }
+ if(pImpLib){
+ (*ppRefType)->reference=offset;
+ (*ppRefType)->pImpTLInfo = pImpLib;
+ if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
+ MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
+ (*ppRefType)->index = TLB_REF_USE_GUID;
+ } else
+ (*ppRefType)->index = impinfo.oGuid;
+ }else{
+ ERR("Cannot find a reference\n");
+ (*ppRefType)->reference=-1;
+ (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
+ }
+ }else{
+ /* in this typelib */
+ (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
+ (*ppRefType)->reference=offset;
+ (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
+ }
+}
+
+/* process Implemented Interfaces of a com class */
+static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
+ int offset)
+{
+ int i;
+ MSFT_RefRecord refrec;
+ TLBImplType **ppImpl = &pTI->impltypelist;
+
+ TRACE_(typelib)("\n");
+
+ for(i=0;i<count;i++){
+ if(offset<0) break; /* paranoia */
+ *ppImpl=TLB_Alloc(sizeof(**ppImpl));
+ MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
+ MSFT_DoRefType(pcx, pTI, refrec.reftype);
+ (*ppImpl)->hRef = refrec.reftype;
+ (*ppImpl)->implflags=refrec.flags;
+ (*ppImpl)->ctCustData=
+ MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
+ offset=refrec.onext;
+ ppImpl=&((*ppImpl)->next);
+ }
+}
+/*
+ * process a typeinfo record
+ */
+static ITypeInfoImpl * MSFT_DoTypeInfo(
+ TLBContext *pcx,
+ int count,
+ ITypeLibImpl * pLibInfo)
+{
+ MSFT_TypeInfoBase tiBase;
+ ITypeInfoImpl *ptiRet;
+
+ TRACE_(typelib)("count=%u\n", count);
+
+ ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
+ MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
+ pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
+
+/* this is where we are coming from */
+ ptiRet->pTypeLib = pLibInfo;
+ ptiRet->index=count;
+/* fill in the typeattr fields */
+ WARN("Assign constructor/destructor memid\n");
+
+ MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
+ ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
+ ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
+ ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
+ ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
+ ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
+ ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
+ ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
+ ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
+ ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
+ ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
+ ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
+ ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
+ ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
+ ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
+ if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
+ MSFT_GetTdesc(pcx, tiBase.datatype1,
+ &ptiRet->TypeAttr.tdescAlias, ptiRet);
+
+/* FIXME: */
+/* IDLDESC idldescType; *//* never saw this one != zero */
+
+/* name, eventually add to a hash table */
+ ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
+ ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
+ TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
+ /* help info */
+ ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
+ ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
+ ptiRet->dwHelpContext=tiBase.helpcontext;
+
+ if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
+ ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
+
+/* note: InfoType's Help file and HelpStringDll come from the containing
+ * library. Further HelpString and Docstring appear to be the same thing :(
+ */
+ /* functions */
+ if(ptiRet->TypeAttr.cFuncs >0 )
+ MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
+ ptiRet->TypeAttr.cVars,
+ tiBase.memoffset, & ptiRet->funclist);
+ /* variables */
+ if(ptiRet->TypeAttr.cVars >0 )
+ MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
+ ptiRet->TypeAttr.cVars,
+ tiBase.memoffset, & ptiRet->varlist);
+ if(ptiRet->TypeAttr.cImplTypes >0 ) {
+ switch(ptiRet->TypeAttr.typekind)
+ {
+ case TKIND_COCLASS:
+ MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
+ tiBase.datatype1);
+ break;
+ case TKIND_DISPATCH:
+ ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
+
+ if (tiBase.datatype1 != -1)
+ {
+ MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
+ ptiRet->impltypelist->hRef = tiBase.datatype1;
+ }
+ else
+ { /* FIXME: This is a really bad hack to add IDispatch */
+ const char* szStdOle = "stdole2.tlb\0";
+ int nStdOleLen = strlen(szStdOle);
+ TLBRefType **ppRef = &ptiRet->reflist;
+
+ while(*ppRef) {
+ if((*ppRef)->reference == -1)
+ break;
+ ppRef = &(*ppRef)->next;
+ }
+ if(!*ppRef) {
+ *ppRef = TLB_Alloc(sizeof(**ppRef));
+ (*ppRef)->guid = IID_IDispatch;
+ (*ppRef)->reference = -1;
+ (*ppRef)->index = TLB_REF_USE_GUID;
+ (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
+ (*ppRef)->pImpTLInfo->guid = IID_StdOle;
+ (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
+ nStdOleLen + 1);
+
+ MultiByteToWideChar(CP_ACP,
+ MB_PRECOMPOSED,
+ szStdOle,
+ -1,
+ (*ppRef)->pImpTLInfo->name,
+ SysStringLen((*ppRef)->pImpTLInfo->name));
+
+ (*ppRef)->pImpTLInfo->lcid = 0;
+ (*ppRef)->pImpTLInfo->wVersionMajor = 2;
+ (*ppRef)->pImpTLInfo->wVersionMinor = 0;
+ }
+ }
+ break;
+ default:
+ ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
+ MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
+ ptiRet->impltypelist->hRef = tiBase.datatype1;
+ break;
+ }
+ }
+ ptiRet->ctCustData=
+ MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
+
+ TRACE_(typelib)("%s guid: %s kind:%s\n",
+ debugstr_w(ptiRet->Name),
+ debugstr_guid(&ptiRet->TypeAttr.guid),
+ typekind_desc[ptiRet->TypeAttr.typekind]);
+
+ return ptiRet;
+}
+
+/* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
+ * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
+ * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
+ * tradeoff here.
+ */
+static ITypeLibImpl *tlb_cache_first;
+static CRITICAL_SECTION cache_section;
+static CRITICAL_SECTION_DEBUG cache_section_debug =
+{
+ 0, 0, &cache_section,
+ { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
+};
+static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
+
+
+/****************************************************************************
+ * TLB_ReadTypeLib
+ *
+ * find the type of the typelib file and map the typelib resource into
+ * the memory
+ */
+#define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
+#define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
+int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
+{
+ ITypeLibImpl *entry;
+ int ret = TYPE_E_CANTLOADLIBRARY;
+ DWORD dwSignature = 0;
+ HANDLE hFile;
+
+ TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
+
+ *ppTypeLib = NULL;
+
+ /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
+ EnterCriticalSection(&cache_section);
+ for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
+ {
+ if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
+ {
+ TRACE("cache hit\n");
+ *ppTypeLib = (ITypeLib2*)entry;
+ ITypeLib_AddRef(*ppTypeLib);
+ LeaveCriticalSection(&cache_section);
+ return S_OK;
+ }
+ }
+ LeaveCriticalSection(&cache_section);
+
+ /* check the signature of the file */
+ hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
+ if (INVALID_HANDLE_VALUE != hFile)
+ {
+ HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
+ if (hMapping)
+ {
+ LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
+ if(pBase)
+ {
+ /* retrieve file size */
+ DWORD dwTLBLength = GetFileSize(hFile, NULL);
+
+ /* first try to load as *.tlb */
+ dwSignature = FromLEDWord(*((DWORD*) pBase));
+ if ( dwSignature == MSFT_SIGNATURE)
+ {
+ *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
+ }
+ else if ( dwSignature == SLTG_SIGNATURE)
+ {
+ *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
+ }
+ UnmapViewOfFile(pBase);
+ }
+ CloseHandle(hMapping);
+ }
+ CloseHandle(hFile);
+ }
+ else
+ {
+ TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
+ }
+
+ /* if the file is a DLL or not found, try loading it with LoadLibrary */
+ if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
+ {
+ /* find the typelibrary resource*/
+ HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
+ LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
+ if (hinstDLL)
+ {
+ static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
+ HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
+ if (hrsrc)
+ {
+ HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
+ if (hGlobal)
+ {
+ LPVOID pBase = LockResource(hGlobal);
+ DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
+
+ if (pBase)
+ {
+ /* try to load as incore resource */
+ dwSignature = FromLEDWord(*((DWORD*) pBase));
+ if ( dwSignature == MSFT_SIGNATURE)
+ {
+ *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
+ }
+ else if ( dwSignature == SLTG_SIGNATURE)
+ {
+ *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
+ }
+ else
+ {
+ FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
+ }
+ }
+ FreeResource( hGlobal );
+ }
+ }
+ FreeLibrary(hinstDLL);
+ }
+ }
+
+ if(*ppTypeLib) {
+ ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
+
+ TRACE("adding to cache\n");
+ impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
+ lstrcpyW(impl->path, pszFileName);
+ /* We should really canonicalise the path here. */
+ impl->index = index;
+
+ /* FIXME: check if it has added already in the meantime */
+ EnterCriticalSection(&cache_section);
+ if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
+ impl->prev = NULL;
+ tlb_cache_first = impl;
+ LeaveCriticalSection(&cache_section);
+ ret = S_OK;
+ } else
+ ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
+
+ return ret;
+}
+
+/*================== ITypeLib(2) Methods ===================================*/
+
+/****************************************************************************
+ * ITypeLib2_Constructor_MSFT
+ *
+ * loading an MSFT typelib from an in-memory image
+ */
+static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
+{
+ TLBContext cx;
+ long lPSegDir;
+ MSFT_Header tlbHeader;
+ MSFT_SegDir tlbSegDir;
+ ITypeLibImpl * pTypeLibImpl;
+
+ TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
+
+ pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
+ if (!pTypeLibImpl) return NULL;
+
+ pTypeLibImpl->lpVtbl = &tlbvt;
+ pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
+ pTypeLibImpl->ref = 1;
+
+ /* get pointer to beginning of typelib data */
+ cx.pos = 0;
+ cx.oStart=0;
+ cx.mapping = pLib;
+ cx.pLibInfo = pTypeLibImpl;
+ cx.length = dwTLBLength;
+
+ /* read header */
+ MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
+ TRACE("header:\n");
+ TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
+ if (tlbHeader.magic1 != MSFT_SIGNATURE) {
+ FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
+ return NULL;
+ }
+ /* there is a small amount of information here until the next important
+ * part:
+ * the segment directory . Try to calculate the amount of data */
+ lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
+
+ /* now read the segment directory */
+ TRACE("read segment directory (at %ld)\n",lPSegDir);
+ MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
+ cx.pTblDir = &tlbSegDir;
+
+ /* just check two entries */
+ if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
+ {
+ ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
+ HeapFree(GetProcessHeap(),0,pTypeLibImpl);
+ return NULL;
+ }
+
+ /* now fill our internal data */
+ /* TLIBATTR fields */
+ MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
+
+ /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
+ /* Windows seems to have zero here, is this correct? */
+ if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
+ pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
+ else
+ pTypeLibImpl->LibAttr.lcid = 0;
+
+ pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
+ pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
+ pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
+ pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
+
+ /* name, eventually add to a hash table */
+ pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
+
+ /* help info */
+ pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
+ pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
+
+ if( tlbHeader.varflags & HELPDLLFLAG)
+ {
+ int offset;
+ MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
+ pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
+ }
+
+ pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
+
+ /* custom data */
+ if(tlbHeader.CustomDataOffset >= 0)
+ {
+ pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
+ }
+
+ /* fill in typedescriptions */
+ if(tlbSegDir.pTypdescTab.length > 0)
+ {
+ int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
+ INT16 td[4];
+ pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
+ MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
+ for(i=0; i<cTD; )
+ {
+ /* FIXME: add several sanity checks here */
+ pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
+ if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
+ {
+ /* FIXME: check safearray */
+ if(td[3] < 0)
+ pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
+ else
+ pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
+ }
+ else if(td[0] == VT_CARRAY)
+ {
+ /* array descr table here */
+ pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
+ }
+ else if(td[0] == VT_USERDEFINED)
+ {
+ pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
+ }
+ if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
+ }
+
+ /* second time around to fill the array subscript info */
+ for(i=0;i<cTD;i++)
+ {
+ if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
+ if(tlbSegDir.pArrayDescriptions.offset>0)
+ {
+ MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
+ pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
+
+ if(td[1]<0)
+ pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
+ else
+ pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
+
+ pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
+
+ for(j = 0; j<td[2]; j++)
+ {
+ MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
+ sizeof(INT), &cx, DO_NOT_SEEK);
+ MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
+ sizeof(INT), &cx, DO_NOT_SEEK);
+ }
+ }
+ else
+ {
+ pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
+ ERR("didn't find array description data\n");
+ }
+ }
+ }
+
+ /* imported type libs */
+ if(tlbSegDir.pImpFiles.offset>0)
+ {
+ TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
+ int oGuid, offset = tlbSegDir.pImpFiles.offset;
+ UINT16 size;
+
+ while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
+ {
+ char *name;
+ DWORD len;
+
+ *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
+ (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
+ MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
+
+ MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
+ MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
+ MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
+ MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
+
+ size >>= 2;
+ name = TLB_Alloc(size+1);
+ MSFT_Read(name, size, &cx, DO_NOT_SEEK);
+ len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
+ (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
+ TLB_Free(name);
+
+ MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
+ offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
+
+ ppImpLib = &(*ppImpLib)->next;
+ }
+ }
+
+ /* type info's */
+ if(tlbHeader.nrtypeinfos >= 0 )
+ {
+ /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
+ ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
+ int i;
+
+ for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
+ {
+ *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
+
+ ppTI = &((*ppTI)->next);
+ (pTypeLibImpl->TypeInfoCount)++;
+ }
+ }
+
+ TRACE("(%p)\n", pTypeLibImpl);
+ return (ITypeLib2*) pTypeLibImpl;
+}
+
+
+static BSTR TLB_MultiByteToBSTR(char *ptr)
+{
+ DWORD len;
+ WCHAR *nameW;
+ BSTR ret;
+
+ len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
+ nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
+ ret = SysAllocString(nameW);
+ HeapFree(GetProcessHeap(), 0, nameW);
+ return ret;
+}
+
+static BOOL TLB_GUIDFromString(char *str, GUID *guid)
+{
+ char b[3];
+ int i;
+ short s;
+
+ if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
+ FIXME("Can't parse guid %s\n", debugstr_guid(guid));
+ return FALSE;
+ }
+
+ guid->Data4[0] = s >> 8;
+ guid->Data4[1] = s & 0xff;
+
+ b[2] = '\0';
+ for(i = 0; i < 6; i++) {
+ memcpy(b, str + 24 + 2 * i, 2);
+ guid->Data4[i + 2] = strtol(b, NULL, 16);
+ }
+ return TRUE;
+}
+
+static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
+{
+ WORD bytelen;
+ DWORD len;
+ WCHAR *nameW;
+
+ *pBstr = NULL;
+ bytelen = *(WORD*)ptr;
+ if(bytelen == 0xffff) return 2;
+ len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
+ nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+ len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
+ *pBstr = SysAllocStringLen(nameW, len);
+ HeapFree(GetProcessHeap(), 0, nameW);
+ return bytelen + 2;
+}
+
+static WORD SLTG_ReadStringA(char *ptr, char **str)
+{
+ WORD bytelen;
+
+ *str = NULL;
+ bytelen = *(WORD*)ptr;
+ if(bytelen == 0xffff) return 2;
+ *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
+ memcpy(*str, ptr + 2, bytelen);
+ (*str)[bytelen] = '\0';
+ return bytelen + 2;
+}
+
+static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
+{
+ char *ptr = pLibBlk;
+ WORD w;
+
+ if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
+ FIXME("libblk magic = %04x\n", w);
+ return 0;
+ }
+
+ ptr += 6;
+ if((w = *(WORD*)ptr) != 0xffff) {
+ FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
+ ptr += w;
+ }
+ ptr += 2;
+
+ ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
+
+ ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
+
+ pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
+ ptr += 4;
+
+ pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
+ ptr += 2;
+
+ if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
+ pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
+ else
+ pTypeLibImpl->LibAttr.lcid = 0;
+ ptr += 2;
+
+ ptr += 4; /* skip res12 */
+
+ pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
+ ptr += 2;
+
+ pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
+ ptr += 2;
+
+ pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
+ ptr += 2;
+
+ memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
+ ptr += sizeof(GUID);
+
+ return ptr - (char*)pLibBlk;
+}
+
+static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
+{
+ BOOL done = FALSE;
+ TYPEDESC *pTD = &pElem->tdesc;
+
+ /* Handle [in/out] first */
+ if((*pType & 0xc000) == 0xc000)
+ pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
+ else if(*pType & 0x8000)
+ pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
+ else if(*pType & 0x4000)
+ pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
+ else
+ pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
+
+ if(*pType & 0x2000)
+ pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
+
+ if(*pType & 0x80)
+ pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
+
+ while(!done) {
+ if((*pType & 0xe00) == 0xe00) {
+ pTD->vt = VT_PTR;
+ pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(TYPEDESC));
+ pTD = pTD->u.lptdesc;
+ }
+ switch(*pType & 0x7f) {
+ case VT_PTR:
+ pTD->vt = VT_PTR;
+ pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(TYPEDESC));
+ pTD = pTD->u.lptdesc;
+ break;
+
+ case VT_USERDEFINED:
+ pTD->vt = VT_USERDEFINED;
+ pTD->u.hreftype = *(++pType) / 4;
+ done = TRUE;
+ break;
+
+ case VT_CARRAY:
+ {
+ /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
+ array */
+
+ SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
+
+ pTD->vt = VT_CARRAY;
+ pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(ARRAYDESC) +
+ (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
+ pTD->u.lpadesc->cDims = pSA->cDims;
+ memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
+ pSA->cDims * sizeof(SAFEARRAYBOUND));
+
+ pTD = &pTD->u.lpadesc->tdescElem;
+ break;
+ }
+
+ case VT_SAFEARRAY:
+ {
+ /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
+ useful? */
+
+ pType++;
+ pTD->vt = VT_SAFEARRAY;
+ pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(TYPEDESC));
+ pTD = pTD->u.lptdesc;
+ break;
+ }
+ default:
+ pTD->vt = *pType & 0x7f;
+ done = TRUE;
+ break;
+ }
+ pType++;
+ }
+ return pType;
+}
+
+
+static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
+ char *pNameTable)
+{
+ int ref;
+ char *name;
+ TLBRefType **ppRefType;
+
+ if(pRef->magic != SLTG_REF_MAGIC) {
+ FIXME("Ref magic = %x\n", pRef->magic);
+ return;
+ }
+ name = ( (char*)(&pRef->names) + pRef->number);
+
+ ppRefType = &pTI->reflist;
+ for(ref = 0; ref < pRef->number >> 3; ref++) {
+ char *refname;
+ unsigned int lib_offs, type_num;
+
+ *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(**ppRefType));
+
+ name += SLTG_ReadStringA(name, &refname);
+ if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
+ FIXME("Can't sscanf ref\n");
+ if(lib_offs != 0xffff) {
+ TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
+
+ while(*import) {
+ if((*import)->offset == lib_offs)
+ break;
+ import = &(*import)->next;
+ }
+ if(!*import) {
+ char fname[MAX_PATH+1];
+ int len;
+
+ *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(**import));
+ (*import)->offset = lib_offs;
+ TLB_GUIDFromString( pNameTable + lib_offs + 4,
+ &(*import)->guid);
+ if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
+ &(*import)->wVersionMajor,
+ &(*import)->wVersionMinor,
+ &(*import)->lcid, fname) != 4) {
+ FIXME("can't sscanf ref %s\n",
+ pNameTable + lib_offs + 40);
+ }
+ len = strlen(fname);
+ if(fname[len-1] != '#')
+ FIXME("fname = %s\n", fname);
+ fname[len-1] = '\0';
+ (*import)->name = TLB_MultiByteToBSTR(fname);
+ }
+ (*ppRefType)->pImpTLInfo = *import;
+ } else { /* internal ref */
+ (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
+ }
+ (*ppRefType)->reference = ref;
+ (*ppRefType)->index = type_num;
+
+ HeapFree(GetProcessHeap(), 0, refname);
+ ppRefType = &(*ppRefType)->next;
+ }
+ if((BYTE)*name != SLTG_REF_MAGIC)
+ FIXME("End of ref block magic = %x\n", *name);
+ dump_TLBRefType(pTI->reflist);
+}
+
+static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
+ BOOL OneOnly)
+{
+ SLTG_ImplInfo *info;
+ TLBImplType **ppImplType = &pTI->impltypelist;
+ /* I don't really get this structure, usually it's 0x16 bytes
+ long, but iuser.tlb contains some that are 0x18 bytes long.
+ That's ok because we can use the next ptr to jump to the next
+ one. But how do we know the length of the last one? The WORD
+ at offs 0x8 might be the clue. For now I'm just assuming that
+ the last one is the regular 0x16 bytes. */
+
+ info = (SLTG_ImplInfo*)pBlk;
+ while(1) {
+ *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(**ppImplType));
+ (*ppImplType)->hRef = info->ref;
+ (*ppImplType)->implflags = info->impltypeflags;
+ pTI->TypeAttr.cImplTypes++;
+ ppImplType = &(*ppImplType)->next;
+
+ if(info->next == 0xffff)
+ break;
+ if(OneOnly)
+ FIXME("Interface inheriting more than one interface\n");
+ info = (SLTG_ImplInfo*)(pBlk + info->next);
+ }
+ info++; /* see comment at top of function */
+ return (char*)info;
+}
+
+static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
+ char *pNameTable)
+{
+ SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
+ SLTG_MemberHeader *pMemHeader;
+ char *pFirstItem, *pNextItem;
+
+ if(pTIHeader->href_table != 0xffffffff) {
+ SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
+ pNameTable);
+ }
+
+
+ pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
+
+ pFirstItem = pNextItem = (char*)(pMemHeader + 1);
+
+ if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
+ pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
+ }
+
+ return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
+}
+
+
+static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
+ char *pNameTable)
+{
+ SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
+ SLTG_MemberHeader *pMemHeader;
+ SLTG_Function *pFunc;
+ char *pFirstItem, *pNextItem;
+ TLBFuncDesc **ppFuncDesc = &pTI->funclist;
+ int num = 0;
+
+ if(pTIHeader->href_table != 0xffffffff) {
+ SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
+ pNameTable);
+ }
+
+ pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
+
+ pFirstItem = pNextItem = (char*)(pMemHeader + 1);
+
+ if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
+ pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
+ }
+
+ for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
+ pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
+
+ int param;
+ WORD *pType, *pArg;
+
+ if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
+ pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
+ FIXME("func magic = %02x\n", pFunc->magic);
+ return NULL;
+ }
+ *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(**ppFuncDesc));
+ (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
+
+ (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
+ (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
+ (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
+ (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
+ (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
+ (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
+
+ if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
+ (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
+
+ if(pFunc->retnextopt & 0x80)
+ pType = &pFunc->rettype;
+ else
+ pType = (WORD*)(pFirstItem + pFunc->rettype);
+
+
+ SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
+
+ (*ppFuncDesc)->funcdesc.lprgelemdescParam =
+ HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
+ (*ppFuncDesc)->pParamDesc =
+ HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
+
+ pArg = (WORD*)(pFirstItem + pFunc->arg_off);
+
+ for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
+ char *paramName = pNameTable + *pArg;
+ BOOL HaveOffs;
+ /* If arg type follows then paramName points to the 2nd
+ letter of the name, else the next WORD is an offset to
+ the arg type and paramName points to the first letter.
+ So let's take one char off paramName and see if we're
+ pointing at an alpha-numeric char. However if *pArg is
+ 0xffff or 0xfffe then the param has no name, the former
+ meaning that the next WORD is the type, the latter
+ meaning the the next WORD is an offset to the type. */
+
+ HaveOffs = FALSE;
+ if(*pArg == 0xffff)
+ paramName = NULL;
+ else if(*pArg == 0xfffe) {
+ paramName = NULL;
+ HaveOffs = TRUE;
+ }
+ else if(paramName[-1] && !isalnum(paramName[-1]))
+ HaveOffs = TRUE;
+
+ pArg++;
+
+ if(HaveOffs) { /* the next word is an offset to type */
+ pType = (WORD*)(pFirstItem + *pArg);
+ SLTG_DoType(pType, pFirstItem,
+ &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
+ pArg++;
+ } else {
+ if(paramName)
+ paramName--;
+ pArg = SLTG_DoType(pArg, pFirstItem,
+ &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
+ }
+
+ /* Are we an optional param ? */
+ if((*ppFuncDesc)->funcdesc.cParams - param <=
+ (*ppFuncDesc)->funcdesc.cParamsOpt)
+ (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
+
+ if(paramName) {
+ (*ppFuncDesc)->pParamDesc[param].Name =
+ TLB_MultiByteToBSTR(paramName);
+ }
+ }
+
+ ppFuncDesc = &((*ppFuncDesc)->next);
+ if(pFunc->next == 0xffff) break;
+ }
+ pTI->TypeAttr.cFuncs = num;
+ dump_TLBFuncDesc(pTI->funclist);
+ return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
+}
+
+static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
+ char *pNameTable)
+{
+ SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
+ SLTG_MemberHeader *pMemHeader;
+ SLTG_RecordItem *pItem;
+ char *pFirstItem;
+ TLBVarDesc **ppVarDesc = &pTI->varlist;
+ int num = 0;
+ WORD *pType;
+ char buf[300];
+
+ pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
+
+ pFirstItem = (char*)(pMemHeader + 1);
+ for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
+ pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
+ if(pItem->magic != SLTG_RECORD_MAGIC) {
+ FIXME("record magic = %02x\n", pItem->magic);
+ return NULL;
+ }
+ *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(**ppVarDesc));
+ (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
+ (*ppVarDesc)->vardesc.memid = pItem->memid;
+ (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
+ (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
+
+ if(pItem->typepos == 0x02)
+ pType = &pItem->type;
+ else if(pItem->typepos == 0x00)
+ pType = (WORD*)(pFirstItem + pItem->type);
+ else {
+ FIXME("typepos = %02x\n", pItem->typepos);
+ break;
+ }
+
+ SLTG_DoType(pType, pFirstItem,
+ &(*ppVarDesc)->vardesc.elemdescVar);
+
+ /* FIXME("helpcontext, helpstring\n"); */
+
+ dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
+
+ ppVarDesc = &((*ppVarDesc)->next);
+ if(pItem->next == 0xffff) break;
+ }
+ pTI->TypeAttr.cVars = num;
+ return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
+}
+
+static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
+ char *pNameTable)
+{
+ SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
+ SLTG_MemberHeader *pMemHeader;
+ SLTG_AliasItem *pItem;
+ int i, mustbelast;
+
+ pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
+ pItem = (SLTG_AliasItem*)(pMemHeader + 1);
+
+ mustbelast = 0;
+ /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
+ for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
+ if (pItem->vt == 0xffff) {
+ if (i<(pMemHeader->cbExtra/4-1))
+ FIXME("Endmarker too early in process alias data!\n");
+ break;
+ }
+ if (mustbelast) {
+ FIXME("Chain extends over last entry?\n");
+ break;
+ }
+ if (pItem->vt == VT_USERDEFINED) {
+ pTI->TypeAttr.tdescAlias.vt = pItem->vt;
+ /* guessing here ... */
+ FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
+ pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
+ mustbelast = 1;
+ } else {
+ FIXME("alias %d: 0x%x\n",i,pItem->vt);
+ FIXME("alias %d: 0x%x\n",i,pItem->res02);
+ }
+ pItem++;
+ }
+ return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
+}
+
+static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
+ char *pNameTable)
+{
+ SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
+ SLTG_MemberHeader *pMemHeader;
+ SLTG_AliasItem *pItem;
+
+ pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
+ pItem = (SLTG_AliasItem*)(pMemHeader + 1);
+ FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
+ FIXME("offset 0 0x%x\n",*(WORD*)pItem);
+ return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
+}
+
+static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
+ char *pNameTable)
+{
+ SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
+ SLTG_MemberHeader *pMemHeader;
+ SLTG_EnumItem *pItem;
+ char *pFirstItem;
+ TLBVarDesc **ppVarDesc = &pTI->varlist;
+ int num = 0;
+
+ pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
+
+ pFirstItem = (char*)(pMemHeader + 1);
+ for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
+ pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
+ if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
+ FIXME("enumitem magic = %04x\n", pItem->magic);
+ return NULL;
+ }
+ *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(**ppVarDesc));
+ (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
+ (*ppVarDesc)->vardesc.memid = pItem->memid;
+ (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
+ sizeof(VARIANT));
+ V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
+ V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
+ *(INT*)(pItem->value + pFirstItem);
+ (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
+ (*ppVarDesc)->vardesc.varkind = VAR_CONST;
+ /* FIXME("helpcontext, helpstring\n"); */
+
+ ppVarDesc = &((*ppVarDesc)->next);
+ if(pItem->next == 0xffff) break;
+ }
+ pTI->TypeAttr.cVars = num;
+ return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
+}
+
+/* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
+ managable copy of it into this */
+typedef struct {
+ WORD small_no;
+ char *index_name;
+ char *other_name;
+ WORD res1a;
+ WORD name_offs;
+ WORD more_bytes;
+ char *extra;
+ WORD res20;
+ DWORD helpcontext;
+ WORD res26;
+ GUID uuid;
+} SLTG_InternalOtherTypeInfo;
+
+/****************************************************************************
+ * ITypeLib2_Constructor_SLTG
+ *
+ * loading a SLTG typelib from an in-memory image
+ */
+static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
+{
+ ITypeLibImpl *pTypeLibImpl;
+ SLTG_Header *pHeader;
+ SLTG_BlkEntry *pBlkEntry;
+ SLTG_Magic *pMagic;
+ SLTG_Index *pIndex;
+ SLTG_Pad9 *pPad9;
+ LPVOID pBlk, pFirstBlk;
+ SLTG_LibBlk *pLibBlk;
+ SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
+ char *pAfterOTIBlks = NULL;
+ char *pNameTable, *ptr;
+ int i;
+ DWORD len, order;
+ ITypeInfoImpl **ppTypeInfoImpl;
+
+ TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
+
+ pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
+ if (!pTypeLibImpl) return NULL;
+
+ pTypeLibImpl->lpVtbl = &tlbvt;
+ pTypeLibImpl->ref = 1;
+
+ pHeader = pLib;
+
+ TRACE_(typelib)("header:\n");
+ TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
+ pHeader->nrOfFileBlks );
+ if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
+ FIXME("Header type magic 0x%08lx not supported.\n",
+ pHeader->SLTG_magic);
+ return NULL;
+ }
+
+ /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
+ pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
+
+ /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
+ pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
+
+ /* Next we have a magic block */
+ pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
+
+ /* Let's see if we're still in sync */
+ if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
+ sizeof(SLTG_COMPOBJ_MAGIC))) {
+ FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
+ return NULL;
+ }
+ if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
+ sizeof(SLTG_DIR_MAGIC))) {
+ FIXME("dir magic = %s\n", pMagic->dir_magic);
+ return NULL;
+ }
+
+ pIndex = (SLTG_Index*)(pMagic+1);
+
+ pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
+
+ pFirstBlk = (LPVOID)(pPad9 + 1);
+
+ /* We'll set up a ptr to the main library block, which is the last one. */
+
+ for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
+ pBlkEntry[order].next != 0;
+ order = pBlkEntry[order].next - 1, i++) {
+ pBlk = (char*)pBlk + pBlkEntry[order].len;
+ }
+ pLibBlk = pBlk;
+
+ len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
+
+ /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
+ interspersed */
+
+ len += 0x40;
+
+ /* And now TypeInfoCount of SLTG_OtherTypeInfo */
+
+ pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(*pOtherTypeInfoBlks) *
+ pTypeLibImpl->TypeInfoCount);
+
+
+ ptr = (char*)pLibBlk + len;
+
+ for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
+ WORD w, extra;
+ len = 0;
+
+ pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
+
+ w = *(WORD*)(ptr + 2);
+ if(w != 0xffff) {
+ len += w;
+ pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
+ w+1);
+ memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
+ pOtherTypeInfoBlks[i].index_name[w] = '\0';
+ }
+ w = *(WORD*)(ptr + 4 + len);
+ if(w != 0xffff) {
+ TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
+ len += w;
+ pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
+ w+1);
+ memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
+ pOtherTypeInfoBlks[i].other_name[w] = '\0';
+ }
+ pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
+ pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
+ extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
+ if(extra) {
+ pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
+ extra);
+ memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
+ len += extra;
+ }
+ pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
+ pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
+ pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
+ memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
+ len += sizeof(SLTG_OtherTypeInfo);
+ ptr += len;
+ }
+
+ pAfterOTIBlks = ptr;
+
+ /* Skip this WORD and get the next DWORD */
+ len = *(DWORD*)(pAfterOTIBlks + 2);
+
+ /* Now add this to pLibBLk look at what we're pointing at and
+ possibly add 0x20, then add 0x216, sprinkle a bit a magic
+ dust and we should be pointing at the beginning of the name
+ table */
+
+ pNameTable = (char*)pLibBlk + len;
+
+ switch(*(WORD*)pNameTable) {
+ case 0xffff:
+ break;
+ case 0x0200:
+ pNameTable += 0x20;
+ break;
+ default:
+ FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
+ break;
+ }
+
+ pNameTable += 0x216;
+
+ pNameTable += 2;
+
+ TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
+
+ pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
+
+
+ /* Hopefully we now have enough ptrs set up to actually read in
+ some TypeInfos. It's not clear which order to do them in, so
+ I'll just follow the links along the BlkEntry chain and read
+ them in in the order in which they're in the file */
+
+ ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
+
+ for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
+ pBlkEntry[order].next != 0;
+ order = pBlkEntry[order].next - 1, i++) {
+
+ SLTG_TypeInfoHeader *pTIHeader;
+ SLTG_TypeInfoTail *pTITail;
+
+ if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
+ pOtherTypeInfoBlks[i].index_name)) {
+ FIXME("Index strings don't match\n");
+ return NULL;
+ }
+
+ pTIHeader = pBlk;
+ if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
+ FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
+ return NULL;
+ }
+ *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
+ (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
+ (*ppTypeInfoImpl)->index = i;
+ (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
+ pOtherTypeInfoBlks[i].name_offs +
+ pNameTable);
+ (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
+ memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
+ sizeof(GUID));
+ (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
+ (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
+ (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
+ (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
+ (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
+
+ if((pTIHeader->typeflags1 & 7) != 2)
+ FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
+ if(pTIHeader->typeflags3 != 2)
+ FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
+
+ TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
+ debugstr_w((*ppTypeInfoImpl)->Name),
+ typekind_desc[pTIHeader->typekind],
+ debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
+ (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
+
+ switch(pTIHeader->typekind) {
+ case TKIND_ENUM:
+ pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
+ break;
+
+ case TKIND_RECORD:
+ pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
+ break;
+
+ case TKIND_INTERFACE:
+ pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
+ break;
+
+ case TKIND_COCLASS:
+ pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
+ break;
+
+ case TKIND_ALIAS:
+ pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
+ if (pTITail->tdescalias_vt)
+ (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
+ break;
+
+ case TKIND_DISPATCH:
+ pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
+ break;
+
+ default:
+ FIXME("Not processing typekind %d\n", pTIHeader->typekind);
+ pTITail = NULL;
+ break;
+
+ }
+
+ if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
+ but we've already set those */
+ (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
+ (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
+ (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
+
+#define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
+ X(06);
+ X(08);
+ X(0a);
+ X(0c);
+ X(0e);
+ X(10);
+ X(12);
+ X(16);
+ X(18);
+ X(1a);
+ X(1c);
+ X(1e);
+ X(24);
+ X(26);
+ X(2a);
+ X(2c);
+ X(2e);
+ X(30);
+ X(32);
+ X(34);
+ }
+ ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
+ pBlk = (char*)pBlk + pBlkEntry[order].len;
+ }
+
+ if(i != pTypeLibImpl->TypeInfoCount) {
+ FIXME("Somehow processed %d TypeInfos\n", i);
+ return NULL;
+ }
+
+ HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
+ return (ITypeLib2*)pTypeLibImpl;
+}
+
+/* ITypeLib::QueryInterface
+ */
+static HRESULT WINAPI ITypeLib2_fnQueryInterface(
+ ITypeLib2 * iface,
+ REFIID riid,
+ VOID **ppvObject)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+
+ TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
+
+ *ppvObject=NULL;
+ if(IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid,&IID_ITypeLib)||
+ IsEqualIID(riid,&IID_ITypeLib2))
+ {
+ *ppvObject = This;
+ }
+
+ if(*ppvObject)
+ {
+ ITypeLib2_AddRef(iface);
+ TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
+ return S_OK;
+ }
+ TRACE("-- Interface: E_NOINTERFACE\n");
+ return E_NOINTERFACE;
+}
+
+/* ITypeLib::AddRef
+ */
+static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p)->ref was %lu\n",This, ref - 1);
+
+ return ref;
+}
+
+/* ITypeLib::Release
+ */
+static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p)->(%lu)\n",This, ref);
+
+ if (!ref)
+ {
+ /* remove cache entry */
+ TRACE("removing from cache list\n");
+ EnterCriticalSection(&cache_section);
+ if (This->next) This->next->prev = This->prev;
+ if (This->prev) This->prev->next = This->next;
+ else tlb_cache_first = This->next;
+ LeaveCriticalSection(&cache_section);
+
+ /* FIXME destroy child objects */
+ TRACE(" destroying ITypeLib(%p)\n",This);
+
+ if (This->Name)
+ {
+ SysFreeString(This->Name);
+ This->Name = NULL;
+ }
+
+ if (This->DocString)
+ {
+ SysFreeString(This->DocString);
+ This->DocString = NULL;
+ }
+
+ if (This->HelpFile)
+ {
+ SysFreeString(This->HelpFile);
+ This->HelpFile = NULL;
+ }
+
+ if (This->HelpStringDll)
+ {
+ SysFreeString(This->HelpStringDll);
+ This->HelpStringDll = NULL;
+ }
+
+ if (This->pTypeInfo) /* can be NULL */
+ ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
+ HeapFree(GetProcessHeap(),0,This);
+ return 0;
+ }
+
+ return ref;
+}
+
+/* ITypeLib::GetTypeInfoCount
+ *
+ * Returns the number of type descriptions in the type library
+ */
+static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
+ return This->TypeInfoCount;
+}
+
+/* ITypeLib::GetTypeInfo
+ *
+ * retrieves the specified type description in the library.
+ */
+static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
+ ITypeLib2 *iface,
+ UINT index,
+ ITypeInfo **ppTInfo)
+{
+ int i;
+
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
+
+ TRACE("(%p)->(index=%d)\n", This, index);
+
+ if (!ppTInfo) return E_INVALIDARG;
+
+ /* search element n in list */
+ for(i=0; i < index; i++)
+ {
+ pTypeInfo = pTypeInfo->next;
+ if (!pTypeInfo)
+ {
+ TRACE("-- element not found\n");
+ return TYPE_E_ELEMENTNOTFOUND;
+ }
+ }
+
+ *ppTInfo = (ITypeInfo *) pTypeInfo;
+
+ ITypeInfo_AddRef(*ppTInfo);
+ TRACE("-- found (%p)\n",*ppTInfo);
+ return S_OK;
+}
+
+
+/* ITypeLibs::GetTypeInfoType
+ *
+ * Retrieves the type of a type description.
+ */
+static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
+ ITypeLib2 *iface,
+ UINT index,
+ TYPEKIND *pTKind)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ int i;
+ ITypeInfoImpl *pTInfo = This->pTypeInfo;
+
+ TRACE("(%p) index %d\n", This, index);
+
+ if(!pTKind) return E_INVALIDARG;
+
+ /* search element n in list */
+ for(i=0; i < index; i++)
+ {
+ if(!pTInfo)
+ {
+ TRACE("-- element not found\n");
+ return TYPE_E_ELEMENTNOTFOUND;
+ }
+ pTInfo = pTInfo->next;
+ }
+
+ *pTKind = pTInfo->TypeAttr.typekind;
+ TRACE("-- found Type (%d)\n", *pTKind);
+ return S_OK;
+}
+
+/* ITypeLib::GetTypeInfoOfGuid
+ *
+ * Retrieves the type description that corresponds to the specified GUID.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
+ ITypeLib2 *iface,
+ REFGUID guid,
+ ITypeInfo **ppTInfo)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
+
+ TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
+
+ if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
+
+ /* search linked list for guid */
+ while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
+ {
+ pTypeInfo = pTypeInfo->next;
+
+ if (!pTypeInfo)
+ {
+ /* end of list reached */
+ TRACE("-- element not found\n");
+ return TYPE_E_ELEMENTNOTFOUND;
+ }
+ }
+
+ TRACE("-- found (%p, %s)\n",
+ pTypeInfo,
+ debugstr_w(pTypeInfo->Name));
+
+ *ppTInfo = (ITypeInfo*)pTypeInfo;
+ ITypeInfo_AddRef(*ppTInfo);
+ return S_OK;
+}
+
+/* ITypeLib::GetLibAttr
+ *
+ * Retrieves the structure that contains the library's attributes.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
+ ITypeLib2 *iface,
+ LPTLIBATTR *ppTLibAttr)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ TRACE("(%p)\n",This);
+ *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
+ memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
+ return S_OK;
+}
+
+/* ITypeLib::GetTypeComp
+ *
+ * Enables a client compiler to bind to a library's types, variables,
+ * constants, and global functions.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
+ ITypeLib2 *iface,
+ ITypeComp **ppTComp)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+
+ TRACE("(%p)->(%p)\n",This,ppTComp);
+ *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
+ ITypeComp_AddRef(*ppTComp);
+
+ return S_OK;
+}
+
+/* ITypeLib::GetDocumentation
+ *
+ * Retrieves the library's documentation string, the complete Help file name
+ * and path, and the context identifier for the library Help topic in the Help
+ * file.
+ *
+ * On a successful return all non-null BSTR pointers will have been set,
+ * possibly to NULL.
+ */
+static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
+ ITypeLib2 *iface,
+ INT index,
+ BSTR *pBstrName,
+ BSTR *pBstrDocString,
+ DWORD *pdwHelpContext,
+ BSTR *pBstrHelpFile)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+
+ HRESULT result = E_INVALIDARG;
+
+ ITypeInfo *pTInfo;
+
+
+ TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
+ This, index,
+ pBstrName, pBstrDocString,
+ pdwHelpContext, pBstrHelpFile);
+
+ if(index<0)
+ {
+ /* documentation for the typelib */
+ if(pBstrName)
+ {
+ if (This->Name)
+ {
+ if(!(*pBstrName = SysAllocString(This->Name)))
+ goto memerr1;
+ }
+ else
+ *pBstrName = NULL;
+ }
+ if(pBstrDocString)
+ {
+ if (This->DocString)
+ {
+ if(!(*pBstrDocString = SysAllocString(This->DocString)))
+ goto memerr2;
+ }
+ else if (This->Name)
+ {
+ if(!(*pBstrDocString = SysAllocString(This->Name)))
+ goto memerr2;
+ }
+ else
+ *pBstrDocString = NULL;
+ }
+ if(pdwHelpContext)
+ {
+ *pdwHelpContext = This->dwHelpContext;
+ }
+ if(pBstrHelpFile)
+ {
+ if (This->HelpFile)
+ {
+ if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
+ goto memerr3;
+ }
+ else
+ *pBstrHelpFile = NULL;
+ }
+
+ result = S_OK;
+ }
+ else
+ {
+ /* for a typeinfo */
+ result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
+
+ if(SUCCEEDED(result))
+ {
+ result = ITypeInfo_GetDocumentation(pTInfo,
+ MEMBERID_NIL,
+ pBstrName,
+ pBstrDocString,
+ pdwHelpContext, pBstrHelpFile);
+
+ ITypeInfo_Release(pTInfo);
+ }
+ }
+ return result;
+memerr3:
+ if (pBstrDocString) SysFreeString (*pBstrDocString);
+memerr2:
+ if (pBstrName) SysFreeString (*pBstrName);
+memerr1:
+ return STG_E_INSUFFICIENTMEMORY;
+}
+
+/* ITypeLib::IsName
+ *
+ * Indicates whether a passed-in string contains the name of a type or member
+ * described in the library.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnIsName(
+ ITypeLib2 *iface,
+ LPOLESTR szNameBuf,
+ ULONG lHashVal,
+ BOOL *pfName)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ ITypeInfoImpl *pTInfo;
+ TLBFuncDesc *pFInfo;
+ TLBVarDesc *pVInfo;
+ int i;
+ UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
+
+ TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
+ pfName);
+
+ *pfName=TRUE;
+ for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
+ if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
+ for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
+ if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
+ for(i=0;i<pFInfo->funcdesc.cParams;i++)
+ if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
+ goto ITypeLib2_fnIsName_exit;
+ }
+ for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
+ if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
+
+ }
+ *pfName=FALSE;
+
+ITypeLib2_fnIsName_exit:
+ TRACE("(%p)slow! search for %s: %s found!\n", This,
+ debugstr_w(szNameBuf), *pfName?"NOT":"");
+
+ return S_OK;
+}
+
+/* ITypeLib::FindName
+ *
+ * Finds occurrences of a type description in a type library. This may be used
+ * to quickly verify that a name exists in a type library.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnFindName(
+ ITypeLib2 *iface,
+ LPOLESTR szNameBuf,
+ ULONG lHashVal,
+ ITypeInfo **ppTInfo,
+ MEMBERID *rgMemId,
+ UINT16 *pcFound)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ ITypeInfoImpl *pTInfo;
+ TLBFuncDesc *pFInfo;
+ TLBVarDesc *pVInfo;
+ int i,j = 0;
+ UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
+
+ for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
+ if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
+ for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
+ if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
+ for(i=0;i<pFInfo->funcdesc.cParams;i++) {
+ if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
+ goto ITypeLib2_fnFindName_exit;
+ }
+ }
+ for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
+ if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
+ continue;
+ITypeLib2_fnFindName_exit:
+ ITypeInfo_AddRef((ITypeInfo*)pTInfo);
+ ppTInfo[j]=(LPTYPEINFO)pTInfo;
+ j++;
+ }
+ TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
+ This, *pcFound, debugstr_w(szNameBuf), j);
+
+ *pcFound=j;
+
+ return S_OK;
+}
+
+/* ITypeLib::ReleaseTLibAttr
+ *
+ * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
+ *
+ */
+static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
+ ITypeLib2 *iface,
+ TLIBATTR *pTLibAttr)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ TRACE("freeing (%p)\n",This);
+ HeapFree(GetProcessHeap(),0,pTLibAttr);
+
+}
+
+/* ITypeLib2::GetCustData
+ *
+ * gets the custom data
+ */
+static HRESULT WINAPI ITypeLib2_fnGetCustData(
+ ITypeLib2 * iface,
+ REFGUID guid,
+ VARIANT *pVarVal)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ TLBCustData *pCData;
+
+ for(pCData=This->pCustData; pCData; pCData = pCData->next)
+ {
+ if( IsEqualIID(guid, &pCData->guid)) break;
+ }
+
+ TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
+
+ if(pCData)
+ {
+ VariantInit( pVarVal);
+ VariantCopy( pVarVal, &pCData->data);
+ return S_OK;
+ }
+ return E_INVALIDARG; /* FIXME: correct? */
+}
+
+/* ITypeLib2::GetLibStatistics
+ *
+ * Returns statistics about a type library that are required for efficient
+ * sizing of hash tables.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
+ ITypeLib2 * iface,
+ ULONG *pcUniqueNames,
+ ULONG *pcchUniqueNames)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+
+ FIXME("(%p): stub!\n", This);
+
+ if(pcUniqueNames) *pcUniqueNames=1;
+ if(pcchUniqueNames) *pcchUniqueNames=1;
+ return S_OK;
+}
+
+/* ITypeLib2::GetDocumentation2
+ *
+ * Retrieves the library's documentation string, the complete Help file name
+ * and path, the localization context to use, and the context ID for the
+ * library Help topic in the Help file.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
+ ITypeLib2 * iface,
+ INT index,
+ LCID lcid,
+ BSTR *pbstrHelpString,
+ DWORD *pdwHelpStringContext,
+ BSTR *pbstrHelpStringDll)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ HRESULT result;
+ ITypeInfo *pTInfo;
+
+ FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
+
+ /* the help string should be obtained from the helpstringdll,
+ * using the _DLLGetDocumentation function, based on the supplied
+ * lcid. Nice to do sometime...
+ */
+ if(index<0)
+ {
+ /* documentation for the typelib */
+ if(pbstrHelpString)
+ *pbstrHelpString=SysAllocString(This->DocString);
+ if(pdwHelpStringContext)
+ *pdwHelpStringContext=This->dwHelpContext;
+ if(pbstrHelpStringDll)
+ *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
+
+ result = S_OK;
+ }
+ else
+ {
+ /* for a typeinfo */
+ result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
+
+ if(SUCCEEDED(result))
+ {
+ ITypeInfo2 * pTInfo2;
+ result = ITypeInfo_QueryInterface(pTInfo,
+ &IID_ITypeInfo2,
+ (LPVOID*) &pTInfo2);
+
+ if(SUCCEEDED(result))
+ {
+ result = ITypeInfo2_GetDocumentation2(pTInfo2,
+ MEMBERID_NIL,
+ lcid,
+ pbstrHelpString,
+ pdwHelpStringContext,
+ pbstrHelpStringDll);
+
+ ITypeInfo2_Release(pTInfo2);
+ }
+
+ ITypeInfo_Release(pTInfo);
+ }
+ }
+ return result;
+}
+
+/* ITypeLib2::GetAllCustData
+ *
+ * Gets all custom data items for the library.
+ *
+ */
+static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
+ ITypeLib2 * iface,
+ CUSTDATA *pCustData)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+ TLBCustData *pCData;
+ int i;
+ TRACE("(%p) returning %d items\n", This, This->ctCustData);
+ pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
+ if(pCustData->prgCustData ){
+ pCustData->cCustData=This->ctCustData;
+ for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
+ pCustData->prgCustData[i].guid=pCData->guid;
+ VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
+ }
+ }else{
+ ERR(" OUT OF MEMORY!\n");
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+}
+
+static const ITypeLib2Vtbl tlbvt = {
+ ITypeLib2_fnQueryInterface,
+ ITypeLib2_fnAddRef,
+ ITypeLib2_fnRelease,
+ ITypeLib2_fnGetTypeInfoCount,
+ ITypeLib2_fnGetTypeInfo,
+ ITypeLib2_fnGetTypeInfoType,
+ ITypeLib2_fnGetTypeInfoOfGuid,
+ ITypeLib2_fnGetLibAttr,
+ ITypeLib2_fnGetTypeComp,
+ ITypeLib2_fnGetDocumentation,
+ ITypeLib2_fnIsName,
+ ITypeLib2_fnFindName,
+ ITypeLib2_fnReleaseTLibAttr,
+
+ ITypeLib2_fnGetCustData,
+ ITypeLib2_fnGetLibStatistics,
+ ITypeLib2_fnGetDocumentation2,
+ ITypeLib2_fnGetAllCustData
+ };
+
+
+static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
+{
+ ITypeLibImpl *This = impl_from_ITypeComp(iface);
+
+ return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
+}
+
+static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
+{
+ ITypeLibImpl *This = impl_from_ITypeComp(iface);
+
+ return ITypeLib2_AddRef((ITypeLib2 *)This);
+}
+
+static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
+{
+ ITypeLibImpl *This = impl_from_ITypeComp(iface);
+
+ return ITypeLib2_Release((ITypeLib2 *)This);
+}
+
+static HRESULT WINAPI ITypeLibComp_fnBind(
+ ITypeComp * iface,
+ OLECHAR * szName,
+ ULONG lHash,
+ WORD wFlags,
+ ITypeInfo ** ppTInfo,
+ DESCKIND * pDescKind,
+ BINDPTR * pBindPtr)
+{
+ ITypeLibImpl *This = impl_from_ITypeComp(iface);
+ ITypeInfoImpl *pTypeInfo;
+
+ TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
+
+ *pDescKind = DESCKIND_NONE;
+ pBindPtr->lptcomp = NULL;
+ *ppTInfo = NULL;
+
+ for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
+ {
+ TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
+
+ /* FIXME: check wFlags here? */
+ /* FIXME: we should use a hash table to look this info up using lHash
+ * instead of an O(n) search */
+ if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
+ (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
+ {
+ if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
+ {
+ *pDescKind = DESCKIND_TYPECOMP;
+ pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
+ ITypeComp_AddRef(pBindPtr->lptcomp);
+ TRACE("module or enum: %s\n", debugstr_w(szName));
+ return S_OK;
+ }
+ }
+
+ if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
+ (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
+ {
+ ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
+ HRESULT hr;
+
+ hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
+ if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
+ {
+ TRACE("found in module or in enum: %s\n", debugstr_w(szName));
+ return S_OK;
+ }
+ }
+
+ if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
+ (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
+ {
+ ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
+ HRESULT hr;
+ ITypeInfo *subtypeinfo;
+ BINDPTR subbindptr;
+ DESCKIND subdesckind;
+
+ hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
+ &subtypeinfo, &subdesckind, &subbindptr);
+ if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
+ {
+ TYPEDESC tdesc_appobject =
+ {
+ {
+ (TYPEDESC *)pTypeInfo->hreftype
+ },
+ VT_USERDEFINED
+ };
+ const VARDESC vardesc_appobject =
+ {
+ -2, /* memid */
+ NULL, /* lpstrSchema */
+ {
+ 0 /* oInst */
+ },
+ {
+ /* ELEMDESC */
+ {
+ /* TYPEDESC */
+ {
+ &tdesc_appobject
+ },
+ VT_PTR
+ },
+ },
+ 0, /* wVarFlags */
+ VAR_STATIC /* varkind */
+ };
+
+ TRACE("found in implicit app object: %s\n", debugstr_w(szName));
+
+ /* cleanup things filled in by Bind call so we can put our
+ * application object data in there instead */
+ switch (subdesckind)
+ {
+ case DESCKIND_FUNCDESC:
+ ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
+ break;
+ case DESCKIND_VARDESC:
+ ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
+ break;
+ default:
+ break;
+ }
+ if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
+
+ if (pTypeInfo->hreftype == -1)
+ FIXME("no hreftype for interface %p\n", pTypeInfo);
+
+ hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
+ if (FAILED(hr))
+ return hr;
+
+ *pDescKind = DESCKIND_IMPLICITAPPOBJ;
+ *ppTInfo = (ITypeInfo *)pTypeInfo;
+ ITypeInfo_AddRef(*ppTInfo);
+ return S_OK;
+ }
+ }
+ }
+
+ TRACE("name not found %s\n", debugstr_w(szName));
+ return S_OK;
+}
+
+static HRESULT WINAPI ITypeLibComp_fnBindType(
+ ITypeComp * iface,
+ OLECHAR * szName,
+ ULONG lHash,
+ ITypeInfo ** ppTInfo,
+ ITypeComp ** ppTComp)
+{
+ FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
+ return E_NOTIMPL;
+}
+
+static const ITypeCompVtbl tlbtcvt =
+{
+
+ ITypeLibComp_fnQueryInterface,
+ ITypeLibComp_fnAddRef,
+ ITypeLibComp_fnRelease,
+
+ ITypeLibComp_fnBind,
+ ITypeLibComp_fnBindType
+};
+
+/*================== ITypeInfo(2) Methods ===================================*/
+static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
+{
+ ITypeInfoImpl * pTypeInfoImpl;
+
+ pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
+ if (pTypeInfoImpl)
+ {
+ pTypeInfoImpl->lpVtbl = &tinfvt;
+ pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
+ pTypeInfoImpl->ref=1;
+ pTypeInfoImpl->hreftype = -1;
+ }
+ TRACE("(%p)\n", pTypeInfoImpl);
+ return (ITypeInfo2*) pTypeInfoImpl;
+}
+
+/* ITypeInfo::QueryInterface
+ */
+static HRESULT WINAPI ITypeInfo_fnQueryInterface(
+ ITypeInfo2 *iface,
+ REFIID riid,
+ VOID **ppvObject)
+{
+ ITypeLibImpl *This = (ITypeLibImpl *)iface;
+
+ TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
+
+ *ppvObject=NULL;
+ if(IsEqualIID(riid, &IID_IUnknown) ||
+ IsEqualIID(riid,&IID_ITypeInfo)||
+ IsEqualIID(riid,&IID_ITypeInfo2))
+ *ppvObject = This;
+
+ if(*ppvObject){
+ ITypeInfo_AddRef(iface);
+ TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
+ return S_OK;
+ }
+ TRACE("-- Interface: E_NOINTERFACE\n");
+ return E_NOINTERFACE;
+}
+
+/* ITypeInfo::AddRef
+ */
+static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ ULONG ref = InterlockedIncrement(&This->ref);
+
+ ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
+
+ TRACE("(%p)->ref is %lu\n",This, ref);
+ return ref;
+}
+
+/* ITypeInfo::Release
+ */
+static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ ULONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p)->(%lu)\n",This, ref);
+
+ if (ref) {
+ /* We don't release ITypeLib when ref=0 because
+ it means that function is called by ITypeLib2_Release */
+ ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
+ } else {
+ FIXME("destroy child objects\n");
+
+ TRACE("destroying ITypeInfo(%p)\n",This);
+ if (This->Name)
+ {
+ SysFreeString(This->Name);
+ This->Name = 0;
+ }
+
+ if (This->DocString)
+ {
+ SysFreeString(This->DocString);
+ This->DocString = 0;
+ }
+
+ if (This->DllName)
+ {
+ SysFreeString(This->DllName);
+ This->DllName = 0;
+ }
+
+ if (This->next)
+ {
+ ITypeInfo_Release((ITypeInfo*)This->next);
+ }
+
+ HeapFree(GetProcessHeap(),0,This);
+ return 0;
+ }
+ return ref;
+}
+
+/* ITypeInfo::GetTypeAttr
+ *
+ * Retrieves a TYPEATTR structure that contains the attributes of the type
+ * description.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
+ LPTYPEATTR *ppTypeAttr)
+{
+ const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ SIZE_T size;
+
+ TRACE("(%p)\n",This);
+
+ size = sizeof(**ppTypeAttr);
+ if (This->TypeAttr.typekind == TKIND_ALIAS)
+ size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
+
+ *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
+ if (!*ppTypeAttr)
+ return E_OUTOFMEMORY;
+
+ memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
+
+ if (This->TypeAttr.typekind == TKIND_ALIAS)
+ TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
+ &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
+
+ if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
+ (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
+ funcs */
+ (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
+ (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
+ }
+ return S_OK;
+}
+
+/* ITypeInfo::GetTypeComp
+ *
+ * Retrieves the ITypeComp interface for the type description, which enables a
+ * client compiler to bind to the type description's members.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
+ ITypeComp * *ppTComp)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+
+ TRACE("(%p)->(%p) stub!\n", This, ppTComp);
+
+ *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
+ ITypeComp_AddRef(*ppTComp);
+ return S_OK;
+}
+
+static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
+{
+ SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
+ if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
+ size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
+ return size;
+}
+
+static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
+{
+ memcpy(dest, src, sizeof(ELEMDESC));
+ *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
+ if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
+ {
+ const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
+ PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
+ *buffer += sizeof(PARAMDESCEX);
+ memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
+ VariantInit(&pparamdescex_dest->varDefaultValue);
+ return VariantCopy(&pparamdescex_dest->varDefaultValue,
+ (VARIANTARG *)&pparamdescex_src->varDefaultValue);
+ }
+ else
+ dest->u.paramdesc.pparamdescex = NULL;
+ return S_OK;
+}
+
+static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
+{
+ if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
+ VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
+}
+
+static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
+{
+ FUNCDESC *dest;
+ char *buffer;
+ SIZE_T size = sizeof(*src);
+ SHORT i;
+ HRESULT hr;
+
+ size += sizeof(*src->lprgscode) * src->cScodes;
+ size += TLB_SizeElemDesc(&src->elemdescFunc);
+ for (i = 0; i < src->cParams; i++)
+ {
+ size += sizeof(ELEMDESC);
+ size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
+ }
+
+ dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
+ if (!dest) return E_OUTOFMEMORY;
+
+ memcpy(dest, src, sizeof(FUNCDESC));
+ buffer = (char *)(dest + 1);
+
+ dest->lprgscode = (SCODE *)buffer;
+ memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
+ buffer += sizeof(*src->lprgscode) * src->cScodes;
+
+ hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
+ if (FAILED(hr))
+ {
+ SysFreeString((BSTR)dest);
+ return hr;
+ }
+
+ dest->lprgelemdescParam = (ELEMDESC *)buffer;
+ buffer += sizeof(ELEMDESC) * src->cParams;
+ for (i = 0; i < src->cParams; i++)
+ {
+ hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
+ if (FAILED(hr))
+ break;
+ }
+ if (FAILED(hr))
+ {
+ /* undo the above actions */
+ for (i = i - 1; i >= 0; i--)
+ TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
+ TLB_FreeElemDesc(&dest->elemdescFunc);
+ SysFreeString((BSTR)dest);
+ return hr;
+ }
+
+ /* special treatment for dispinterfaces: this makes functions appear
+ * to return their [retval] value when it is really returning an
+ * HRESULT */
+ if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
+ {
+ if (dest->cParams &&
+ (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
+ {
+ ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
+ if (elemdesc->tdesc.vt != VT_PTR)
+ {
+ ERR("elemdesc should have started with VT_PTR instead of:\n");
+ if (ERR_ON(ole))
+ dump_ELEMDESC(elemdesc);
+ return E_UNEXPECTED;
+ }
+
+ /* copy last parameter to the return value. we are using a flat
+ * buffer so there is no danger of leaking memory in
+ * elemdescFunc */
+ dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
+
+ /* remove the last parameter */
+ dest->cParams--;
+ }
+ else
+ /* otherwise this function is made to appear to have no return
+ * value */
+ dest->elemdescFunc.tdesc.vt = VT_VOID;
+
+ }
+
+ *dest_ptr = dest;
+ return S_OK;
+}
+
+HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ const TLBFuncDesc *pFDesc;
+ int i;
+
+ for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
+ ;
+
+ if (pFDesc)
+ {
+ *ppFuncDesc = &pFDesc->funcdesc;
+ return S_OK;
+ }
+
+ return E_INVALIDARG;
+}
+
+/* ITypeInfo::GetFuncDesc
+ *
+ * Retrieves the FUNCDESC structure that contains information about a
+ * specified function.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
+ LPFUNCDESC *ppFuncDesc)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ const FUNCDESC *internal_funcdesc;
+ HRESULT hr;
+
+ TRACE("(%p) index %d\n", This, index);
+
+ hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
+ if (FAILED(hr))
+ return hr;
+
+ return TLB_AllocAndInitFuncDesc(
+ internal_funcdesc,
+ ppFuncDesc,
+ This->TypeAttr.typekind == TKIND_DISPATCH);
+}
+
+static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
+{
+ VARDESC *dest;
+ char *buffer;
+ SIZE_T size = sizeof(*src);
+ HRESULT hr;
+
+ if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
+ if (src->varkind == VAR_CONST)
+ size += sizeof(VARIANT);
+ size += TLB_SizeElemDesc(&src->elemdescVar);
+
+ dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
+ if (!dest) return E_OUTOFMEMORY;
+
+ *dest = *src;
+ buffer = (char *)(dest + 1);
+ if (src->lpstrSchema)
+ {
+ int len;
+ dest->lpstrSchema = (LPOLESTR)buffer;
+ len = strlenW(src->lpstrSchema);
+ memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
+ buffer += (len + 1) * sizeof(WCHAR);
+ }
+
+ if (src->varkind == VAR_CONST)
+ {
+ HRESULT hr;
+
+ dest->u.lpvarValue = (VARIANT *)buffer;
+ *dest->u.lpvarValue = *src->u.lpvarValue;
+ buffer += sizeof(VARIANT);
+ VariantInit(dest->u.lpvarValue);
+ hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
+ if (FAILED(hr))
+ {
+ SysFreeString((BSTR)dest_ptr);
+ return hr;
+ }
+ }
+ hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
+ if (FAILED(hr))
+ {
+ if (src->varkind == VAR_CONST)
+ VariantClear(dest->u.lpvarValue);
+ SysFreeString((BSTR)dest);
+ return hr;
+ }
+ *dest_ptr = dest;
+ return S_OK;
+}
+
+/* ITypeInfo::GetVarDesc
+ *
+ * Retrieves a VARDESC structure that describes the specified variable.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
+ LPVARDESC *ppVarDesc)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ int i;
+ const TLBVarDesc *pVDesc;
+
+ TRACE("(%p) index %d\n", This, index);
+
+ for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
+ ;
+
+ if (pVDesc)
+ return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
+
+ return E_INVALIDARG;
+}
+
+/* ITypeInfo_GetNames
+ *
+ * Retrieves the variable with the specified member ID (or the name of the
+ * property or method and its parameters) that correspond to the specified
+ * function ID.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
+ BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBFuncDesc * pFDesc;
+ TLBVarDesc * pVDesc;
+ int i;
+ TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
+ for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
+ if(pFDesc)
+ {
+ /* function found, now return function and parameter names */
+ for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
+ {
+ if(!i)
+ *rgBstrNames=SysAllocString(pFDesc->Name);
+ else
+ rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
+ }
+ *pcNames=i;
+ }
+ else
+ {
+ for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
+ if(pVDesc)
+ {
+ *rgBstrNames=SysAllocString(pVDesc->Name);
+ *pcNames=1;
+ }
+ else
+ {
+ if(This->TypeAttr.cImplTypes &&
+ (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
+ /* recursive search */
+ ITypeInfo *pTInfo;
+ HRESULT result;
+ result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
+ &pTInfo);
+ if(SUCCEEDED(result))
+ {
+ result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
+ ITypeInfo_Release(pTInfo);
+ return result;
+ }
+ WARN("Could not search inherited interface!\n");
+ }
+ else
+ {
+ WARN("no names found\n");
+ }
+ *pcNames=0;
+ return TYPE_E_ELEMENTNOTFOUND;
+ }
+ }
+ return S_OK;
+}
+
+
+/* ITypeInfo::GetRefTypeOfImplType
+ *
+ * If a type description describes a COM class, it retrieves the type
+ * description of the implemented interface types. For an interface,
+ * GetRefTypeOfImplType returns the type information for inherited interfaces,
+ * if any exist.
+ *
+ */
+static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
+ ITypeInfo2 *iface,
+ UINT index,
+ HREFTYPE *pRefType)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ int i;
+ HRESULT hr = S_OK;
+ TLBImplType *pImpl = This->impltypelist;
+
+ TRACE("(%p) index %d\n", This, index);
+ if (TRACE_ON(ole)) dump_TypeInfo(This);
+
+ if(index==(UINT)-1)
+ {
+ /* only valid on dual interfaces;
+ retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
+ */
+ if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
+
+ if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
+ This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
+ {
+ *pRefType = -1;
+ }
+ else
+ {
+ hr = TYPE_E_ELEMENTNOTFOUND;
+ }
+ }
+ else
+ {
+ /* get element n from linked list */
+ for(i=0; pImpl && i<index; i++)
+ {
+ pImpl = pImpl->next;
+ }
+
+ if (pImpl)
+ *pRefType = pImpl->hRef;
+ else
+ hr = TYPE_E_ELEMENTNOTFOUND;
+ }
+
+ if(TRACE_ON(ole))
+ {
+ if(SUCCEEDED(hr))
+ TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
+ else
+ TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
+ }
+
+ return hr;
+}
+
+/* ITypeInfo::GetImplTypeFlags
+ *
+ * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
+ * or base interface in a type description.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
+ UINT index, INT *pImplTypeFlags)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ int i;
+ TLBImplType *pImpl;
+
+ TRACE("(%p) index %d\n", This, index);
+ for(i=0, pImpl=This->impltypelist; i<index && pImpl;
+ i++, pImpl=pImpl->next)
+ ;
+ if(i==index && pImpl){
+ *pImplTypeFlags=pImpl->implflags;
+ return S_OK;
+ }
+ *pImplTypeFlags=0;
+ return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* GetIDsOfNames
+ * Maps between member names and member IDs, and parameter names and
+ * parameter IDs.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
+ LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBFuncDesc * pFDesc;
+ TLBVarDesc * pVDesc;
+ HRESULT ret=S_OK;
+
+ TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
+ cNames);
+ for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
+ int i, j;
+ if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
+ if(cNames) *pMemId=pFDesc->funcdesc.memid;
+ for(i=1; i < cNames; i++){
+ for(j=0; j<pFDesc->funcdesc.cParams; j++)
+ if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
+ break;
+ if( j<pFDesc->funcdesc.cParams)
+ pMemId[i]=j;
+ else
+ ret=DISP_E_UNKNOWNNAME;
+ };
+ return ret;
+ }
+ }
+ for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
+ if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
+ if(cNames) *pMemId=pVDesc->vardesc.memid;
+ return ret;
+ }
+ }
+ /* not found, see if this is and interface with an inheritance */
+ if(This->TypeAttr.cImplTypes &&
+ (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
+ /* recursive search */
+ ITypeInfo *pTInfo;
+ ret=ITypeInfo_GetRefTypeInfo(iface,
+ This->impltypelist->hRef, &pTInfo);
+ if(SUCCEEDED(ret)){
+ ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
+ ITypeInfo_Release(pTInfo);
+ return ret;
+ }
+ WARN("Could not search inherited interface!\n");
+ } else
+ WARN("no names found\n");
+ return DISP_E_UNKNOWNNAME;
+}
+
+/* ITypeInfo::Invoke
+ *
+ * Invokes a method, or accesses a property of an object, that implements the
+ * interface described by the type description.
+ */
+DWORD
+_invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
+ DWORD res;
+
+ if (TRACE_ON(ole)) {
+ int i;
+ TRACE("Calling %p(",func);
+ for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
+ TRACE(")\n");
+ }
+
+ switch (callconv) {
+ case CC_STDCALL:
+
+ switch (nrargs) {
+ case 0:
+ res = func();
+ break;
+ case 1:
+ res = func(args[0]);
+ break;
+ case 2:
+ res = func(args[0],args[1]);
+ break;
+ case 3:
+ res = func(args[0],args[1],args[2]);
+ break;
+ case 4:
+ res = func(args[0],args[1],args[2],args[3]);
+ break;
+ case 5:
+ res = func(args[0],args[1],args[2],args[3],args[4]);
+ break;
+ case 6:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
+ break;
+ case 7:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
+ break;
+ case 8:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
+ break;
+ case 9:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
+ break;
+ case 10:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
+ break;
+ case 11:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
+ break;
+ case 12:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
+ break;
+ case 13:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
+ break;
+ case 14:
+ res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
+ break;
+ default:
+ FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
+ res = -1;
+ break;
+ }
+ break;
+ default:
+ FIXME("unsupported calling convention %d\n",callconv);
+ res = -1;
+ break;
+ }
+ TRACE("returns %08lx\n",res);
+ return res;
+}
+
+extern int _argsize(DWORD vt);
+
+/****************************************************************************
+ * Helper functions for Dispcall / Invoke, which copies one variant
+ * with target type onto the argument stack.
+ */
+static HRESULT
+_copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
+ DWORD *argpos, VARIANT *arg, VARTYPE vt
+) {
+ UINT arglen = _argsize(vt)*sizeof(DWORD);
+ VARIANT va;
+
+ if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
+ memcpy(argpos,&arg,sizeof(void*));
+ return S_OK;
+ }
+
+ if (V_VT(arg) == vt) {
+ memcpy(argpos, &V_I4(arg), arglen);
+ return S_OK;
+ }
+
+ if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
+ memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
+ return S_OK;
+ }
+
+ if (vt == VT_VARIANT) {
+ memcpy(argpos, arg, arglen);
+ return S_OK;
+ }
+ /* Deref BYREF vars if there is need */
+ if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
+ memcpy(argpos,(void*)V_I4(arg), arglen);
+ return S_OK;
+ }
+ if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
+ /* in this context, if the type lib specifies IUnknown*, giving an
+ IDispatch* is correct; so, don't invoke VariantChangeType */
+ memcpy(argpos,&V_I4(arg), arglen);
+ return S_OK;
+ }
+ if ((vt == VT_PTR) && tdesc)
+ return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
+
+ if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
+ ITypeInfo *tinfo2 = NULL;
+ TYPEATTR *tattr = NULL;
+ HRESULT hres;
+
+ hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
+ if (hres) {
+ 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));
+ memcpy(argpos, &V_I4(arg), 4);
+ return S_OK;
+ }
+ hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
+ if( hres )
+ {
+ ERR("GetTypeAttr failed\n");
+ ITypeInfo_Release(tinfo2);
+ return hres;
+ }
+ switch (tattr->typekind) {
+ case TKIND_ENUM:
+ switch ( V_VT( arg ) ) {
+ case VT_I2:
+ *argpos = V_I2(arg);
+ hres = S_OK;
+ break;
+ case VT_I4:
+ memcpy(argpos, &V_I4(arg), 4);
+ hres = S_OK;
+ break;
+ case VT_BYREF|VT_I4:
+ memcpy(argpos, V_I4REF(arg), 4);
+ hres = S_OK;
+ break;
+ default:
+ FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
+ hres = E_FAIL;
+ break;
+ }
+ break;
+
+ case TKIND_ALIAS:
+ tdesc = &(tattr->tdescAlias);
+ hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
+ break;
+
+ case TKIND_INTERFACE:
+ if (V_VT(arg) == VT_DISPATCH) {
+ IDispatch *disp;
+ if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
+ memcpy(argpos, &V_DISPATCH(arg), 4);
+ hres = S_OK;
+ break;
+ }
+ hres=IUnknown_QueryInterface(V_DISPATCH(arg),
+ &IID_IDispatch,(LPVOID*)&disp);
+ if (SUCCEEDED(hres)) {
+ memcpy(argpos,&disp,4);
+ IUnknown_Release(V_DISPATCH(arg));
+ hres = S_OK;
+ break;
+ }
+ FIXME("Failed to query IDispatch interface from %s while "
+ "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
+ hres = E_FAIL;
+ break;
+ }
+ if (V_VT(arg) == VT_UNKNOWN) {
+ memcpy(argpos, &V_UNKNOWN(arg), 4);
+ hres = S_OK;
+ break;
+ }
+ FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
+ V_VT(arg),debugstr_guid(&(tattr->guid)));
+ hres = E_FAIL;
+ break;
+
+ case TKIND_DISPATCH:
+ if (V_VT(arg) == VT_DISPATCH) {
+ memcpy(argpos, &V_DISPATCH(arg), 4);
+ hres = S_OK;
+ }
+ else {
+ hres = E_FAIL;
+ FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
+ }
+ break;
+ case TKIND_RECORD:
+ FIXME("TKIND_RECORD unhandled.\n");
+ hres = E_FAIL;
+ break;
+ default:
+ FIXME("TKIND %d unhandled.\n",tattr->typekind);
+ hres = E_FAIL;
+ break;
+ }
+ ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
+ ITypeInfo_Release(tinfo2);
+ return hres;
+ }
+
+ VariantInit(&va);
+ if (VariantChangeType(&va,arg,0,vt)==S_OK) {
+ memcpy(argpos,&V_I4(&va), arglen);
+ FIXME("Should not use VariantChangeType here."
+ " (conversion from 0x%x -> 0x%x) %08lx\n",
+ V_VT(arg), vt, *argpos
+ );
+ return S_OK;
+ }
+ ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
+ return E_FAIL;
+}
+
+static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
+{
+ HRESULT hr = S_OK;
+ ITypeInfo *tinfo2 = NULL;
+ TYPEATTR *tattr = NULL;
+
+ hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
+ if (hr)
+ {
+ ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
+ "hr = 0x%08lx\n",
+ tdesc->u.hreftype, hr);
+ return hr;
+ }
+ hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
+ if (hr)
+ {
+ ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
+ ITypeInfo_Release(tinfo2);
+ return hr;
+ }
+
+ switch (tattr->typekind)
+ {
+ case TKIND_ENUM:
+ *vt |= VT_I4;
+ break;
+
+ case TKIND_ALIAS:
+ tdesc = &tattr->tdescAlias;
+ hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
+ break;
+
+ case TKIND_INTERFACE:
+ if (IsEqualIID(&IID_IDispatch, &tattr->guid))
+ *vt |= VT_DISPATCH;
+ else
+ *vt |= VT_UNKNOWN;
+ break;
+
+ case TKIND_DISPATCH:
+ *vt |= VT_DISPATCH;
+ break;
+
+ case TKIND_RECORD:
+ FIXME("TKIND_RECORD unhandled.\n");
+ hr = E_NOTIMPL;
+ break;
+
+ case TKIND_UNION:
+ FIXME("TKIND_RECORD unhandled.\n");
+ hr = E_NOTIMPL;
+ break;
+
+ default:
+ FIXME("TKIND %d unhandled.\n",tattr->typekind);
+ hr = E_NOTIMPL;
+ break;
+ }
+ ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
+ ITypeInfo_Release(tinfo2);
+ return hr;
+}
+
+static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
+{
+ HRESULT hr = S_OK;
+
+ /* enforce only one level of pointer indirection */
+ if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
+ {
+ tdesc = tdesc->u.lptdesc;
+
+ /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
+ * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
+ * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
+ if ((tdesc->vt == VT_USERDEFINED) ||
+ ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
+ {
+ VARTYPE vt_userdefined = 0;
+ TYPEDESC *tdesc_userdefined = tdesc;
+ if (tdesc->vt == VT_PTR)
+ {
+ vt_userdefined = VT_BYREF;
+ tdesc_userdefined = tdesc->u.lptdesc;
+ }
+ hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
+ if ((hr == S_OK) &&
+ (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
+ ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
+ {
+ *vt |= vt_userdefined;
+ return S_OK;
+ }
+ }
+ *vt = VT_BYREF;
+ }
+
+ switch (tdesc->vt)
+ {
+ case VT_HRESULT:
+ *vt |= VT_ERROR;
+ break;
+ case VT_USERDEFINED:
+ hr = userdefined_to_variantvt(tinfo, tdesc, vt);
+ break;
+ case VT_PTR:
+ ERR("cannot convert VT_PTR into variant VT\n");
+ hr = E_FAIL;
+ break;
+ default:
+ *vt |= tdesc->vt;
+ break;
+ }
+ return hr;
+}
+
+/***********************************************************************
+ * DispCallFunc (OLEAUT32.@)
+ *
+ * Invokes a function of the specifed calling convention, passing the
+ * specified arguments and returns the result.
+ *
+ * PARAMS
+ * pvInstance [I] Optional pointer to the instance whose function to invoke.
+ * oVft [I] The offset in the vtable. See notes.
+ * cc [I] Calling convention of the function to call.
+ * vtReturn [I] The return type of the function.
+ * cActuals [I] Number of parameters.
+ * prgvt [I] The types of the parameters to pass. This is used for sizing only.
+ * prgpvarg [I] The arguments to pass.
+ * pvargResult [O] The return value of the function. Can be NULL.
+ *
+ * RETURNS
+ * Success: S_OK.
+ * Failure: HRESULT code.
+ *
+ * NOTES
+ * The HRESULT return value of this function is not affected by the return
+ * value of the user supplied function, which is returned in pvargResult.
+ *
+ * If pvInstance is NULL then a non-object function is to be called and oVft
+ * is the address of the function to call.
+ *
+ * The cc parameter can be one of the following values:
+ *|CC_FASTCALL
+ *|CC_CDECL
+ *|CC_PASCAL
+ *|CC_STDCALL
+ *|CC_FPFASTCALL
+ *|CC_SYSCALL
+ *|CC_MPWCDECL
+ *|CC_MPWPASCAL
+ *
+ * BUGS
+ * Native accepts arguments in the reverse order. I.e. the first item in the
+ * prgpvarg array is the last argument in the C/C++ declaration of the
+ * function to be called.
+ */
+HRESULT WINAPI
+DispCallFunc(
+ void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
+ VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
+{
+ int i, argsize, argspos;
+ DWORD *args;
+ HRESULT hres;
+
+ TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
+ pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
+ pvargResult, V_VT(pvargResult));
+
+ argsize = 0;
+ if (pvInstance)
+ argsize++; /* for This pointer */
+
+ for (i=0;i<cActuals;i++)
+ {
+ TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
+ dump_Variant(prgpvarg[i]);
+ argsize += _argsize(prgvt[i]);
+ }
+ args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
+
+ argspos = 0;
+ if (pvInstance)
+ {
+ args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
+ argspos++;
+ }
+
+ for (i=0;i<cActuals;i++)
+ {
+ VARIANT *arg = prgpvarg[i];
+ TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
+ memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
+ argspos += _argsize(prgvt[i]);
+ }
+
+ if (pvInstance)
+ {
+ FARPROC *vtable = *(FARPROC**)pvInstance;
+ hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
+ }
+ else
+ /* if we aren't invoking an object then the function pointer is stored
+ * in oVft */
+ hres = _invoke((FARPROC)oVft, cc, argsize, args);
+
+ if (pvargResult && (vtReturn != VT_EMPTY))
+ {
+ TRACE("Method returned 0x%08lx\n",hres);
+ V_VT(pvargResult) = vtReturn;
+ V_UI4(pvargResult) = hres;
+ }
+
+ HeapFree(GetProcessHeap(),0,args);
+ return S_OK;
+}
+
+static HRESULT WINAPI ITypeInfo_fnInvoke(
+ ITypeInfo2 *iface,
+ VOID *pIUnk,
+ MEMBERID memid,
+ UINT16 wFlags,
+ DISPPARAMS *pDispParams,
+ VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo,
+ UINT *pArgErr)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ int i;
+ unsigned int var_index;
+ TYPEKIND type_kind;
+ HRESULT hres;
+ const TLBFuncDesc *pFuncInfo;
+
+ TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
+ This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
+ );
+ dump_DispParms(pDispParams);
+
+ /* we do this instead of using GetFuncDesc since it will return a fake
+ * FUNCDESC for dispinterfaces and we want the real function description */
+ for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
+ if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
+ break;
+
+ if (pFuncInfo) {
+ const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
+
+ if (TRACE_ON(ole))
+ {
+ TRACE("invoking:\n");
+ dump_TLBFuncDesc(pFuncInfo);
+ }
+
+ switch (func_desc->funckind) {
+ case FUNC_PUREVIRTUAL:
+ case FUNC_VIRTUAL: {
+ DWORD res;
+ int numargs, numargs2, argspos, args2pos;
+ DWORD *args , *args2;
+ VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
+ memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
+
+ hres = S_OK;
+ numargs = 1; /* sizeof(thisptr) */
+ numargs2 = 0;
+ for (i = 0; i < func_desc->cParams; i++) {
+ TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
+
+ numargs += _argsize(tdesc->vt);
+ if (i>=pDispParams->cArgs) { /* arguments to return */
+ if (tdesc->vt == VT_PTR) {
+ numargs2 += _argsize(tdesc->u.lptdesc->vt);
+ } else {
+ FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
+ numargs2 += _argsize(tdesc->vt);
+ }
+ }
+ }
+
+ args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
+ args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
+
+ args[0] = (DWORD)pIUnk;
+ argspos = 1; args2pos = 0;
+ for (i = 0; i < func_desc->cParams; i++) {
+ ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
+ TYPEDESC *tdesc = &(elemdesc->tdesc);
+ USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
+ int arglen = _argsize(tdesc->vt);
+
+ if (i<pDispParams->cArgs) {
+ VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
+
+ if (paramFlags & PARAMFLAG_FOPT) {
+ if(i < func_desc->cParams - func_desc->cParamsOpt)
+ ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
+ if(V_VT(arg) == VT_EMPTY
+ || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
+ /* FIXME: Documentation says that we do this when parameter is left unspecified.
+ How to determine it? */
+
+ if(paramFlags & PARAMFLAG_FHASDEFAULT)
+ FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
+ V_VT(arg) = VT_ERROR;
+ V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
+ arglen = _argsize(VT_ERROR);
+ }
+ }
+ hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
+ if (FAILED(hres)) goto func_fail;
+ argspos += arglen;
+ } else if (paramFlags & PARAMFLAG_FOPT) {
+ VARIANT *arg = &rgvarg[i];
+
+ if (i < func_desc->cParams - func_desc->cParamsOpt)
+ ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
+ if (paramFlags & PARAMFLAG_FHASDEFAULT)
+ FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
+
+ V_VT(arg) = VT_ERROR;
+ V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
+ arglen = _argsize(VT_ERROR);
+ hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
+ if (FAILED(hres)) goto func_fail;
+ argspos += arglen;
+ } else {
+ if (tdesc->vt == VT_PTR)
+ arglen = _argsize(tdesc->u.lptdesc->vt);
+ else
+ FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
+
+ /* Supply pointers for the rest, so propertyget works*/
+ args[argspos] = (DWORD)&args2[args2pos];
+
+ /* If pointer to variant, pass reference it. */
+ if ((tdesc->vt == VT_PTR) &&
+ (tdesc->u.lptdesc->vt == VT_VARIANT) &&
+ pVarResult
+ )
+ args[argspos]= (DWORD)pVarResult;
+ argspos += 1;
+ args2pos += arglen;
+ }
+ }
+ if (func_desc->cParamsOpt < 0)
+ FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
+
+ res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
+ func_desc->callconv,
+ numargs,
+ args
+ );
+
+ if (pVarResult) {
+ for (i = 0; i < func_desc->cParams; i++) {
+ USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
+ if (wParamFlags & PARAMFLAG_FRETVAL) {
+ ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
+ TYPEDESC *tdesc = &elemdesc->tdesc;
+ VARIANTARG varresult;
+ V_VT(&varresult) = 0;
+ hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
+ if (hres)
+ break;
+ /* FIXME: this is really messy - we should keep the
+ * args in VARIANTARGs rather than a DWORD array */
+ memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
+ if (TRACE_ON(ole))
+ {
+ TRACE("varresult: ");
+ dump_Variant(&varresult);
+ }
+ hres = VariantCopyInd(pVarResult, &varresult);
+ /* free data stored in varresult. Note that
+ * VariantClear doesn't do what we want because we are
+ * working with byref types. */
+ /* FIXME: clear safearrays, bstrs, records and
+ * variants here too */
+ if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
+ (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
+ {
+ if(*V_UNKNOWNREF(&varresult))
+ IUnknown_Release(*V_UNKNOWNREF(&varresult));
+ }
+ break;
+ }
+ }
+ }
+
+ if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
+ WARN("invoked function failed with error 0x%08lx\n", res);
+ hres = DISP_E_EXCEPTION;
+ if (pExcepInfo) pExcepInfo->scode = res;
+ }
+func_fail:
+ HeapFree(GetProcessHeap(), 0, rgvarg);
+ HeapFree(GetProcessHeap(),0,args2);
+ HeapFree(GetProcessHeap(),0,args);
+ break;
+ }
+ case FUNC_DISPATCH: {
+ IDispatch *disp;
+
+ hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
+ if (SUCCEEDED(hres)) {
+ FIXME("Calling Invoke in IDispatch iface. untested!\n");
+ hres = IDispatch_Invoke(
+ disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
+ pVarResult,pExcepInfo,pArgErr
+ );
+ if (FAILED(hres))
+ FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
+ IDispatch_Release(disp);
+ } else
+ FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
+ break;
+ }
+ default:
+ FIXME("Unknown function invocation type %d\n", func_desc->funckind);
+ hres = E_FAIL;
+ break;
+ }
+
+ TRACE("-- 0x%08lx\n", hres);
+ return hres;
+
+ } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
+ VARDESC *var_desc;
+
+ hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
+ if(FAILED(hres)) return hres;
+
+ FIXME("varseek: Found memid, but variable-based invoking not supported\n");
+ dump_VARDESC(var_desc);
+ ITypeInfo2_ReleaseVarDesc(iface, var_desc);
+ return E_NOTIMPL;
+ }
+
+ /* not found, look for it in inherited interfaces */
+ ITypeInfo2_GetTypeKind(iface, &type_kind);
+ if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
+ HREFTYPE ref_type;
+ if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
+ /* recursive search */
+ ITypeInfo *pTInfo;
+ hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
+ if(SUCCEEDED(hres)){
+ hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
+ ITypeInfo_Release(pTInfo);
+ return hres;
+ }
+ WARN("Could not search inherited interface!\n");
+ }
+ }
+ ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+/* ITypeInfo::GetDocumentation
+ *
+ * Retrieves the documentation string, the complete Help file name and path,
+ * and the context ID for the Help topic for a specified type description.
+ *
+ * (Can be tested by the Visual Basic Editor in Word for instance.)
+ */
+static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
+ MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
+ DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBFuncDesc * pFDesc;
+ TLBVarDesc * pVDesc;
+ TRACE("(%p) memid %ld Name(%p) DocString(%p)"
+ " HelpContext(%p) HelpFile(%p)\n",
+ This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
+ if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
+ if(pBstrName)
+ *pBstrName=SysAllocString(This->Name);
+ if(pBstrDocString)
+ *pBstrDocString=SysAllocString(This->DocString);
+ if(pdwHelpContext)
+ *pdwHelpContext=This->dwHelpContext;
+ if(pBstrHelpFile)
+ *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
+ return S_OK;
+ }else {/* for a member */
+ for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
+ if(pFDesc->funcdesc.memid==memid){
+ if(pBstrName)
+ *pBstrName = SysAllocString(pFDesc->Name);
+ if(pBstrDocString)
+ *pBstrDocString=SysAllocString(pFDesc->HelpString);
+ if(pdwHelpContext)
+ *pdwHelpContext=pFDesc->helpcontext;
+ return S_OK;
+ }
+ for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
+ if(pVDesc->vardesc.memid==memid){
+ if(pBstrName)
+ *pBstrName = SysAllocString(pVDesc->Name);
+ if(pBstrDocString)
+ *pBstrDocString=SysAllocString(pVDesc->HelpString);
+ if(pdwHelpContext)
+ *pdwHelpContext=pVDesc->HelpContext;
+ return S_OK;
+ }
+ }
+ WARN("member %ld not found\n", memid);
+ return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo::GetDllEntry
+ *
+ * Retrieves a description or specification of an entry point for a function
+ * in a DLL.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
+ INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
+ WORD *pwOrdinal)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBFuncDesc *pFDesc;
+
+ TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
+
+ if (pBstrDllName) *pBstrDllName = NULL;
+ if (pBstrName) *pBstrName = NULL;
+ if (pwOrdinal) *pwOrdinal = 0;
+
+ if (This->TypeAttr.typekind != TKIND_MODULE)
+ return TYPE_E_BADMODULEKIND;
+
+ for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
+ if(pFDesc->funcdesc.memid==memid){
+ dump_TypeInfo(This);
+ dump_TLBFuncDescOne(pFDesc);
+
+ if (pBstrDllName)
+ *pBstrDllName = SysAllocString(This->DllName);
+
+ if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
+ if (pBstrName)
+ *pBstrName = SysAllocString(pFDesc->Entry);
+ if (pwOrdinal)
+ *pwOrdinal = -1;
+ return S_OK;
+ }
+ if (pBstrName)
+ *pBstrName = NULL;
+ if (pwOrdinal)
+ *pwOrdinal = (DWORD)pFDesc->Entry;
+ return S_OK;
+ }
+ return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo::GetRefTypeInfo
+ *
+ * If a type description references other type descriptions, it retrieves
+ * the referenced type descriptions.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
+ ITypeInfo2 *iface,
+ HREFTYPE hRefType,
+ ITypeInfo **ppTInfo)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ HRESULT result = E_FAIL;
+
+ if ((This->hreftype != -1) && (This->hreftype == hRefType))
+ {
+ *ppTInfo = (ITypeInfo *)&This->lpVtbl;
+ ITypeInfo_AddRef(*ppTInfo);
+ result = S_OK;
+ }
+ else if (hRefType == -1 &&
+ (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
+ (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
+ {
+ /* when we meet a DUAL dispinterface, we must create the interface
+ * version of it.
+ */
+ ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
+
+
+ /* the interface version contains the same information as the dispinterface
+ * copy the contents of the structs.
+ */
+ *pTypeInfoImpl = *This;
+ pTypeInfoImpl->ref = 1;
+
+ /* change the type to interface */
+ pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
+
+ *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
+
+ ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
+
+ result = S_OK;
+
+ } else {
+ TLBRefType *pRefType;
+ for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
+ if(pRefType->reference == hRefType)
+ break;
+ }
+ if(!pRefType)
+ FIXME("Can't find pRefType for ref %lx\n", hRefType);
+ if(pRefType && hRefType != -1) {
+ ITypeLib *pTLib = NULL;
+
+ if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
+ UINT Index;
+ result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
+ } else {
+ if(pRefType->pImpTLInfo->pImpTypeLib) {
+ TRACE("typeinfo in imported typelib that is already loaded\n");
+ pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
+ ITypeLib2_AddRef((ITypeLib*) pTLib);
+ result = S_OK;
+ } else {
+ TRACE("typeinfo in imported typelib that isn't already loaded\n");
+ result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
+ pRefType->pImpTLInfo->wVersionMajor,
+ pRefType->pImpTLInfo->wVersionMinor,
+ pRefType->pImpTLInfo->lcid,
+ &pTLib);
+
+ if(!SUCCEEDED(result)) {
+ BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
+ result=LoadTypeLib(libnam, &pTLib);
+ SysFreeString(libnam);
+ }
+ if(SUCCEEDED(result)) {
+ pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
+ ITypeLib2_AddRef(pTLib);
+ }
+ }
+ }
+ if(SUCCEEDED(result)) {
+ if(pRefType->index == TLB_REF_USE_GUID)
+ result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
+ &pRefType->guid,
+ ppTInfo);
+ else
+ result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
+ ppTInfo);
+ }
+ if (pTLib != NULL)
+ ITypeLib2_Release(pTLib);
+ }
+ }
+
+ TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
+ SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
+ return result;
+}
+
+/* ITypeInfo::AddressOfMember
+ *
+ * Retrieves the addresses of static functions or variables, such as those
+ * defined in a DLL.
+ */
+static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
+ MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ HRESULT hr;
+ BSTR dll, entry;
+ WORD ordinal;
+ HMODULE module;
+
+ TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
+
+ hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
+ if (FAILED(hr))
+ return hr;
+
+ module = LoadLibraryW(dll);
+ if (!module)
+ {
+ ERR("couldn't load %s\n", debugstr_w(dll));
+ SysFreeString(dll);
+ if (entry) SysFreeString(entry);
+ return STG_E_FILENOTFOUND;
+ }
+ /* FIXME: store library somewhere where we can free it */
+
+ if (entry)
+ {
+ LPSTR entryA;
+ INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
+ entryA = HeapAlloc(GetProcessHeap(), 0, len);
+ WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
+
+ *ppv = GetProcAddress(module, entryA);
+ if (!*ppv)
+ ERR("function not found %s\n", debugstr_a(entryA));
+
+ HeapFree(GetProcessHeap(), 0, entryA);
+ }
+ else
+ {
+ *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
+ if (!*ppv)
+ ERR("function not found %d\n", ordinal);
+ }
+
+ SysFreeString(dll);
+ if (entry) SysFreeString(entry);
+
+ if (!*ppv)
+ return TYPE_E_DLLFUNCTIONNOTFOUND;
+
+ return S_OK;
+}
+
+/* ITypeInfo::CreateInstance
+ *
+ * Creates a new instance of a type that describes a component object class
+ * (coclass).
+ */
+static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
+ IUnknown *pUnk, REFIID riid, VOID **ppvObj)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ FIXME("(%p) stub!\n", This);
+ return S_OK;
+}
+
+/* ITypeInfo::GetMops
+ *
+ * Retrieves marshalling information.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
+ BSTR *pBstrMops)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ FIXME("(%p) stub!\n", This);
+ return S_OK;
+}
+
+/* ITypeInfo::GetContainingTypeLib
+ *
+ * Retrieves the containing type library and the index of the type description
+ * within that type library.
+ */
+static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
+ ITypeLib * *ppTLib, UINT *pIndex)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+
+ /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
+ if (pIndex) {
+ *pIndex=This->index;
+ TRACE("returning pIndex=%d\n", *pIndex);
+ }
+
+ if (ppTLib) {
+ *ppTLib=(LPTYPELIB )(This->pTypeLib);
+ ITypeLib2_AddRef(*ppTLib);
+ TRACE("returning ppTLib=%p\n", *ppTLib);
+ }
+
+ return S_OK;
+}
+
+/* ITypeInfo::ReleaseTypeAttr
+ *
+ * Releases a TYPEATTR previously returned by GetTypeAttr.
+ *
+ */
+static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
+ TYPEATTR* pTypeAttr)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TRACE("(%p)->(%p)\n", This, pTypeAttr);
+ HeapFree(GetProcessHeap(), 0, pTypeAttr);
+}
+
+/* ITypeInfo::ReleaseFuncDesc
+ *
+ * Releases a FUNCDESC previously returned by GetFuncDesc. *
+ */
+static void WINAPI ITypeInfo_fnReleaseFuncDesc(
+ ITypeInfo2 *iface,
+ FUNCDESC *pFuncDesc)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ SHORT i;
+
+ TRACE("(%p)->(%p)\n", This, pFuncDesc);
+
+ for (i = 0; i < pFuncDesc->cParams; i++)
+ TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
+ TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
+
+ SysFreeString((BSTR)pFuncDesc);
+}
+
+/* ITypeInfo::ReleaseVarDesc
+ *
+ * Releases a VARDESC previously returned by GetVarDesc.
+ */
+static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
+ VARDESC *pVarDesc)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TRACE("(%p)->(%p)\n", This, pVarDesc);
+
+ TLB_FreeElemDesc(&pVarDesc->elemdescVar);
+ if (pVarDesc->varkind == VAR_CONST)
+ VariantClear(pVarDesc->u.lpvarValue);
+ SysFreeString((BSTR)pVarDesc);
+}
+
+/* ITypeInfo2::GetTypeKind
+ *
+ * Returns the TYPEKIND enumeration quickly, without doing any allocations.
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
+ TYPEKIND *pTypeKind)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ *pTypeKind=This->TypeAttr.typekind;
+ TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
+ return S_OK;
+}
+
+/* ITypeInfo2::GetTypeFlags
+ *
+ * Returns the type flags without any allocations. This returns a DWORD type
+ * flag, which expands the type flags without growing the TYPEATTR (type
+ * attribute).
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ *pTypeFlags=This->TypeAttr.wTypeFlags;
+ TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
+ return S_OK;
+}
+
+/* ITypeInfo2::GetFuncIndexOfMemId
+ * Binds to a specific member based on a known DISPID, where the member name
+ * is not known (for example, when binding to a default member).
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
+ MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBFuncDesc *pFuncInfo;
+ int i;
+ HRESULT result;
+
+ for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
+ if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
+ break;
+ if(pFuncInfo) {
+ *pFuncIndex = i;
+ result = S_OK;
+ } else
+ result = TYPE_E_ELEMENTNOTFOUND;
+
+ TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
+ memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
+ return result;
+}
+
+/* TypeInfo2::GetVarIndexOfMemId
+ *
+ * Binds to a specific member based on a known DISPID, where the member name
+ * is not known (for example, when binding to a default member).
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
+ MEMBERID memid, UINT *pVarIndex)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBVarDesc *pVarInfo;
+ int i;
+ HRESULT result;
+ for(i=0, pVarInfo=This->varlist; pVarInfo &&
+ memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
+ ;
+ if(pVarInfo) {
+ *pVarIndex = i;
+ result = S_OK;
+ } else
+ result = TYPE_E_ELEMENTNOTFOUND;
+
+ TRACE("(%p) memid 0x%08lx -> %s\n", This,
+ memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
+ return result;
+}
+
+/* ITypeInfo2::GetCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetCustData(
+ ITypeInfo2 * iface,
+ REFGUID guid,
+ VARIANT *pVarVal)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData;
+
+ for(pCData=This->pCustData; pCData; pCData = pCData->next)
+ if( IsEqualIID(guid, &pCData->guid)) break;
+
+ TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
+
+ if(pCData)
+ {
+ VariantInit( pVarVal);
+ VariantCopy( pVarVal, &pCData->data);
+ return S_OK;
+ }
+ return E_INVALIDARG; /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetFuncCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
+ ITypeInfo2 * iface,
+ UINT index,
+ REFGUID guid,
+ VARIANT *pVarVal)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData=NULL;
+ TLBFuncDesc * pFDesc;
+ int i;
+ for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
+ pFDesc=pFDesc->next);
+
+ if(pFDesc)
+ for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
+ if( IsEqualIID(guid, &pCData->guid)) break;
+
+ TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
+
+ if(pCData){
+ VariantInit( pVarVal);
+ VariantCopy( pVarVal, &pCData->data);
+ return S_OK;
+ }
+ return E_INVALIDARG; /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetParamCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
+ ITypeInfo2 * iface,
+ UINT indexFunc,
+ UINT indexParam,
+ REFGUID guid,
+ VARIANT *pVarVal)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData=NULL;
+ TLBFuncDesc * pFDesc;
+ int i;
+
+ for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
+
+ if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
+ for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
+ pCData = pCData->next)
+ if( IsEqualIID(guid, &pCData->guid)) break;
+
+ TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
+
+ if(pCData)
+ {
+ VariantInit( pVarVal);
+ VariantCopy( pVarVal, &pCData->data);
+ return S_OK;
+ }
+ return E_INVALIDARG; /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetVarCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
+ ITypeInfo2 * iface,
+ UINT index,
+ REFGUID guid,
+ VARIANT *pVarVal)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData=NULL;
+ TLBVarDesc * pVDesc;
+ int i;
+
+ for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
+
+ if(pVDesc)
+ {
+ for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
+ {
+ if( IsEqualIID(guid, &pCData->guid)) break;
+ }
+ }
+
+ TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
+
+ if(pCData)
+ {
+ VariantInit( pVarVal);
+ VariantCopy( pVarVal, &pCData->data);
+ return S_OK;
+ }
+ return E_INVALIDARG; /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetImplCustData
+ *
+ * Gets the custom data
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
+ ITypeInfo2 * iface,
+ UINT index,
+ REFGUID guid,
+ VARIANT *pVarVal)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData=NULL;
+ TLBImplType * pRDesc;
+ int i;
+
+ for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
+
+ if(pRDesc)
+ {
+ for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
+ {
+ if( IsEqualIID(guid, &pCData->guid)) break;
+ }
+ }
+
+ TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
+
+ if(pCData)
+ {
+ VariantInit( pVarVal);
+ VariantCopy( pVarVal, &pCData->data);
+ return S_OK;
+ }
+ return E_INVALIDARG; /* FIXME: correct? */
+}
+
+/* ITypeInfo2::GetDocumentation2
+ *
+ * Retrieves the documentation string, the complete Help file name and path,
+ * the localization context to use, and the context ID for the library Help
+ * topic in the Help file.
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
+ ITypeInfo2 * iface,
+ MEMBERID memid,
+ LCID lcid,
+ BSTR *pbstrHelpString,
+ DWORD *pdwHelpStringContext,
+ BSTR *pbstrHelpStringDll)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBFuncDesc * pFDesc;
+ TLBVarDesc * pVDesc;
+ TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
+ "HelpStringContext(%p) HelpStringDll(%p)\n",
+ This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
+ pbstrHelpStringDll );
+ /* the help string should be obtained from the helpstringdll,
+ * using the _DLLGetDocumentation function, based on the supplied
+ * lcid. Nice to do sometime...
+ */
+ if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
+ if(pbstrHelpString)
+ *pbstrHelpString=SysAllocString(This->Name);
+ if(pdwHelpStringContext)
+ *pdwHelpStringContext=This->dwHelpStringContext;
+ if(pbstrHelpStringDll)
+ *pbstrHelpStringDll=
+ SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
+ return S_OK;
+ }else {/* for a member */
+ for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
+ if(pFDesc->funcdesc.memid==memid){
+ if(pbstrHelpString)
+ *pbstrHelpString=SysAllocString(pFDesc->HelpString);
+ if(pdwHelpStringContext)
+ *pdwHelpStringContext=pFDesc->HelpStringContext;
+ if(pbstrHelpStringDll)
+ *pbstrHelpStringDll=
+ SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
+ return S_OK;
+ }
+ for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
+ if(pVDesc->vardesc.memid==memid){
+ if(pbstrHelpString)
+ *pbstrHelpString=SysAllocString(pVDesc->HelpString);
+ if(pdwHelpStringContext)
+ *pdwHelpStringContext=pVDesc->HelpStringContext;
+ if(pbstrHelpStringDll)
+ *pbstrHelpStringDll=
+ SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
+ return S_OK;
+ }
+ }
+ return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo2::GetAllCustData
+ *
+ * Gets all custom data items for the Type info.
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
+ ITypeInfo2 * iface,
+ CUSTDATA *pCustData)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData;
+ int i;
+
+ TRACE("(%p) returning %d items\n", This, This->ctCustData);
+
+ pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
+ if(pCustData->prgCustData ){
+ pCustData->cCustData=This->ctCustData;
+ for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
+ pCustData->prgCustData[i].guid=pCData->guid;
+ VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
+ }
+ }else{
+ ERR(" OUT OF MEMORY!\n");
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+}
+
+/* ITypeInfo2::GetAllFuncCustData
+ *
+ * Gets all custom data items for the specified Function
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
+ ITypeInfo2 * iface,
+ UINT index,
+ CUSTDATA *pCustData)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData;
+ TLBFuncDesc * pFDesc;
+ int i;
+ TRACE("(%p) index %d\n", This, index);
+ for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
+ pFDesc=pFDesc->next)
+ ;
+ if(pFDesc){
+ pCustData->prgCustData =
+ TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
+ if(pCustData->prgCustData ){
+ pCustData->cCustData=pFDesc->ctCustData;
+ for(i=0, pCData=pFDesc->pCustData; pCData; i++,
+ pCData = pCData->next){
+ pCustData->prgCustData[i].guid=pCData->guid;
+ VariantCopy(& pCustData->prgCustData[i].varValue,
+ & pCData->data);
+ }
+ }else{
+ ERR(" OUT OF MEMORY!\n");
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+ return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo2::GetAllParamCustData
+ *
+ * Gets all custom data items for the Functions
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
+ UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData=NULL;
+ TLBFuncDesc * pFDesc;
+ int i;
+ TRACE("(%p) index %d\n", This, indexFunc);
+ for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
+ pFDesc=pFDesc->next)
+ ;
+ if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
+ pCustData->prgCustData =
+ TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
+ sizeof(CUSTDATAITEM));
+ if(pCustData->prgCustData ){
+ pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
+ for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
+ pCData; i++, pCData = pCData->next){
+ pCustData->prgCustData[i].guid=pCData->guid;
+ VariantCopy(& pCustData->prgCustData[i].varValue,
+ & pCData->data);
+ }
+ }else{
+ ERR(" OUT OF MEMORY!\n");
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+ return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo2::GetAllVarCustData
+ *
+ * Gets all custom data items for the specified Variable
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
+ UINT index, CUSTDATA *pCustData)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData;
+ TLBVarDesc * pVDesc;
+ int i;
+ TRACE("(%p) index %d\n", This, index);
+ for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
+ pVDesc=pVDesc->next)
+ ;
+ if(pVDesc){
+ pCustData->prgCustData =
+ TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
+ if(pCustData->prgCustData ){
+ pCustData->cCustData=pVDesc->ctCustData;
+ for(i=0, pCData=pVDesc->pCustData; pCData; i++,
+ pCData = pCData->next){
+ pCustData->prgCustData[i].guid=pCData->guid;
+ VariantCopy(& pCustData->prgCustData[i].varValue,
+ & pCData->data);
+ }
+ }else{
+ ERR(" OUT OF MEMORY!\n");
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+ return TYPE_E_ELEMENTNOTFOUND;
+}
+
+/* ITypeInfo2::GetAllImplCustData
+ *
+ * Gets all custom data items for the specified implementation type
+ *
+ */
+static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
+ ITypeInfo2 * iface,
+ UINT index,
+ CUSTDATA *pCustData)
+{
+ ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
+ TLBCustData *pCData;
+ TLBImplType * pRDesc;
+ int i;
+ TRACE("(%p) index %d\n", This, index);
+ for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
+ pRDesc=pRDesc->next)
+ ;
+ if(pRDesc){
+ pCustData->prgCustData =
+ TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
+ if(pCustData->prgCustData ){
+ pCustData->cCustData=pRDesc->ctCustData;
+ for(i=0, pCData=pRDesc->pCustData; pCData; i++,
+ pCData = pCData->next){
+ pCustData->prgCustData[i].guid=pCData->guid;
+ VariantCopy(& pCustData->prgCustData[i].varValue,
+ & pCData->data);
+ }
+ }else{
+ ERR(" OUT OF MEMORY!\n");
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+ }
+ return TYPE_E_ELEMENTNOTFOUND;
+}
+
+static const ITypeInfo2Vtbl tinfvt =
+{
+
+ ITypeInfo_fnQueryInterface,
+ ITypeInfo_fnAddRef,
+ ITypeInfo_fnRelease,
+
+ ITypeInfo_fnGetTypeAttr,
+ ITypeInfo_fnGetTypeComp,
+ ITypeInfo_fnGetFuncDesc,
+ ITypeInfo_fnGetVarDesc,
+ ITypeInfo_fnGetNames,
+ ITypeInfo_fnGetRefTypeOfImplType,
+ ITypeInfo_fnGetImplTypeFlags,
+ ITypeInfo_fnGetIDsOfNames,
+ ITypeInfo_fnInvoke,
+ ITypeInfo_fnGetDocumentation,
+ ITypeInfo_fnGetDllEntry,
+ ITypeInfo_fnGetRefTypeInfo,
+ ITypeInfo_fnAddressOfMember,
+ ITypeInfo_fnCreateInstance,
+ ITypeInfo_fnGetMops,
+ ITypeInfo_fnGetContainingTypeLib,
+ ITypeInfo_fnReleaseTypeAttr,
+ ITypeInfo_fnReleaseFuncDesc,
+ ITypeInfo_fnReleaseVarDesc,
+
+ ITypeInfo2_fnGetTypeKind,
+ ITypeInfo2_fnGetTypeFlags,
+ ITypeInfo2_fnGetFuncIndexOfMemId,
+ ITypeInfo2_fnGetVarIndexOfMemId,
+ ITypeInfo2_fnGetCustData,
+ ITypeInfo2_fnGetFuncCustData,
+ ITypeInfo2_fnGetParamCustData,
+ ITypeInfo2_fnGetVarCustData,
+ ITypeInfo2_fnGetImplTypeCustData,
+ ITypeInfo2_fnGetDocumentation2,
+ ITypeInfo2_fnGetAllCustData,
+ ITypeInfo2_fnGetAllFuncCustData,
+ ITypeInfo2_fnGetAllParamCustData,
+ ITypeInfo2_fnGetAllVarCustData,
+ ITypeInfo2_fnGetAllImplTypeCustData,
+};
+
+/******************************************************************************
+ * CreateDispTypeInfo [OLEAUT32.31]
+ *
+ * Build type information for an object so it can be called through an
+ * IDispatch interface.
+ *
+ * RETURNS
+ * Success: S_OK. pptinfo contains the created ITypeInfo object.
+ * Failure: E_INVALIDARG, if one or more arguments is invalid.
+ *
+ * NOTES
+ * This call allows an objects methods to be accessed through IDispatch, by
+ * building an ITypeInfo object that IDispatch can use to call through.
+ */
+HRESULT WINAPI CreateDispTypeInfo(
+ INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
+ LCID lcid, /* [I] Locale Id */
+ ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
+{
+ ITypeInfoImpl *pTIImpl;
+ int param, func;
+ TLBFuncDesc **ppFuncDesc;
+
+ pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
+ pTIImpl->pTypeLib = NULL;
+ pTIImpl->index = 0;
+ pTIImpl->Name = NULL;
+ pTIImpl->dwHelpContext = -1;
+ memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
+ pTIImpl->TypeAttr.lcid = lcid;
+ pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
+ pTIImpl->TypeAttr.wMajorVerNum = 0;
+ pTIImpl->TypeAttr.wMinorVerNum = 0;
+ pTIImpl->TypeAttr.cbAlignment = 2;
+ pTIImpl->TypeAttr.cbSizeInstance = -1;
+ pTIImpl->TypeAttr.cbSizeVft = -1;
+ pTIImpl->TypeAttr.cFuncs = 0;
+ pTIImpl->TypeAttr.cImplTypes = 1;
+ pTIImpl->TypeAttr.cVars = 0;
+ pTIImpl->TypeAttr.wTypeFlags = 0;
+
+ ppFuncDesc = &pTIImpl->funclist;
+ for(func = 0; func < pidata->cMembers; func++) {
+ METHODDATA *md = pidata->pmethdata + func;
+ *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
+ (*ppFuncDesc)->Name = SysAllocString(md->szName);
+ (*ppFuncDesc)->funcdesc.memid = md->dispid;
+ (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
+ (*ppFuncDesc)->funcdesc.callconv = md->cc;
+ (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
+ (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
+ (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
+ (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
+ (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
+ (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ md->cArgs * sizeof(ELEMDESC));
+ (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ md->cArgs * sizeof(TLBParDesc));
+ for(param = 0; param < md->cArgs; param++) {
+ (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
+ (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
+ }
+ ppFuncDesc = &(*ppFuncDesc)->next;
+ }
+ *pptinfo = (ITypeInfo*)pTIImpl;
+ return S_OK;
+
+}
+
+static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
+{
+ ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
+
+ return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
+}
+
+static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
+{
+ ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
+
+ return ITypeInfo_AddRef((ITypeInfo *)This);
+}
+
+static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
+{
+ ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
+
+ return ITypeInfo_Release((ITypeInfo *)This);
+}
+
+static HRESULT WINAPI ITypeComp_fnBind(
+ ITypeComp * iface,
+ OLECHAR * szName,
+ ULONG lHash,
+ WORD wFlags,
+ ITypeInfo ** ppTInfo,
+ DESCKIND * pDescKind,
+ BINDPTR * pBindPtr)
+{
+ ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
+ TLBFuncDesc * pFDesc;
+ TLBVarDesc * pVDesc;
+
+ TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
+
+ *pDescKind = DESCKIND_NONE;
+ pBindPtr->lpfuncdesc = NULL;
+ *ppTInfo = NULL;
+
+ for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
+ if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
+ if (!strcmpW(pFDesc->Name, szName)) {
+ break;
+ }
+
+ if (pFDesc)
+ {
+ HRESULT hr = TLB_AllocAndInitFuncDesc(
+ &pFDesc->funcdesc,
+ &pBindPtr->lpfuncdesc,
+ This->TypeAttr.typekind == TKIND_DISPATCH);
+ if (FAILED(hr))
+ return hr;
+ *pDescKind = DESCKIND_FUNCDESC;
+ *ppTInfo = (ITypeInfo *)&This->lpVtbl;
+ ITypeInfo_AddRef(*ppTInfo);
+ return S_OK;
+ } else {
+ for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
+ if (!strcmpW(pVDesc->Name, szName)) {
+ HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
+ if (FAILED(hr))
+ return hr;
+ *pDescKind = DESCKIND_VARDESC;
+ *ppTInfo = (ITypeInfo *)&This->lpVtbl;
+ ITypeInfo_AddRef(*ppTInfo);
+ return S_OK;
+ }
+ }
+ }
+ /* FIXME: search each inherited interface, not just the first */
+ if (This->TypeAttr.cImplTypes) {
+ /* recursive search */
+ ITypeInfo *pTInfo;
+ ITypeComp *pTComp;
+ HRESULT hr;
+ hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
+ if (SUCCEEDED(hr))
+ {
+ hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
+ ITypeInfo_Release(pTInfo);
+ }
+ if (SUCCEEDED(hr))
+ {
+ hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
+ ITypeComp_Release(pTComp);
+ return hr;
+ }
+ WARN("Could not search inherited interface!\n");
+ }
+ WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+static HRESULT WINAPI ITypeComp_fnBindType(
+ ITypeComp * iface,
+ OLECHAR * szName,
+ ULONG lHash,
+ ITypeInfo ** ppTInfo,
+ ITypeComp ** ppTComp)
+{
+ TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
+
+ /* strange behaviour (does nothing) but like the
+ * original */
+
+ if (!ppTInfo || !ppTComp)
+ return E_POINTER;
+
+ *ppTInfo = NULL;
+ *ppTComp = NULL;
+
+ return S_OK;
+}
+
+static const ITypeCompVtbl tcompvt =
+{
+
+ ITypeComp_fnQueryInterface,
+ ITypeComp_fnAddRef,
+ ITypeComp_fnRelease,
+
+ ITypeComp_fnBind,
+ ITypeComp_fnBindType
+};