user32: Don't do the painting if combobox is not visible in CBPaintText.
[wine.git] / dlls / oleaut32 / typelib.c
blobebf6d8526bef69ade365a0981ce5fe30df5f6b53
1 /*
2 * TYPELIB
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
45 * behaviour.
46 * -. lousy fatal error handling
50 #include "config.h"
51 #include "wine/port.h"
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <ctype.h>
59 #define COBJMACROS
60 #define NONAMELESSUNION
62 #include "winerror.h"
63 #include "windef.h"
64 #include "winbase.h"
65 #include "winnls.h"
66 #include "winreg.h"
67 #include "winuser.h"
68 #include "winternl.h"
69 #include "lzexpand.h"
71 #include "wine/unicode.h"
72 #include "objbase.h"
73 #include "typelib.h"
74 #include "wine/debug.h"
75 #include "variant.h"
76 #include "wine/list.h"
78 WINE_DEFAULT_DEBUG_CHANNEL(ole);
79 WINE_DECLARE_DEBUG_CHANNEL(typelib);
81 typedef struct
83 WORD offset;
84 WORD length;
85 WORD flags;
86 WORD id;
87 WORD handle;
88 WORD usage;
89 } NE_NAMEINFO;
91 typedef struct
93 WORD type_id; /* Type identifier */
94 WORD count; /* Number of resources of this type */
95 DWORD resloader; /* SetResourceHandler() */
97 * Name info array.
99 } NE_TYPEINFO;
101 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
102 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
103 static void TLB_FreeVarDesc(VARDESC*);
105 /****************************************************************************
106 * FromLExxx
108 * Takes p_iVal (which is in little endian) and returns it
109 * in the host machine's byte order.
111 #ifdef WORDS_BIGENDIAN
112 static WORD FromLEWord(WORD p_iVal)
114 return (((p_iVal & 0x00FF) << 8) |
115 ((p_iVal & 0xFF00) >> 8));
119 static DWORD FromLEDWord(DWORD p_iVal)
121 return (((p_iVal & 0x000000FF) << 24) |
122 ((p_iVal & 0x0000FF00) << 8) |
123 ((p_iVal & 0x00FF0000) >> 8) |
124 ((p_iVal & 0xFF000000) >> 24));
126 #else
127 #define FromLEWord(X) (X)
128 #define FromLEDWord(X) (X)
129 #endif
131 #define DISPATCH_HREF_OFFSET 0x01000000
132 #define DISPATCH_HREF_MASK 0xff000000
134 /****************************************************************************
135 * FromLExxx
137 * Fix byte order in any structure if necessary
139 #ifdef WORDS_BIGENDIAN
140 static void FromLEWords(void *p_Val, int p_iSize)
142 WORD *Val = p_Val;
144 p_iSize /= sizeof(WORD);
146 while (p_iSize) {
147 *Val = FromLEWord(*Val);
148 Val++;
149 p_iSize--;
154 static void FromLEDWords(void *p_Val, int p_iSize)
156 DWORD *Val = p_Val;
158 p_iSize /= sizeof(DWORD);
160 while (p_iSize) {
161 *Val = FromLEDWord(*Val);
162 Val++;
163 p_iSize--;
166 #else
167 #define FromLEWords(X,Y) /*nothing*/
168 #define FromLEDWords(X,Y) /*nothing*/
169 #endif
172 * Find a typelib key which matches a requested maj.min version.
174 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
176 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
177 WCHAR buffer[60];
178 char key_name[16];
179 DWORD len, i;
180 INT best_maj = -1, best_min = -1;
181 HKEY hkey;
183 memcpy( buffer, typelibW, sizeof(typelibW) );
184 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
186 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
187 return FALSE;
189 len = sizeof(key_name);
190 i = 0;
191 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
193 INT v_maj, v_min;
195 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
197 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
199 if (*wMaj == 0xffff && *wMin == 0xffff)
201 if (v_maj > best_maj) best_maj = v_maj;
202 if (v_min > best_min) best_min = v_min;
204 else if (*wMaj == v_maj)
206 best_maj = v_maj;
208 if (*wMin == v_min)
210 best_min = v_min;
211 break; /* exact match */
213 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
216 len = sizeof(key_name);
218 RegCloseKey( hkey );
220 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
222 if (*wMaj == 0xffff && *wMin == 0xffff)
224 if (best_maj >= 0 && best_min >= 0)
226 *wMaj = best_maj;
227 *wMin = best_min;
228 return TRUE;
232 if (*wMaj == best_maj && best_min >= 0)
234 *wMin = best_min;
235 return TRUE;
237 return FALSE;
240 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
241 /* buffer must be at least 60 characters long */
242 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
244 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
245 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
247 memcpy( buffer, TypelibW, sizeof(TypelibW) );
248 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
249 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
250 return buffer;
253 /* get the path of an interface key, in the form "Interface\\<guid>" */
254 /* buffer must be at least 50 characters long */
255 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
257 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
259 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
260 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
261 return buffer;
264 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
265 /* buffer must be at least 16 characters long */
266 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
268 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
269 static const WCHAR win16W[] = {'w','i','n','1','6',0};
270 static const WCHAR win32W[] = {'w','i','n','3','2',0};
271 static const WCHAR win64W[] = {'w','i','n','6','4',0};
273 sprintfW( buffer, LcidFormatW, lcid );
274 switch(syskind)
276 case SYS_WIN16: strcatW( buffer, win16W ); break;
277 case SYS_WIN32: strcatW( buffer, win32W ); break;
278 case SYS_WIN64: strcatW( buffer, win64W ); break;
279 default:
280 TRACE("Typelib is for unsupported syskind %i\n", syskind);
281 return NULL;
283 return buffer;
286 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
288 struct tlibredirect_data
290 ULONG size;
291 DWORD res;
292 ULONG name_len;
293 ULONG name_offset;
294 LANGID langid;
295 WORD flags;
296 ULONG help_len;
297 ULONG help_offset;
298 WORD major_version;
299 WORD minor_version;
302 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
303 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
304 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
306 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
307 LCID myLCID = lcid;
308 HKEY hkey;
309 WCHAR buffer[60];
310 WCHAR Path[MAX_PATH];
311 LONG res;
313 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
315 if (redir)
317 ACTCTX_SECTION_KEYED_DATA data;
319 data.cbSize = sizeof(data);
320 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
322 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
323 WCHAR *nameW;
324 DWORD len;
326 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
327 return TYPE_E_LIBNOTREGISTERED;
329 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
330 len = SearchPathW( NULL, nameW, NULL, sizeof(Path)/sizeof(WCHAR), Path, NULL );
331 if (!len) return TYPE_E_LIBNOTREGISTERED;
333 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
334 *path = SysAllocString( Path );
335 return S_OK;
339 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
340 get_typelib_key( guid, wMaj, wMin, buffer );
342 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
343 if (res == ERROR_FILE_NOT_FOUND)
345 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
346 return TYPE_E_LIBNOTREGISTERED;
348 else if (res != ERROR_SUCCESS)
350 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
351 return TYPE_E_REGISTRYACCESS;
354 while (hr != S_OK)
356 LONG dwPathLen = sizeof(Path);
358 get_lcid_subkey( myLCID, syskind, buffer );
360 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
362 if (!lcid)
363 break;
364 else if (myLCID == lcid)
366 /* try with sub-langid */
367 myLCID = SUBLANGID(lcid);
369 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
371 /* try with system langid */
372 myLCID = 0;
374 else
376 break;
379 else
381 *path = SysAllocString( Path );
382 hr = S_OK;
385 RegCloseKey( hkey );
386 TRACE_(typelib)("-- 0x%08x\n", hr);
387 return hr;
390 /****************************************************************************
391 * QueryPathOfRegTypeLib [OLEAUT32.164]
393 * Gets the path to a registered type library.
395 * PARAMS
396 * guid [I] referenced guid
397 * wMaj [I] major version
398 * wMin [I] minor version
399 * lcid [I] locale id
400 * path [O] path of typelib
402 * RETURNS
403 * Success: S_OK.
404 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
405 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
406 * opened.
408 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
410 BOOL redir = TRUE;
411 #ifdef _WIN64
412 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
413 if(SUCCEEDED(hres))
414 return hres;
415 redir = FALSE;
416 #endif
417 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
420 /******************************************************************************
421 * CreateTypeLib [OLEAUT32.160] creates a typelib
423 * RETURNS
424 * Success: S_OK
425 * Failure: Status
427 HRESULT WINAPI CreateTypeLib(
428 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
430 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
431 return E_FAIL;
434 /******************************************************************************
435 * LoadTypeLib [OLEAUT32.161]
437 * Loads a type library
439 * PARAMS
440 * szFile [I] Name of file to load from.
441 * pptLib [O] Pointer that receives ITypeLib object on success.
443 * RETURNS
444 * Success: S_OK
445 * Failure: Status
447 * SEE
448 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
450 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
452 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
453 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
456 /******************************************************************************
457 * LoadTypeLibEx [OLEAUT32.183]
459 * Loads and optionally registers a type library
461 * RETURNS
462 * Success: S_OK
463 * Failure: Status
465 HRESULT WINAPI LoadTypeLibEx(
466 LPCOLESTR szFile, /* [in] Name of file to load from */
467 REGKIND regkind, /* [in] Specify kind of registration */
468 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
470 WCHAR szPath[MAX_PATH+1];
471 HRESULT res;
473 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
475 if (!szFile || !pptLib)
476 return E_INVALIDARG;
478 *pptLib = NULL;
480 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
482 if (SUCCEEDED(res))
483 switch(regkind)
485 case REGKIND_DEFAULT:
486 /* don't register typelibs supplied with full path. Experimentation confirms the following */
487 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
488 (szFile[0] && (szFile[1] == ':'))) break;
489 /* else fall-through */
491 case REGKIND_REGISTER:
492 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
494 ITypeLib_Release(*pptLib);
495 *pptLib = 0;
497 break;
498 case REGKIND_NONE:
499 break;
502 TRACE(" returns %08x\n",res);
503 return res;
506 /******************************************************************************
507 * LoadRegTypeLib [OLEAUT32.162]
509 * Loads a registered type library.
511 * PARAMS
512 * rguid [I] GUID of the registered type library.
513 * wVerMajor [I] major version.
514 * wVerMinor [I] minor version.
515 * lcid [I] locale ID.
516 * ppTLib [O] pointer that receives an ITypeLib object on success.
518 * RETURNS
519 * Success: S_OK.
520 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
521 * LoadTypeLib.
523 HRESULT WINAPI LoadRegTypeLib(
524 REFGUID rguid,
525 WORD wVerMajor,
526 WORD wVerMinor,
527 LCID lcid,
528 ITypeLib **ppTLib)
530 BSTR bstr=NULL;
531 HRESULT res;
533 *ppTLib = NULL;
535 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
537 if(SUCCEEDED(res))
539 res= LoadTypeLib(bstr, ppTLib);
540 SysFreeString(bstr);
542 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
544 TLIBATTR *attr;
546 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
547 if (res == S_OK)
549 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
550 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
552 if (mismatch)
554 ITypeLib_Release(*ppTLib);
555 *ppTLib = NULL;
556 res = TYPE_E_LIBNOTREGISTERED;
562 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
564 return res;
568 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
569 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
570 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
571 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
572 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
573 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
575 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
577 WCHAR keyName[60];
578 HKEY key, subKey;
580 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
581 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
582 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
584 get_interface_key( &tattr->guid, keyName );
585 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
586 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
588 if (name)
589 RegSetValueExW(key, NULL, 0, REG_SZ,
590 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
592 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
593 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
594 RegSetValueExW(subKey, NULL, 0, REG_SZ,
595 (const BYTE *)PSOA, sizeof PSOA);
596 RegCloseKey(subKey);
599 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
600 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
601 RegSetValueExW(subKey, NULL, 0, REG_SZ,
602 (const BYTE *)PSOA, sizeof PSOA);
603 RegCloseKey(subKey);
606 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
607 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
609 WCHAR buffer[40];
610 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
611 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
613 StringFromGUID2(&libattr->guid, buffer, 40);
614 RegSetValueExW(subKey, NULL, 0, REG_SZ,
615 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
616 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
617 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
618 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
619 RegCloseKey(subKey);
622 RegCloseKey(key);
626 /******************************************************************************
627 * RegisterTypeLib [OLEAUT32.163]
628 * Adds information about a type library to the System Registry
629 * NOTES
630 * Docs: ITypeLib FAR * ptlib
631 * Docs: OLECHAR FAR* szFullPath
632 * Docs: OLECHAR FAR* szHelpDir
634 * RETURNS
635 * Success: S_OK
636 * Failure: Status
638 HRESULT WINAPI RegisterTypeLib(
639 ITypeLib * ptlib, /* [in] Pointer to the library*/
640 OLECHAR * szFullPath, /* [in] full Path of the library*/
641 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
642 may be NULL*/
644 HRESULT res;
645 TLIBATTR *attr;
646 WCHAR keyName[60];
647 WCHAR tmp[16];
648 HKEY key, subKey;
649 UINT types, tidx;
650 TYPEKIND kind;
651 DWORD disposition;
653 if (ptlib == NULL || szFullPath == NULL)
654 return E_INVALIDARG;
656 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
657 return E_FAIL;
659 #ifndef _WIN64
660 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
661 #endif
663 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
665 res = S_OK;
666 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
667 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
669 LPOLESTR doc;
671 /* Set the human-readable name of the typelib */
672 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
673 res = E_FAIL;
674 else if (doc)
676 if (RegSetValueExW(key, NULL, 0, REG_SZ,
677 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
678 res = E_FAIL;
680 SysFreeString(doc);
683 /* Make up the name of the typelib path subkey */
684 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
686 /* Create the typelib path subkey */
687 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
688 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
690 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
691 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
692 res = E_FAIL;
694 RegCloseKey(subKey);
696 else
697 res = E_FAIL;
699 /* Create the flags subkey */
700 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
701 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
703 /* FIXME: is %u correct? */
704 static const WCHAR formatW[] = {'%','u',0};
705 WCHAR buf[20];
706 sprintfW(buf, formatW, attr->wLibFlags);
707 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
709 res = E_FAIL;
711 RegCloseKey(subKey);
713 else
714 res = E_FAIL;
716 /* create the helpdir subkey */
717 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
720 BOOL freeHelpDir = FALSE;
721 OLECHAR* pIndexStr;
723 /* if we created a new key, and helpDir was null, set the helpdir
724 to the directory which contains the typelib. However,
725 if we just opened an existing key, we leave the helpdir alone */
726 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
727 szHelpDir = SysAllocString(szFullPath);
728 pIndexStr = strrchrW(szHelpDir, '\\');
729 if (pIndexStr) {
730 *pIndexStr = 0;
732 freeHelpDir = TRUE;
735 /* if we have an szHelpDir, set it! */
736 if (szHelpDir != NULL) {
737 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
738 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
739 res = E_FAIL;
743 /* tidy up */
744 if (freeHelpDir) SysFreeString(szHelpDir);
745 RegCloseKey(subKey);
747 } else {
748 res = E_FAIL;
751 RegCloseKey(key);
753 else
754 res = E_FAIL;
756 /* register OLE Automation-compatible interfaces for this typelib */
757 types = ITypeLib_GetTypeInfoCount(ptlib);
758 for (tidx=0; tidx<types; tidx++) {
759 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
760 LPOLESTR name = NULL;
761 ITypeInfo *tinfo = NULL;
763 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
765 switch (kind) {
766 case TKIND_INTERFACE:
767 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
768 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
769 break;
771 case TKIND_DISPATCH:
772 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
773 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
774 break;
776 default:
777 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
778 break;
781 if (tinfo) {
782 TYPEATTR *tattr = NULL;
783 ITypeInfo_GetTypeAttr(tinfo, &tattr);
785 if (tattr) {
786 TRACE_(typelib)("guid=%s, flags=%04x (",
787 debugstr_guid(&tattr->guid),
788 tattr->wTypeFlags);
790 if (TRACE_ON(typelib)) {
791 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
792 XX(FAPPOBJECT);
793 XX(FCANCREATE);
794 XX(FLICENSED);
795 XX(FPREDECLID);
796 XX(FHIDDEN);
797 XX(FCONTROL);
798 XX(FDUAL);
799 XX(FNONEXTENSIBLE);
800 XX(FOLEAUTOMATION);
801 XX(FRESTRICTED);
802 XX(FAGGREGATABLE);
803 XX(FREPLACEABLE);
804 XX(FDISPATCHABLE);
805 XX(FREVERSEBIND);
806 XX(FPROXY);
807 #undef XX
808 MESSAGE("\n");
811 /* Register all dispinterfaces (which includes dual interfaces) and
812 oleautomation interfaces */
813 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
814 kind == TKIND_DISPATCH)
816 BOOL is_wow64;
817 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
819 /* register interface<->typelib coupling */
820 TLB_register_interface(attr, name, tattr, 0);
822 /* register TLBs into the opposite registry view, too */
823 if(opposite == KEY_WOW64_32KEY ||
824 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
825 TLB_register_interface(attr, name, tattr, opposite);
828 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
831 ITypeInfo_Release(tinfo);
834 SysFreeString(name);
838 ITypeLib_ReleaseTLibAttr(ptlib, attr);
840 return res;
843 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
845 WCHAR subKeyName[50];
846 HKEY subKey;
848 /* the path to the type */
849 get_interface_key( guid, subKeyName );
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
853 return;
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
858 RegCloseKey(subKey);
859 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
862 /******************************************************************************
863 * UnRegisterTypeLib [OLEAUT32.186]
864 * Removes information about a type library from the System Registry
865 * NOTES
867 * RETURNS
868 * Success: S_OK
869 * Failure: Status
871 HRESULT WINAPI UnRegisterTypeLib(
872 REFGUID libid, /* [in] Guid of the library */
873 WORD wVerMajor, /* [in] major version */
874 WORD wVerMinor, /* [in] minor version */
875 LCID lcid, /* [in] locale id */
876 SYSKIND syskind)
878 BSTR tlibPath = NULL;
879 DWORD tmpLength;
880 WCHAR keyName[60];
881 WCHAR subKeyName[50];
882 int result = S_OK;
883 DWORD i = 0;
884 BOOL deleteOtherStuff;
885 HKEY key = NULL;
886 TYPEATTR* typeAttr = NULL;
887 TYPEKIND kind;
888 ITypeInfo* typeInfo = NULL;
889 ITypeLib* typeLib = NULL;
890 int numTypes;
892 TRACE("(IID: %s)\n",debugstr_guid(libid));
894 /* Create the path to the key */
895 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
897 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
899 TRACE("Unsupported syskind %i\n", syskind);
900 result = E_INVALIDARG;
901 goto end;
904 /* get the path to the typelib on disk */
905 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
906 result = E_INVALIDARG;
907 goto end;
910 /* Try and open the key to the type library. */
911 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
912 result = E_INVALIDARG;
913 goto end;
916 /* Try and load the type library */
917 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
918 result = TYPE_E_INVALIDSTATE;
919 goto end;
922 /* remove any types registered with this typelib */
923 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
924 for (i=0; i<numTypes; i++) {
925 /* get the kind of type */
926 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
927 goto enddeleteloop;
930 /* skip non-interfaces, and get type info for the type */
931 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
932 goto enddeleteloop;
934 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
935 goto enddeleteloop;
937 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
938 goto enddeleteloop;
941 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
942 kind == TKIND_DISPATCH)
944 BOOL is_wow64;
945 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
947 TLB_unregister_interface(&typeAttr->guid, 0);
949 /* unregister TLBs into the opposite registry view, too */
950 if(opposite == KEY_WOW64_32KEY ||
951 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
952 TLB_unregister_interface(&typeAttr->guid, opposite);
956 enddeleteloop:
957 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
958 typeAttr = NULL;
959 if (typeInfo) ITypeInfo_Release(typeInfo);
960 typeInfo = NULL;
963 /* Now, delete the type library path subkey */
964 get_lcid_subkey( lcid, syskind, subKeyName );
965 RegDeleteKeyW(key, subKeyName);
966 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
967 RegDeleteKeyW(key, subKeyName);
969 /* check if there is anything besides the FLAGS/HELPDIR keys.
970 If there is, we don't delete them */
971 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
972 deleteOtherStuff = TRUE;
973 i = 0;
974 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
975 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
977 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
978 if (!strcmpW(subKeyName, FLAGSW)) continue;
979 if (!strcmpW(subKeyName, HELPDIRW)) continue;
980 deleteOtherStuff = FALSE;
981 break;
984 /* only delete the other parts of the key if we're absolutely sure */
985 if (deleteOtherStuff) {
986 RegDeleteKeyW(key, FLAGSW);
987 RegDeleteKeyW(key, HELPDIRW);
988 RegCloseKey(key);
989 key = NULL;
991 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
992 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
993 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
996 end:
997 SysFreeString(tlibPath);
998 if (typeLib) ITypeLib_Release(typeLib);
999 if (key) RegCloseKey(key);
1000 return result;
1003 /******************************************************************************
1004 * RegisterTypeLibForUser [OLEAUT32.442]
1005 * Adds information about a type library to the user registry
1006 * NOTES
1007 * Docs: ITypeLib FAR * ptlib
1008 * Docs: OLECHAR FAR* szFullPath
1009 * Docs: OLECHAR FAR* szHelpDir
1011 * RETURNS
1012 * Success: S_OK
1013 * Failure: Status
1015 HRESULT WINAPI RegisterTypeLibForUser(
1016 ITypeLib * ptlib, /* [in] Pointer to the library*/
1017 OLECHAR * szFullPath, /* [in] full Path of the library*/
1018 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1019 may be NULL*/
1021 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1022 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1023 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1026 /******************************************************************************
1027 * UnRegisterTypeLibForUser [OLEAUT32.443]
1028 * Removes information about a type library from the user registry
1030 * RETURNS
1031 * Success: S_OK
1032 * Failure: Status
1034 HRESULT WINAPI UnRegisterTypeLibForUser(
1035 REFGUID libid, /* [in] GUID of the library */
1036 WORD wVerMajor, /* [in] major version */
1037 WORD wVerMinor, /* [in] minor version */
1038 LCID lcid, /* [in] locale id */
1039 SYSKIND syskind)
1041 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1042 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1043 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1046 /*======================= ITypeLib implementation =======================*/
1048 typedef struct tagTLBGuid {
1049 GUID guid;
1050 INT hreftype;
1051 UINT offset;
1052 struct list entry;
1053 } TLBGuid;
1055 typedef struct tagTLBCustData
1057 TLBGuid *guid;
1058 VARIANT data;
1059 struct list entry;
1060 } TLBCustData;
1062 /* data structure for import typelibs */
1063 typedef struct tagTLBImpLib
1065 int offset; /* offset in the file (MSFT)
1066 offset in nametable (SLTG)
1067 just used to identify library while reading
1068 data from file */
1069 TLBGuid *guid; /* libid */
1070 BSTR name; /* name */
1072 LCID lcid; /* lcid of imported typelib */
1074 WORD wVersionMajor; /* major version number */
1075 WORD wVersionMinor; /* minor version number */
1077 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1078 NULL if not yet loaded */
1079 struct list entry;
1080 } TLBImpLib;
1082 typedef struct tagTLBString {
1083 BSTR str;
1084 UINT offset;
1085 struct list entry;
1086 } TLBString;
1088 /* internal ITypeLib data */
1089 typedef struct tagITypeLibImpl
1091 ITypeLib2 ITypeLib2_iface;
1092 ITypeComp ITypeComp_iface;
1093 ICreateTypeLib2 ICreateTypeLib2_iface;
1094 LONG ref;
1095 TLBGuid *guid;
1096 LCID lcid;
1097 SYSKIND syskind;
1098 int ptr_size;
1099 WORD ver_major;
1100 WORD ver_minor;
1101 WORD libflags;
1102 LCID set_lcid;
1104 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1105 * exported to the application as a UNICODE string.
1107 struct list string_list;
1108 struct list name_list;
1109 struct list guid_list;
1111 const TLBString *Name;
1112 const TLBString *DocString;
1113 const TLBString *HelpFile;
1114 const TLBString *HelpStringDll;
1115 DWORD dwHelpContext;
1116 int TypeInfoCount; /* nr of typeinfo's in librarry */
1117 struct tagITypeInfoImpl **typeinfos;
1118 struct list custdata_list;
1119 struct list implib_list;
1120 int ctTypeDesc; /* number of items in type desc array */
1121 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1122 library. Only used while reading MSFT
1123 typelibs */
1124 struct list ref_list; /* list of ref types in this typelib */
1125 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1128 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1129 struct list entry;
1130 WCHAR *path;
1131 INT index;
1132 } ITypeLibImpl;
1134 static const ITypeLib2Vtbl tlbvt;
1135 static const ITypeCompVtbl tlbtcvt;
1136 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1138 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1140 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1143 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1145 return impl_from_ITypeLib2((ITypeLib2*)iface);
1148 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1150 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1153 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1155 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1158 /* ITypeLib methods */
1159 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1160 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1162 /*======================= ITypeInfo implementation =======================*/
1164 /* data for referenced types */
1165 typedef struct tagTLBRefType
1167 INT index; /* Type index for internal ref or for external ref
1168 it the format is SLTG. -2 indicates to
1169 use guid */
1171 TYPEKIND tkind;
1172 TLBGuid *guid; /* guid of the referenced type */
1173 /* if index == TLB_REF_USE_GUID */
1175 HREFTYPE reference; /* The href of this ref */
1176 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1177 TLB_REF_INTERNAL for internal refs
1178 TLB_REF_NOT_FOUND for broken refs */
1180 struct list entry;
1181 } TLBRefType;
1183 #define TLB_REF_USE_GUID -2
1185 #define TLB_REF_INTERNAL (void*)-2
1186 #define TLB_REF_NOT_FOUND (void*)-1
1188 /* internal Parameter data */
1189 typedef struct tagTLBParDesc
1191 const TLBString *Name;
1192 struct list custdata_list;
1193 } TLBParDesc;
1195 /* internal Function data */
1196 typedef struct tagTLBFuncDesc
1198 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1199 const TLBString *Name; /* the name of this function */
1200 TLBParDesc *pParamDesc; /* array with param names and custom data */
1201 int helpcontext;
1202 int HelpStringContext;
1203 const TLBString *HelpString;
1204 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1205 struct list custdata_list;
1206 } TLBFuncDesc;
1208 /* internal Variable data */
1209 typedef struct tagTLBVarDesc
1211 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1212 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1213 const TLBString *Name; /* the name of this variable */
1214 int HelpContext;
1215 int HelpStringContext;
1216 const TLBString *HelpString;
1217 struct list custdata_list;
1218 } TLBVarDesc;
1220 /* internal implemented interface data */
1221 typedef struct tagTLBImplType
1223 HREFTYPE hRef; /* hRef of interface */
1224 int implflags; /* IMPLFLAG_*s */
1225 struct list custdata_list;
1226 } TLBImplType;
1228 /* internal TypeInfo data */
1229 typedef struct tagITypeInfoImpl
1231 ITypeInfo2 ITypeInfo2_iface;
1232 ITypeComp ITypeComp_iface;
1233 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1234 LONG ref;
1235 BOOL not_attached_to_typelib;
1236 BOOL needs_layout;
1238 TLBGuid *guid;
1239 TYPEATTR typeattr;
1240 TYPEDESC *tdescAlias;
1242 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1243 int index; /* index in this typelib; */
1244 HREFTYPE hreftype; /* hreftype for app object binding */
1245 /* type libs seem to store the doc strings in ascii
1246 * so why should we do it in unicode?
1248 const TLBString *Name;
1249 const TLBString *DocString;
1250 const TLBString *DllName;
1251 const TLBString *Schema;
1252 DWORD dwHelpContext;
1253 DWORD dwHelpStringContext;
1255 /* functions */
1256 TLBFuncDesc *funcdescs;
1258 /* variables */
1259 TLBVarDesc *vardescs;
1261 /* Implemented Interfaces */
1262 TLBImplType *impltypes;
1264 struct list *pcustdata_list;
1265 struct list custdata_list;
1266 } ITypeInfoImpl;
1268 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1270 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1273 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1275 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1278 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1280 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1283 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1285 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1288 static const ITypeInfo2Vtbl tinfvt;
1289 static const ITypeCompVtbl tcompvt;
1290 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1292 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1293 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1295 typedef struct tagTLBContext
1297 unsigned int oStart; /* start of TLB in file */
1298 unsigned int pos; /* current pos */
1299 unsigned int length; /* total length */
1300 void *mapping; /* memory mapping */
1301 MSFT_SegDir * pTblDir;
1302 ITypeLibImpl* pLibInfo;
1303 } TLBContext;
1306 static inline BSTR TLB_get_bstr(const TLBString *str)
1308 return str != NULL ? str->str : NULL;
1311 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1313 if(!str)
1314 return 1;
1315 return memcmp(left, str->str, len);
1318 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1320 return guid != NULL ? &guid->guid : NULL;
1323 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1325 return guid != NULL ? &guid->guid : &GUID_NULL;
1328 static int get_ptr_size(SYSKIND syskind)
1330 switch(syskind){
1331 case SYS_WIN64:
1332 return 8;
1333 case SYS_WIN32:
1334 case SYS_MAC:
1335 case SYS_WIN16:
1336 return 4;
1338 WARN("Unhandled syskind: 0x%x\n", syskind);
1339 return 4;
1343 debug
1345 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1346 if (pTD->vt & VT_RESERVED)
1347 szVarType += strlen(strcpy(szVarType, "reserved | "));
1348 if (pTD->vt & VT_BYREF)
1349 szVarType += strlen(strcpy(szVarType, "ref to "));
1350 if (pTD->vt & VT_ARRAY)
1351 szVarType += strlen(strcpy(szVarType, "array of "));
1352 if (pTD->vt & VT_VECTOR)
1353 szVarType += strlen(strcpy(szVarType, "vector of "));
1354 switch(pTD->vt & VT_TYPEMASK) {
1355 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1356 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1357 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1358 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1359 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1360 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1361 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1362 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1363 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1364 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1365 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1366 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1367 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1368 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1369 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1370 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1371 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1372 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1373 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1374 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1375 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1376 pTD->u.hreftype); break;
1377 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1378 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1379 case VT_PTR: sprintf(szVarType, "ptr to ");
1380 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1381 break;
1382 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1383 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1384 break;
1385 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1386 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1387 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1388 break;
1390 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1394 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1395 char buf[200];
1396 USHORT flags = edesc->u.paramdesc.wParamFlags;
1397 dump_TypeDesc(&edesc->tdesc,buf);
1398 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1399 MESSAGE("\t\tu.paramdesc.wParamFlags");
1400 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1401 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1402 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1403 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1404 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1405 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1406 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1407 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1408 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1410 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1411 int i;
1412 MESSAGE("memid is %08x\n",funcdesc->memid);
1413 for (i=0;i<funcdesc->cParams;i++) {
1414 MESSAGE("Param %d:\n",i);
1415 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1417 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1418 switch (funcdesc->funckind) {
1419 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1420 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1421 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1422 case FUNC_STATIC: MESSAGE("static");break;
1423 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1424 default: MESSAGE("unknown");break;
1426 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1427 switch (funcdesc->invkind) {
1428 case INVOKE_FUNC: MESSAGE("func");break;
1429 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1430 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1431 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1433 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1434 switch (funcdesc->callconv) {
1435 case CC_CDECL: MESSAGE("cdecl");break;
1436 case CC_PASCAL: MESSAGE("pascal");break;
1437 case CC_STDCALL: MESSAGE("stdcall");break;
1438 case CC_SYSCALL: MESSAGE("syscall");break;
1439 default:break;
1441 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1442 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1443 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1445 MESSAGE("\telemdescFunc (return value type):\n");
1446 dump_ELEMDESC(&funcdesc->elemdescFunc);
1449 static const char * const typekind_desc[] =
1451 "TKIND_ENUM",
1452 "TKIND_RECORD",
1453 "TKIND_MODULE",
1454 "TKIND_INTERFACE",
1455 "TKIND_DISPATCH",
1456 "TKIND_COCLASS",
1457 "TKIND_ALIAS",
1458 "TKIND_UNION",
1459 "TKIND_MAX"
1462 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1464 int i;
1465 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1466 for (i=0;i<pfd->funcdesc.cParams;i++)
1467 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1470 dump_FUNCDESC(&(pfd->funcdesc));
1472 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1473 if(pfd->Entry == NULL)
1474 MESSAGE("\tentry: (null)\n");
1475 else if(pfd->Entry == (void*)-1)
1476 MESSAGE("\tentry: invalid\n");
1477 else if(IS_INTRESOURCE(pfd->Entry))
1478 MESSAGE("\tentry: %p\n", pfd->Entry);
1479 else
1480 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1482 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1484 while (n)
1486 dump_TLBFuncDescOne(pfd);
1487 ++pfd;
1488 --n;
1491 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1493 while (n)
1495 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1496 ++pvd;
1497 --n;
1501 static void dump_TLBImpLib(const TLBImpLib *import)
1503 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1504 debugstr_w(import->name));
1505 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1506 import->wVersionMinor, import->lcid, import->offset);
1509 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1511 TLBRefType *ref;
1513 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1515 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1516 if(ref->index == -1)
1517 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1518 else
1519 TRACE_(typelib)("type no: %d\n", ref->index);
1521 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1523 TRACE_(typelib)("in lib\n");
1524 dump_TLBImpLib(ref->pImpTLInfo);
1529 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1531 if(!impl)
1532 return;
1533 while (n) {
1534 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1535 impl->hRef, impl->implflags);
1536 ++impl;
1537 --n;
1541 static void dump_DispParms(const DISPPARAMS * pdp)
1543 unsigned int index;
1545 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1547 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1549 TRACE("named args:\n");
1550 for (index = 0; index < pdp->cNamedArgs; index++)
1551 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1554 if (pdp->cArgs && pdp->rgvarg)
1556 TRACE("args:\n");
1557 for (index = 0; index < pdp->cArgs; index++)
1558 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1562 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1564 TRACE("%p ref=%u\n", pty, pty->ref);
1565 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1566 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1567 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1568 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1569 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1570 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1571 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1572 if (TRACE_ON(ole))
1573 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1574 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1575 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1578 static void dump_VARDESC(const VARDESC *v)
1580 MESSAGE("memid %d\n",v->memid);
1581 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1582 MESSAGE("oInst %d\n",v->u.oInst);
1583 dump_ELEMDESC(&(v->elemdescVar));
1584 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1585 MESSAGE("varkind %d\n",v->varkind);
1588 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1590 /* VT_LPWSTR is largest type that, may appear in type description */
1591 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1592 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1593 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1594 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1595 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1596 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1597 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1598 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1601 static void TLB_abort(void)
1603 DebugBreak();
1606 /* returns the size required for a deep copy of a typedesc into a
1607 * flat buffer */
1608 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1610 SIZE_T size = 0;
1612 if (alloc_initial_space)
1613 size += sizeof(TYPEDESC);
1615 switch (tdesc->vt)
1617 case VT_PTR:
1618 case VT_SAFEARRAY:
1619 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1620 break;
1621 case VT_CARRAY:
1622 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1623 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1624 break;
1626 return size;
1629 /* deep copy a typedesc into a flat buffer */
1630 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1632 if (!dest)
1634 dest = buffer;
1635 buffer = (char *)buffer + sizeof(TYPEDESC);
1638 *dest = *src;
1640 switch (src->vt)
1642 case VT_PTR:
1643 case VT_SAFEARRAY:
1644 dest->u.lptdesc = buffer;
1645 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1646 break;
1647 case VT_CARRAY:
1648 dest->u.lpadesc = buffer;
1649 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1650 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1651 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1652 break;
1654 return buffer;
1657 /* free custom data allocated by MSFT_CustData */
1658 static inline void TLB_FreeCustData(struct list *custdata_list)
1660 TLBCustData *cd, *cdn;
1661 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1663 list_remove(&cd->entry);
1664 VariantClear(&cd->data);
1665 heap_free(cd);
1669 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1671 DWORD len;
1672 BSTR ret;
1674 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1675 ret = SysAllocStringLen(NULL, len - 1);
1676 if (!ret) return ret;
1677 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1678 return ret;
1681 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1682 UINT n, MEMBERID memid)
1684 while(n){
1685 if(funcdescs->funcdesc.memid == memid)
1686 return funcdescs;
1687 ++funcdescs;
1688 --n;
1690 return NULL;
1693 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1694 UINT n, MEMBERID memid)
1696 while(n){
1697 if(vardescs->vardesc.memid == memid)
1698 return vardescs;
1699 ++vardescs;
1700 --n;
1702 return NULL;
1705 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1706 UINT n, const OLECHAR *name)
1708 while(n){
1709 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1710 return vardescs;
1711 ++vardescs;
1712 --n;
1714 return NULL;
1717 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1719 TLBCustData *cust_data;
1720 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1721 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1722 return cust_data;
1723 return NULL;
1726 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1727 UINT n, const OLECHAR *name)
1729 while(n){
1730 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1731 return *typeinfos;
1732 ++typeinfos;
1733 --n;
1735 return NULL;
1738 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1740 list_init(&var_desc->custdata_list);
1743 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1745 TLBVarDesc *ret;
1747 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1748 if(!ret)
1749 return NULL;
1751 while(n){
1752 TLBVarDesc_Constructor(&ret[n-1]);
1753 --n;
1756 return ret;
1759 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1761 TLBParDesc *ret;
1763 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1764 if(!ret)
1765 return NULL;
1767 while(n){
1768 list_init(&ret[n-1].custdata_list);
1769 --n;
1772 return ret;
1775 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1777 list_init(&func_desc->custdata_list);
1780 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1782 TLBFuncDesc *ret;
1784 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1785 if(!ret)
1786 return NULL;
1788 while(n){
1789 TLBFuncDesc_Constructor(&ret[n-1]);
1790 --n;
1793 return ret;
1796 static void TLBImplType_Constructor(TLBImplType *impl)
1798 list_init(&impl->custdata_list);
1801 static TLBImplType *TLBImplType_Alloc(UINT n)
1803 TLBImplType *ret;
1805 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1806 if(!ret)
1807 return NULL;
1809 while(n){
1810 TLBImplType_Constructor(&ret[n-1]);
1811 --n;
1814 return ret;
1817 static TLBGuid *TLB_append_guid(struct list *guid_list,
1818 const GUID *new_guid, HREFTYPE hreftype)
1820 TLBGuid *guid;
1822 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1823 if (IsEqualGUID(&guid->guid, new_guid))
1824 return guid;
1827 guid = heap_alloc(sizeof(TLBGuid));
1828 if (!guid)
1829 return NULL;
1831 memcpy(&guid->guid, new_guid, sizeof(GUID));
1832 guid->hreftype = hreftype;
1834 list_add_tail(guid_list, &guid->entry);
1836 return guid;
1839 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1841 TLBCustData *cust_data;
1843 switch(V_VT(var)){
1844 case VT_I4:
1845 case VT_R4:
1846 case VT_UI4:
1847 case VT_INT:
1848 case VT_UINT:
1849 case VT_HRESULT:
1850 case VT_BSTR:
1851 break;
1852 default:
1853 return DISP_E_BADVARTYPE;
1856 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1858 if (!cust_data) {
1859 cust_data = heap_alloc(sizeof(TLBCustData));
1860 if (!cust_data)
1861 return E_OUTOFMEMORY;
1863 cust_data->guid = tlbguid;
1864 VariantInit(&cust_data->data);
1866 list_add_tail(custdata_list, &cust_data->entry);
1867 }else
1868 VariantClear(&cust_data->data);
1870 return VariantCopy(&cust_data->data, var);
1873 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1875 TLBString *str;
1877 if(!new_str)
1878 return NULL;
1880 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1881 if (strcmpW(str->str, new_str) == 0)
1882 return str;
1885 str = heap_alloc(sizeof(TLBString));
1886 if (!str)
1887 return NULL;
1889 str->str = SysAllocString(new_str);
1890 if (!str->str) {
1891 heap_free(str);
1892 return NULL;
1895 list_add_tail(string_list, &str->entry);
1897 return str;
1900 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1901 ULONG *size, WORD *align)
1903 ITypeInfo *other;
1904 TYPEATTR *attr;
1905 HRESULT hr;
1907 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1908 if(FAILED(hr))
1909 return hr;
1911 hr = ITypeInfo_GetTypeAttr(other, &attr);
1912 if(FAILED(hr)){
1913 ITypeInfo_Release(other);
1914 return hr;
1917 if(size)
1918 *size = attr->cbSizeInstance;
1919 if(align)
1920 *align = attr->cbAlignment;
1922 ITypeInfo_ReleaseTypeAttr(other, attr);
1923 ITypeInfo_Release(other);
1925 return S_OK;
1928 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1929 TYPEDESC *tdesc, ULONG *size, WORD *align)
1931 ULONG i, sub, ptr_size;
1932 HRESULT hr;
1934 ptr_size = get_ptr_size(sys);
1936 switch(tdesc->vt){
1937 case VT_VOID:
1938 *size = 0;
1939 break;
1940 case VT_I1:
1941 case VT_UI1:
1942 *size = 1;
1943 break;
1944 case VT_I2:
1945 case VT_BOOL:
1946 case VT_UI2:
1947 *size = 2;
1948 break;
1949 case VT_I4:
1950 case VT_R4:
1951 case VT_ERROR:
1952 case VT_UI4:
1953 case VT_INT:
1954 case VT_UINT:
1955 case VT_HRESULT:
1956 *size = 4;
1957 break;
1958 case VT_R8:
1959 case VT_I8:
1960 case VT_UI8:
1961 *size = 8;
1962 break;
1963 case VT_BSTR:
1964 case VT_DISPATCH:
1965 case VT_UNKNOWN:
1966 case VT_PTR:
1967 case VT_SAFEARRAY:
1968 case VT_LPSTR:
1969 case VT_LPWSTR:
1970 *size = ptr_size;
1971 break;
1972 case VT_DATE:
1973 *size = sizeof(DATE);
1974 break;
1975 case VT_VARIANT:
1976 *size = sizeof(VARIANT);
1977 #ifdef _WIN64
1978 if(sys == SYS_WIN32)
1979 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1980 #endif
1981 break;
1982 case VT_DECIMAL:
1983 *size = sizeof(DECIMAL);
1984 break;
1985 case VT_CY:
1986 *size = sizeof(CY);
1987 break;
1988 case VT_CARRAY:
1989 *size = 0;
1990 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
1991 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
1992 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
1993 if(FAILED(hr))
1994 return hr;
1995 *size *= sub;
1996 return S_OK;
1997 case VT_USERDEFINED:
1998 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
1999 default:
2000 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2001 return E_FAIL;
2004 if(align){
2005 if(*size < 4)
2006 *align = *size;
2007 else
2008 *align = 4;
2011 return S_OK;
2014 /**********************************************************************
2016 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2019 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2021 if (where != DO_NOT_SEEK)
2023 where += pcx->oStart;
2024 if (where > pcx->length)
2026 /* FIXME */
2027 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2028 TLB_abort();
2030 pcx->pos = where;
2034 /* read function */
2035 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2037 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2038 pcx->pos, count, pcx->oStart, pcx->length, where);
2040 MSFT_Seek(pcx, where);
2041 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2042 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2043 pcx->pos += count;
2044 return count;
2047 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2048 LONG where )
2050 DWORD ret;
2052 ret = MSFT_Read(buffer, count, pcx, where);
2053 FromLEDWords(buffer, ret);
2055 return ret;
2058 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2059 LONG where )
2061 DWORD ret;
2063 ret = MSFT_Read(buffer, count, pcx, where);
2064 FromLEWords(buffer, ret);
2066 return ret;
2069 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2071 TLBGuid *guid;
2072 MSFT_GuidEntry entry;
2073 int offs = 0;
2075 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2076 while (1) {
2077 if (offs >= pcx->pTblDir->pGuidTab.length)
2078 return S_OK;
2080 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2082 guid = heap_alloc(sizeof(TLBGuid));
2084 guid->offset = offs;
2085 guid->guid = entry.guid;
2086 guid->hreftype = entry.hreftype;
2088 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2090 offs += sizeof(MSFT_GuidEntry);
2094 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2096 TLBGuid *ret;
2098 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2099 if(ret->offset == offset){
2100 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2101 return ret;
2105 return NULL;
2108 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2110 MSFT_NameIntro niName;
2112 if (offset < 0)
2114 ERR_(typelib)("bad offset %d\n", offset);
2115 return -1;
2118 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2119 pcx->pTblDir->pNametab.offset+offset);
2121 return niName.hreftype;
2124 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2126 char *string;
2127 MSFT_NameIntro intro;
2128 INT16 len_piece;
2129 int offs = 0, lengthInChars;
2131 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2132 while (1) {
2133 TLBString *tlbstr;
2135 if (offs >= pcx->pTblDir->pNametab.length)
2136 return S_OK;
2138 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2139 intro.namelen &= 0xFF;
2140 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2141 if(len_piece % 4)
2142 len_piece = (len_piece + 4) & ~0x3;
2143 if(len_piece < 8)
2144 len_piece = 8;
2146 string = heap_alloc(len_piece + 1);
2147 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2148 string[intro.namelen] = '\0';
2150 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2151 string, -1, NULL, 0);
2152 if (!lengthInChars) {
2153 heap_free(string);
2154 return E_UNEXPECTED;
2157 tlbstr = heap_alloc(sizeof(TLBString));
2159 tlbstr->offset = offs;
2160 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2161 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2163 heap_free(string);
2165 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2167 offs += len_piece;
2171 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2173 TLBString *tlbstr;
2175 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2176 if (tlbstr->offset == offset) {
2177 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2178 return tlbstr;
2182 return NULL;
2185 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2187 TLBString *tlbstr;
2189 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2190 if (tlbstr->offset == offset) {
2191 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2192 return tlbstr;
2196 return NULL;
2200 * read a value and fill a VARIANT structure
2202 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2204 int size;
2206 TRACE_(typelib)("\n");
2208 if(offset <0) { /* data are packed in here */
2209 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2210 V_I4(pVar) = offset & 0x3ffffff;
2211 return;
2213 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2214 pcx->pTblDir->pCustData.offset + offset );
2215 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2216 switch (V_VT(pVar)){
2217 case VT_EMPTY: /* FIXME: is this right? */
2218 case VT_NULL: /* FIXME: is this right? */
2219 case VT_I2 : /* this should not happen */
2220 case VT_I4 :
2221 case VT_R4 :
2222 case VT_ERROR :
2223 case VT_BOOL :
2224 case VT_I1 :
2225 case VT_UI1 :
2226 case VT_UI2 :
2227 case VT_UI4 :
2228 case VT_INT :
2229 case VT_UINT :
2230 case VT_VOID : /* FIXME: is this right? */
2231 case VT_HRESULT :
2232 size=4; break;
2233 case VT_R8 :
2234 case VT_CY :
2235 case VT_DATE :
2236 case VT_I8 :
2237 case VT_UI8 :
2238 case VT_DECIMAL : /* FIXME: is this right? */
2239 case VT_FILETIME :
2240 size=8;break;
2241 /* pointer types with known behaviour */
2242 case VT_BSTR :{
2243 char * ptr;
2244 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2245 if(size == -1){
2246 V_BSTR(pVar) = NULL;
2247 }else{
2248 ptr = heap_alloc_zero(size);
2249 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2250 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2251 /* FIXME: do we need a AtoW conversion here? */
2252 V_UNION(pVar, bstrVal[size])='\0';
2253 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2254 heap_free(ptr);
2257 size=-4; break;
2258 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2259 case VT_DISPATCH :
2260 case VT_VARIANT :
2261 case VT_UNKNOWN :
2262 case VT_PTR :
2263 case VT_SAFEARRAY :
2264 case VT_CARRAY :
2265 case VT_USERDEFINED :
2266 case VT_LPSTR :
2267 case VT_LPWSTR :
2268 case VT_BLOB :
2269 case VT_STREAM :
2270 case VT_STORAGE :
2271 case VT_STREAMED_OBJECT :
2272 case VT_STORED_OBJECT :
2273 case VT_BLOB_OBJECT :
2274 case VT_CF :
2275 case VT_CLSID :
2276 default:
2277 size=0;
2278 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2279 V_VT(pVar));
2282 if(size>0) /* (big|small) endian correct? */
2283 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2284 return;
2287 * create a linked list with custom data
2289 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2291 MSFT_CDGuid entry;
2292 TLBCustData* pNew;
2293 int count=0;
2295 TRACE_(typelib)("\n");
2297 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2299 while(offset >=0){
2300 count++;
2301 pNew=heap_alloc_zero(sizeof(TLBCustData));
2302 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2303 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2304 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2305 list_add_head(custdata_list, &pNew->entry);
2306 offset = entry.next;
2308 return count;
2311 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2313 if(type <0)
2314 pTd->vt=type & VT_TYPEMASK;
2315 else
2316 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2318 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2321 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2323 return (invkind == INVOKE_PROPERTYGET ||
2324 invkind == INVOKE_PROPERTYPUT ||
2325 invkind == INVOKE_PROPERTYPUTREF);
2328 static void
2329 MSFT_DoFuncs(TLBContext* pcx,
2330 ITypeInfoImpl* pTI,
2331 int cFuncs,
2332 int cVars,
2333 int offset,
2334 TLBFuncDesc** pptfd)
2337 * member information is stored in a data structure at offset
2338 * indicated by the memoffset field of the typeinfo structure
2339 * There are several distinctive parts.
2340 * The first part starts with a field that holds the total length
2341 * of this (first) part excluding this field. Then follow the records,
2342 * for each member there is one record.
2344 * The first entry is always the length of the record (including this
2345 * length word).
2346 * The rest of the record depends on the type of the member. If there is
2347 * a field indicating the member type (function, variable, interface, etc)
2348 * I have not found it yet. At this time we depend on the information
2349 * in the type info and the usual order how things are stored.
2351 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2352 * for each member;
2354 * Third is an equal sized array with file offsets to the name entry
2355 * of each member.
2357 * The fourth and last (?) part is an array with offsets to the records
2358 * in the first part of this file segment.
2361 int infolen, nameoffset, reclength, i;
2362 int recoffset = offset + sizeof(INT);
2364 char *recbuf = heap_alloc(0xffff);
2365 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2366 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2368 TRACE_(typelib)("\n");
2370 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2372 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2373 ptfd = *pptfd;
2374 for ( i = 0; i < cFuncs ; i++ )
2376 int optional;
2378 /* name, eventually add to a hash table */
2379 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2380 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2382 /* read the function information record */
2383 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2385 reclength &= 0xffff;
2387 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2389 /* size without argument data */
2390 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2391 if (pFuncRec->FKCCIC & 0x1000)
2392 optional -= pFuncRec->nrargs * sizeof(INT);
2394 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2395 ptfd->helpcontext = pFuncRec->HelpContext;
2397 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2398 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2400 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2402 if (pFuncRec->FKCCIC & 0x2000 )
2404 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2405 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2406 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2408 else
2409 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2411 else
2412 ptfd->Entry = (TLBString*)-1;
2414 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2415 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2417 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2418 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2420 /* fill the FuncDesc Structure */
2421 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2422 offset + infolen + ( i + 1) * sizeof(INT));
2424 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2425 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2426 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2427 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2428 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2429 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2430 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2432 /* nameoffset is sometimes -1 on the second half of a propget/propput
2433 * pair of functions */
2434 if ((nameoffset == -1) && (i > 0) &&
2435 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2436 TLB_is_propgetput(ptfd->funcdesc.invkind))
2437 ptfd->Name = ptfd_prev->Name;
2438 else
2439 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2441 MSFT_GetTdesc(pcx,
2442 pFuncRec->DataType,
2443 &ptfd->funcdesc.elemdescFunc.tdesc);
2445 /* do the parameters/arguments */
2446 if(pFuncRec->nrargs)
2448 int j = 0;
2449 MSFT_ParameterInfo paraminfo;
2451 ptfd->funcdesc.lprgelemdescParam =
2452 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2454 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2456 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2457 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2459 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2461 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2463 MSFT_GetTdesc(pcx,
2464 paraminfo.DataType,
2465 &elemdesc->tdesc);
2467 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2469 /* name */
2470 if (paraminfo.oName != -1)
2471 ptfd->pParamDesc[j].Name =
2472 MSFT_ReadName( pcx, paraminfo.oName );
2473 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2475 /* default value */
2476 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2477 (pFuncRec->FKCCIC & 0x1000) )
2479 INT* pInt = (INT *)((char *)pFuncRec +
2480 reclength -
2481 (pFuncRec->nrargs * 4) * sizeof(INT) );
2483 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2485 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2486 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2488 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2489 pInt[j], pcx);
2491 else
2492 elemdesc->u.paramdesc.pparamdescex = NULL;
2494 /* custom info */
2495 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2496 j*sizeof(pFuncRec->oArgCustData[0])) &&
2497 pFuncRec->FKCCIC & 0x80 )
2499 MSFT_CustData(pcx,
2500 pFuncRec->oArgCustData[j],
2501 &ptfd->pParamDesc[j].custdata_list);
2504 /* SEEK value = jump to offset,
2505 * from there jump to the end of record,
2506 * go back by (j-1) arguments
2508 MSFT_ReadLEDWords( &paraminfo ,
2509 sizeof(MSFT_ParameterInfo), pcx,
2510 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2511 * sizeof(MSFT_ParameterInfo)));
2515 /* scode is not used: archaic win16 stuff FIXME: right? */
2516 ptfd->funcdesc.cScodes = 0 ;
2517 ptfd->funcdesc.lprgscode = NULL ;
2519 ptfd_prev = ptfd;
2520 ++ptfd;
2521 recoffset += reclength;
2523 heap_free(recbuf);
2526 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2527 int cVars, int offset, TLBVarDesc ** pptvd)
2529 int infolen, nameoffset, reclength;
2530 char recbuf[256];
2531 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2532 TLBVarDesc *ptvd;
2533 int i;
2534 int recoffset;
2536 TRACE_(typelib)("\n");
2538 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2539 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2540 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2541 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2542 recoffset += offset+sizeof(INT);
2543 for(i=0;i<cVars;i++, ++ptvd){
2544 /* name, eventually add to a hash table */
2545 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2546 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2547 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2548 /* read the variable information record */
2549 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2550 reclength &= 0xff;
2551 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2553 /* optional data */
2554 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2555 ptvd->HelpContext = pVarRec->HelpContext;
2557 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2558 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2560 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2561 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2563 /* fill the VarDesc Structure */
2564 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2565 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2566 ptvd->vardesc.varkind = pVarRec->VarKind;
2567 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2568 MSFT_GetTdesc(pcx, pVarRec->DataType,
2569 &ptvd->vardesc.elemdescVar.tdesc);
2570 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2571 if(pVarRec->VarKind == VAR_CONST ){
2572 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2573 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2574 pVarRec->OffsValue, pcx);
2575 } else
2576 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2577 recoffset += reclength;
2581 /* process Implemented Interfaces of a com class */
2582 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2583 int offset)
2585 int i;
2586 MSFT_RefRecord refrec;
2587 TLBImplType *pImpl;
2589 TRACE_(typelib)("\n");
2591 pTI->impltypes = TLBImplType_Alloc(count);
2592 pImpl = pTI->impltypes;
2593 for(i=0;i<count;i++){
2594 if(offset<0) break; /* paranoia */
2595 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2596 pImpl->hRef = refrec.reftype;
2597 pImpl->implflags=refrec.flags;
2598 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2599 offset=refrec.onext;
2600 ++pImpl;
2604 #ifdef _WIN64
2605 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2606 * and some structures, and fix the alignment */
2607 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2609 if(info->typeattr.typekind == TKIND_ALIAS){
2610 switch(info->tdescAlias->vt){
2611 case VT_BSTR:
2612 case VT_DISPATCH:
2613 case VT_UNKNOWN:
2614 case VT_PTR:
2615 case VT_SAFEARRAY:
2616 case VT_LPSTR:
2617 case VT_LPWSTR:
2618 info->typeattr.cbSizeInstance = sizeof(void*);
2619 info->typeattr.cbAlignment = sizeof(void*);
2620 break;
2621 case VT_CARRAY:
2622 case VT_USERDEFINED:
2623 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2624 break;
2625 case VT_VARIANT:
2626 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2627 info->typeattr.cbAlignment = 8;
2628 default:
2629 if(info->typeattr.cbSizeInstance < sizeof(void*))
2630 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2631 else
2632 info->typeattr.cbAlignment = sizeof(void*);
2633 break;
2635 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2636 info->typeattr.typekind == TKIND_DISPATCH ||
2637 info->typeattr.typekind == TKIND_COCLASS){
2638 info->typeattr.cbSizeInstance = sizeof(void*);
2639 info->typeattr.cbAlignment = sizeof(void*);
2642 #endif
2645 * process a typeinfo record
2647 static ITypeInfoImpl * MSFT_DoTypeInfo(
2648 TLBContext *pcx,
2649 int count,
2650 ITypeLibImpl * pLibInfo)
2652 MSFT_TypeInfoBase tiBase;
2653 ITypeInfoImpl *ptiRet;
2655 TRACE_(typelib)("count=%u\n", count);
2657 ptiRet = ITypeInfoImpl_Constructor();
2658 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2659 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2661 /* this is where we are coming from */
2662 ptiRet->pTypeLib = pLibInfo;
2663 ptiRet->index=count;
2665 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2666 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2667 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2668 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2669 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2670 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2671 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2672 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2673 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2674 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2675 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2676 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2677 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2678 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2679 TYPEDESC tmp;
2680 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2681 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2682 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2685 /* FIXME: */
2686 /* IDLDESC idldescType; *//* never saw this one != zero */
2688 /* name, eventually add to a hash table */
2689 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2690 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2691 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2692 /* help info */
2693 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2694 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2695 ptiRet->dwHelpContext=tiBase.helpcontext;
2697 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2698 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2700 /* note: InfoType's Help file and HelpStringDll come from the containing
2701 * library. Further HelpString and Docstring appear to be the same thing :(
2703 /* functions */
2704 if(ptiRet->typeattr.cFuncs >0 )
2705 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2706 ptiRet->typeattr.cVars,
2707 tiBase.memoffset, &ptiRet->funcdescs);
2708 /* variables */
2709 if(ptiRet->typeattr.cVars >0 )
2710 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2711 ptiRet->typeattr.cVars,
2712 tiBase.memoffset, &ptiRet->vardescs);
2713 if(ptiRet->typeattr.cImplTypes >0 ) {
2714 switch(ptiRet->typeattr.typekind)
2716 case TKIND_COCLASS:
2717 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2718 tiBase.datatype1);
2719 break;
2720 case TKIND_DISPATCH:
2721 /* This is not -1 when the interface is a non-base dual interface or
2722 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2723 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2724 not this interface.
2727 if (tiBase.datatype1 != -1)
2729 ptiRet->impltypes = TLBImplType_Alloc(1);
2730 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2732 break;
2733 default:
2734 ptiRet->impltypes = TLBImplType_Alloc(1);
2735 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2736 break;
2739 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2741 TRACE_(typelib)("%s guid: %s kind:%s\n",
2742 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2743 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2744 typekind_desc[ptiRet->typeattr.typekind]);
2745 if (TRACE_ON(typelib))
2746 dump_TypeInfo(ptiRet);
2748 return ptiRet;
2751 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2753 char *string;
2754 INT16 len_str, len_piece;
2755 int offs = 0, lengthInChars;
2757 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2758 while (1) {
2759 TLBString *tlbstr;
2761 if (offs >= pcx->pTblDir->pStringtab.length)
2762 return S_OK;
2764 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2765 len_piece = len_str + sizeof(INT16);
2766 if(len_piece % 4)
2767 len_piece = (len_piece + 4) & ~0x3;
2768 if(len_piece < 8)
2769 len_piece = 8;
2771 string = heap_alloc(len_piece + 1);
2772 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2773 string[len_str] = '\0';
2775 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2776 string, -1, NULL, 0);
2777 if (!lengthInChars) {
2778 heap_free(string);
2779 return E_UNEXPECTED;
2782 tlbstr = heap_alloc(sizeof(TLBString));
2784 tlbstr->offset = offs;
2785 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2786 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2788 heap_free(string);
2790 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2792 offs += len_piece;
2796 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2798 TLBRefType *ref;
2799 int offs = 0;
2801 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2802 while (offs < pcx->pTblDir->pImpInfo.length) {
2803 MSFT_ImpInfo impinfo;
2804 TLBImpLib *pImpLib;
2806 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2808 ref = heap_alloc_zero(sizeof(TLBRefType));
2809 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2811 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2812 if(pImpLib->offset==impinfo.oImpFile)
2813 break;
2815 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2816 ref->reference = offs;
2817 ref->pImpTLInfo = pImpLib;
2818 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2819 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2820 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2821 ref->index = TLB_REF_USE_GUID;
2822 } else
2823 ref->index = impinfo.oGuid;
2824 }else{
2825 ERR("Cannot find a reference\n");
2826 ref->reference = -1;
2827 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2830 offs += sizeof(impinfo);
2833 return S_OK;
2836 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2837 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2838 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2839 * tradeoff here.
2841 static struct list tlb_cache = LIST_INIT(tlb_cache);
2842 static CRITICAL_SECTION cache_section;
2843 static CRITICAL_SECTION_DEBUG cache_section_debug =
2845 0, 0, &cache_section,
2846 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2847 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2849 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2852 typedef struct TLB_PEFile
2854 IUnknown IUnknown_iface;
2855 LONG refs;
2856 HMODULE dll;
2857 HRSRC typelib_resource;
2858 HGLOBAL typelib_global;
2859 LPVOID typelib_base;
2860 } TLB_PEFile;
2862 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2864 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2867 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2869 if (IsEqualIID(riid, &IID_IUnknown))
2871 *ppv = iface;
2872 IUnknown_AddRef(iface);
2873 return S_OK;
2875 *ppv = NULL;
2876 return E_NOINTERFACE;
2879 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2881 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2882 return InterlockedIncrement(&This->refs);
2885 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2887 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2888 ULONG refs = InterlockedDecrement(&This->refs);
2889 if (!refs)
2891 if (This->typelib_global)
2892 FreeResource(This->typelib_global);
2893 if (This->dll)
2894 FreeLibrary(This->dll);
2895 heap_free(This);
2897 return refs;
2900 static const IUnknownVtbl TLB_PEFile_Vtable =
2902 TLB_PEFile_QueryInterface,
2903 TLB_PEFile_AddRef,
2904 TLB_PEFile_Release
2907 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2909 TLB_PEFile *This;
2910 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2912 This = heap_alloc(sizeof(TLB_PEFile));
2913 if (!This)
2914 return E_OUTOFMEMORY;
2916 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2917 This->refs = 1;
2918 This->dll = NULL;
2919 This->typelib_resource = NULL;
2920 This->typelib_global = NULL;
2921 This->typelib_base = NULL;
2923 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2924 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2926 if (This->dll)
2928 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2929 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2930 if (This->typelib_resource)
2932 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2933 if (This->typelib_global)
2935 This->typelib_base = LockResource(This->typelib_global);
2937 if (This->typelib_base)
2939 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2940 *ppBase = This->typelib_base;
2941 *ppFile = &This->IUnknown_iface;
2942 return S_OK;
2947 TRACE("No TYPELIB resource found\n");
2948 hr = E_FAIL;
2951 TLB_PEFile_Release(&This->IUnknown_iface);
2952 return hr;
2955 typedef struct TLB_NEFile
2957 IUnknown IUnknown_iface;
2958 LONG refs;
2959 LPVOID typelib_base;
2960 } TLB_NEFile;
2962 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2964 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2967 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2969 if (IsEqualIID(riid, &IID_IUnknown))
2971 *ppv = iface;
2972 IUnknown_AddRef(iface);
2973 return S_OK;
2975 *ppv = NULL;
2976 return E_NOINTERFACE;
2979 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2981 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2982 return InterlockedIncrement(&This->refs);
2985 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2987 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2988 ULONG refs = InterlockedDecrement(&This->refs);
2989 if (!refs)
2991 heap_free(This->typelib_base);
2992 heap_free(This);
2994 return refs;
2997 static const IUnknownVtbl TLB_NEFile_Vtable =
2999 TLB_NEFile_QueryInterface,
3000 TLB_NEFile_AddRef,
3001 TLB_NEFile_Release
3004 /***********************************************************************
3005 * read_xx_header [internal]
3007 static int read_xx_header( HFILE lzfd )
3009 IMAGE_DOS_HEADER mzh;
3010 char magic[3];
3012 LZSeek( lzfd, 0, SEEK_SET );
3013 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3014 return 0;
3015 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3016 return 0;
3018 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3019 if ( 2 != LZRead( lzfd, magic, 2 ) )
3020 return 0;
3022 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3024 if ( magic[0] == 'N' && magic[1] == 'E' )
3025 return IMAGE_OS2_SIGNATURE;
3026 if ( magic[0] == 'P' && magic[1] == 'E' )
3027 return IMAGE_NT_SIGNATURE;
3029 magic[2] = '\0';
3030 WARN("Can't handle %s files.\n", magic );
3031 return 0;
3035 /***********************************************************************
3036 * find_ne_resource [internal]
3038 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3039 DWORD *resLen, DWORD *resOff )
3041 IMAGE_OS2_HEADER nehd;
3042 NE_TYPEINFO *typeInfo;
3043 NE_NAMEINFO *nameInfo;
3044 DWORD nehdoffset;
3045 LPBYTE resTab;
3046 DWORD resTabSize;
3047 int count;
3049 /* Read in NE header */
3050 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3051 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3053 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3054 if ( !resTabSize )
3056 TRACE("No resources in NE dll\n" );
3057 return FALSE;
3060 /* Read in resource table */
3061 resTab = heap_alloc( resTabSize );
3062 if ( !resTab ) return FALSE;
3064 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3065 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3067 heap_free( resTab );
3068 return FALSE;
3071 /* Find resource */
3072 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3074 if (!IS_INTRESOURCE(typeid)) /* named type */
3076 BYTE len = strlen( typeid );
3077 while (typeInfo->type_id)
3079 if (!(typeInfo->type_id & 0x8000))
3081 BYTE *p = resTab + typeInfo->type_id;
3082 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3084 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3085 typeInfo->count * sizeof(NE_NAMEINFO));
3088 else /* numeric type id */
3090 WORD id = LOWORD(typeid) | 0x8000;
3091 while (typeInfo->type_id)
3093 if (typeInfo->type_id == id) goto found_type;
3094 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3095 typeInfo->count * sizeof(NE_NAMEINFO));
3098 TRACE("No typeid entry found for %p\n", typeid );
3099 heap_free( resTab );
3100 return FALSE;
3102 found_type:
3103 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3105 if (!IS_INTRESOURCE(resid)) /* named resource */
3107 BYTE len = strlen( resid );
3108 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3110 BYTE *p = resTab + nameInfo->id;
3111 if (nameInfo->id & 0x8000) continue;
3112 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3115 else /* numeric resource id */
3117 WORD id = LOWORD(resid) | 0x8000;
3118 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3119 if (nameInfo->id == id) goto found_name;
3121 TRACE("No resid entry found for %p\n", typeid );
3122 heap_free( resTab );
3123 return FALSE;
3125 found_name:
3126 /* Return resource data */
3127 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3128 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3130 heap_free( resTab );
3131 return TRUE;
3134 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3136 HFILE lzfd = -1;
3137 OFSTRUCT ofs;
3138 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3139 TLB_NEFile *This;
3141 This = heap_alloc(sizeof(TLB_NEFile));
3142 if (!This) return E_OUTOFMEMORY;
3144 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3145 This->refs = 1;
3146 This->typelib_base = NULL;
3148 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3149 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3151 DWORD reslen, offset;
3152 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3154 This->typelib_base = heap_alloc(reslen);
3155 if( !This->typelib_base )
3156 hr = E_OUTOFMEMORY;
3157 else
3159 LZSeek( lzfd, offset, SEEK_SET );
3160 reslen = LZRead( lzfd, This->typelib_base, reslen );
3161 LZClose( lzfd );
3162 *ppBase = This->typelib_base;
3163 *pdwTLBLength = reslen;
3164 *ppFile = &This->IUnknown_iface;
3165 return S_OK;
3170 if( lzfd >= 0) LZClose( lzfd );
3171 TLB_NEFile_Release(&This->IUnknown_iface);
3172 return hr;
3175 typedef struct TLB_Mapping
3177 IUnknown IUnknown_iface;
3178 LONG refs;
3179 HANDLE file;
3180 HANDLE mapping;
3181 LPVOID typelib_base;
3182 } TLB_Mapping;
3184 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3186 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3189 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3191 if (IsEqualIID(riid, &IID_IUnknown))
3193 *ppv = iface;
3194 IUnknown_AddRef(iface);
3195 return S_OK;
3197 *ppv = NULL;
3198 return E_NOINTERFACE;
3201 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3203 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3204 return InterlockedIncrement(&This->refs);
3207 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3209 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3210 ULONG refs = InterlockedDecrement(&This->refs);
3211 if (!refs)
3213 if (This->typelib_base)
3214 UnmapViewOfFile(This->typelib_base);
3215 if (This->mapping)
3216 CloseHandle(This->mapping);
3217 if (This->file != INVALID_HANDLE_VALUE)
3218 CloseHandle(This->file);
3219 heap_free(This);
3221 return refs;
3224 static const IUnknownVtbl TLB_Mapping_Vtable =
3226 TLB_Mapping_QueryInterface,
3227 TLB_Mapping_AddRef,
3228 TLB_Mapping_Release
3231 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3233 TLB_Mapping *This;
3235 This = heap_alloc(sizeof(TLB_Mapping));
3236 if (!This)
3237 return E_OUTOFMEMORY;
3239 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3240 This->refs = 1;
3241 This->file = INVALID_HANDLE_VALUE;
3242 This->mapping = NULL;
3243 This->typelib_base = NULL;
3245 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3246 if (INVALID_HANDLE_VALUE != This->file)
3248 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3249 if (This->mapping)
3251 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3252 if(This->typelib_base)
3254 /* retrieve file size */
3255 *pdwTLBLength = GetFileSize(This->file, NULL);
3256 *ppBase = This->typelib_base;
3257 *ppFile = &This->IUnknown_iface;
3258 return S_OK;
3263 IUnknown_Release(&This->IUnknown_iface);
3264 return TYPE_E_CANTLOADLIBRARY;
3267 /****************************************************************************
3268 * TLB_ReadTypeLib
3270 * find the type of the typelib file and map the typelib resource into
3271 * the memory
3274 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3275 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3277 ITypeLibImpl *entry;
3278 HRESULT ret;
3279 INT index = 1;
3280 LPWSTR index_str, file = (LPWSTR)pszFileName;
3281 LPVOID pBase = NULL;
3282 DWORD dwTLBLength = 0;
3283 IUnknown *pFile = NULL;
3284 HANDLE h;
3286 *ppTypeLib = NULL;
3288 index_str = strrchrW(pszFileName, '\\');
3289 if(index_str && *++index_str != '\0')
3291 LPWSTR end_ptr;
3292 LONG idx = strtolW(index_str, &end_ptr, 10);
3293 if(*end_ptr == '\0')
3295 int str_len = index_str - pszFileName - 1;
3296 index = idx;
3297 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3298 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3299 file[str_len] = 0;
3303 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3305 if(strchrW(file, '\\'))
3307 lstrcpyW(pszPath, file);
3309 else
3311 int len = GetSystemDirectoryW(pszPath, cchPath);
3312 pszPath[len] = '\\';
3313 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3317 if(file != pszFileName) heap_free(file);
3319 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3320 if(h != INVALID_HANDLE_VALUE){
3321 FILE_NAME_INFORMATION size_info;
3322 BOOL br;
3324 /* GetFileInformationByHandleEx returns the path of the file without
3325 * WOW64 redirection */
3326 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3327 if(br || GetLastError() == ERROR_MORE_DATA){
3328 FILE_NAME_INFORMATION *info;
3329 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3331 info = HeapAlloc(GetProcessHeap(), 0, size);
3333 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3334 if(br){
3335 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3336 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3339 HeapFree(GetProcessHeap(), 0, info);
3342 CloseHandle(h);
3345 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3347 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3348 EnterCriticalSection(&cache_section);
3349 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3351 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3353 TRACE("cache hit\n");
3354 *ppTypeLib = &entry->ITypeLib2_iface;
3355 ITypeLib2_AddRef(*ppTypeLib);
3356 LeaveCriticalSection(&cache_section);
3357 return S_OK;
3360 LeaveCriticalSection(&cache_section);
3362 /* now actually load and parse the typelib */
3364 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3365 if (ret == TYPE_E_CANTLOADLIBRARY)
3366 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3367 if (ret == TYPE_E_CANTLOADLIBRARY)
3368 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3369 if (SUCCEEDED(ret))
3371 if (dwTLBLength >= 4)
3373 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3374 if (dwSignature == MSFT_SIGNATURE)
3375 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3376 else if (dwSignature == SLTG_SIGNATURE)
3377 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3378 else
3380 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3381 ret = TYPE_E_CANTLOADLIBRARY;
3384 else
3385 ret = TYPE_E_CANTLOADLIBRARY;
3386 IUnknown_Release(pFile);
3389 if(*ppTypeLib) {
3390 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3392 TRACE("adding to cache\n");
3393 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3394 lstrcpyW(impl->path, pszPath);
3395 /* We should really canonicalise the path here. */
3396 impl->index = index;
3398 /* FIXME: check if it has added already in the meantime */
3399 EnterCriticalSection(&cache_section);
3400 list_add_head(&tlb_cache, &impl->entry);
3401 LeaveCriticalSection(&cache_section);
3402 ret = S_OK;
3404 else
3406 if(ret != E_FAIL)
3407 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3409 ret = TYPE_E_CANTLOADLIBRARY;
3413 return ret;
3416 /*================== ITypeLib(2) Methods ===================================*/
3418 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3420 ITypeLibImpl* pTypeLibImpl;
3422 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3423 if (!pTypeLibImpl) return NULL;
3425 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3426 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3427 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3428 pTypeLibImpl->ref = 1;
3430 list_init(&pTypeLibImpl->implib_list);
3431 list_init(&pTypeLibImpl->custdata_list);
3432 list_init(&pTypeLibImpl->name_list);
3433 list_init(&pTypeLibImpl->string_list);
3434 list_init(&pTypeLibImpl->guid_list);
3435 list_init(&pTypeLibImpl->ref_list);
3436 pTypeLibImpl->dispatch_href = -1;
3438 return pTypeLibImpl;
3441 /****************************************************************************
3442 * ITypeLib2_Constructor_MSFT
3444 * loading an MSFT typelib from an in-memory image
3446 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3448 TLBContext cx;
3449 LONG lPSegDir;
3450 MSFT_Header tlbHeader;
3451 MSFT_SegDir tlbSegDir;
3452 ITypeLibImpl * pTypeLibImpl;
3453 int i;
3455 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3457 pTypeLibImpl = TypeLibImpl_Constructor();
3458 if (!pTypeLibImpl) return NULL;
3460 /* get pointer to beginning of typelib data */
3461 cx.pos = 0;
3462 cx.oStart=0;
3463 cx.mapping = pLib;
3464 cx.pLibInfo = pTypeLibImpl;
3465 cx.length = dwTLBLength;
3467 /* read header */
3468 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3469 TRACE_(typelib)("header:\n");
3470 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3471 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3472 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3473 return NULL;
3475 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3477 /* there is a small amount of information here until the next important
3478 * part:
3479 * the segment directory . Try to calculate the amount of data */
3480 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3482 /* now read the segment directory */
3483 TRACE("read segment directory (at %d)\n",lPSegDir);
3484 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3485 cx.pTblDir = &tlbSegDir;
3487 /* just check two entries */
3488 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3490 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3491 heap_free(pTypeLibImpl);
3492 return NULL;
3495 MSFT_ReadAllNames(&cx);
3496 MSFT_ReadAllStrings(&cx);
3497 MSFT_ReadAllGuids(&cx);
3499 /* now fill our internal data */
3500 /* TLIBATTR fields */
3501 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3503 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3504 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3505 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3506 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3507 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3509 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3510 pTypeLibImpl->lcid = tlbHeader.lcid;
3512 /* name, eventually add to a hash table */
3513 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3515 /* help info */
3516 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3517 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3519 if( tlbHeader.varflags & HELPDLLFLAG)
3521 int offset;
3522 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3523 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3526 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3528 /* custom data */
3529 if(tlbHeader.CustomDataOffset >= 0)
3531 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3534 /* fill in type descriptions */
3535 if(tlbSegDir.pTypdescTab.length > 0)
3537 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3538 INT16 td[4];
3539 pTypeLibImpl->ctTypeDesc = cTD;
3540 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3541 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3542 for(i=0; i<cTD; )
3544 /* FIXME: add several sanity checks here */
3545 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3546 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3548 /* FIXME: check safearray */
3549 if(td[3] < 0)
3550 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3551 else
3552 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3554 else if(td[0] == VT_CARRAY)
3556 /* array descr table here */
3557 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3559 else if(td[0] == VT_USERDEFINED)
3561 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3563 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3566 /* second time around to fill the array subscript info */
3567 for(i=0;i<cTD;i++)
3569 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3570 if(tlbSegDir.pArrayDescriptions.offset>0)
3572 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3573 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3575 if(td[1]<0)
3576 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3577 else
3578 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3580 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3582 for(j = 0; j<td[2]; j++)
3584 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3585 sizeof(INT), &cx, DO_NOT_SEEK);
3586 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3587 sizeof(INT), &cx, DO_NOT_SEEK);
3590 else
3592 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3593 ERR("didn't find array description data\n");
3598 /* imported type libs */
3599 if(tlbSegDir.pImpFiles.offset>0)
3601 TLBImpLib *pImpLib;
3602 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3603 UINT16 size;
3605 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3607 char *name;
3609 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3610 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3611 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3613 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3614 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3615 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3616 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3618 size >>= 2;
3619 name = heap_alloc_zero(size+1);
3620 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3621 pImpLib->name = TLB_MultiByteToBSTR(name);
3622 heap_free(name);
3624 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3625 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3627 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3631 MSFT_ReadAllRefs(&cx);
3633 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3635 /* type infos */
3636 if(tlbHeader.nrtypeinfos >= 0 )
3638 ITypeInfoImpl **ppTI;
3640 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3642 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3644 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3646 ++ppTI;
3647 (pTypeLibImpl->TypeInfoCount)++;
3651 #ifdef _WIN64
3652 if(pTypeLibImpl->syskind == SYS_WIN32){
3653 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3654 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3656 #endif
3658 TRACE("(%p)\n", pTypeLibImpl);
3659 return &pTypeLibImpl->ITypeLib2_iface;
3663 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3665 char b[3];
3666 int i;
3667 short s;
3669 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3670 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3671 return FALSE;
3674 guid->Data4[0] = s >> 8;
3675 guid->Data4[1] = s & 0xff;
3677 b[2] = '\0';
3678 for(i = 0; i < 6; i++) {
3679 memcpy(b, str + 24 + 2 * i, 2);
3680 guid->Data4[i + 2] = strtol(b, NULL, 16);
3682 return TRUE;
3685 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3687 WORD bytelen;
3688 DWORD len;
3689 BSTR tmp_str;
3691 *pStr = NULL;
3692 bytelen = *(const WORD*)ptr;
3693 if(bytelen == 0xffff) return 2;
3695 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3696 tmp_str = SysAllocStringLen(NULL, len);
3697 if (tmp_str) {
3698 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3699 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3700 SysFreeString(tmp_str);
3702 return bytelen + 2;
3705 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3707 WORD bytelen;
3709 *str = NULL;
3710 bytelen = *(const WORD*)ptr;
3711 if(bytelen == 0xffff) return 2;
3712 *str = heap_alloc(bytelen + 1);
3713 memcpy(*str, ptr + 2, bytelen);
3714 (*str)[bytelen] = '\0';
3715 return bytelen + 2;
3718 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3720 BSTR tmp_str;
3721 TLBString *tlbstr;
3723 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3724 if (tlbstr->offset == offset)
3725 return tlbstr;
3728 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3729 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3730 SysFreeString(tmp_str);
3732 return tlbstr;
3735 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3737 char *ptr = pLibBlk;
3738 WORD w;
3740 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3741 FIXME("libblk magic = %04x\n", w);
3742 return 0;
3745 ptr += 6;
3746 if((w = *(WORD*)ptr) != 0xffff) {
3747 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3748 ptr += w;
3750 ptr += 2;
3752 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3754 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3756 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3757 ptr += 4;
3759 pTypeLibImpl->syskind = *(WORD*)ptr;
3760 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3761 ptr += 2;
3763 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3764 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3765 else
3766 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3767 ptr += 2;
3769 ptr += 4; /* skip res12 */
3771 pTypeLibImpl->libflags = *(WORD*)ptr;
3772 ptr += 2;
3774 pTypeLibImpl->ver_major = *(WORD*)ptr;
3775 ptr += 2;
3777 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3778 ptr += 2;
3780 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3781 ptr += sizeof(GUID);
3783 return ptr - (char*)pLibBlk;
3786 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3787 typedef struct
3789 unsigned int num;
3790 HREFTYPE refs[1];
3791 } sltg_ref_lookup_t;
3793 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3794 HREFTYPE *typelib_ref)
3796 if(table && typeinfo_ref < table->num)
3798 *typelib_ref = table->refs[typeinfo_ref];
3799 return S_OK;
3802 ERR_(typelib)("Unable to find reference\n");
3803 *typelib_ref = -1;
3804 return E_FAIL;
3807 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3809 BOOL done = FALSE;
3811 while(!done) {
3812 if((*pType & 0xe00) == 0xe00) {
3813 pTD->vt = VT_PTR;
3814 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3815 pTD = pTD->u.lptdesc;
3817 switch(*pType & 0x3f) {
3818 case VT_PTR:
3819 pTD->vt = VT_PTR;
3820 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3821 pTD = pTD->u.lptdesc;
3822 break;
3824 case VT_USERDEFINED:
3825 pTD->vt = VT_USERDEFINED;
3826 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3827 done = TRUE;
3828 break;
3830 case VT_CARRAY:
3832 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3833 array */
3835 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3837 pTD->vt = VT_CARRAY;
3838 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3839 pTD->u.lpadesc->cDims = pSA->cDims;
3840 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3841 pSA->cDims * sizeof(SAFEARRAYBOUND));
3843 pTD = &pTD->u.lpadesc->tdescElem;
3844 break;
3847 case VT_SAFEARRAY:
3849 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3850 useful? */
3852 pType++;
3853 pTD->vt = VT_SAFEARRAY;
3854 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3855 pTD = pTD->u.lptdesc;
3856 break;
3858 default:
3859 pTD->vt = *pType & 0x3f;
3860 done = TRUE;
3861 break;
3863 pType++;
3865 return pType;
3868 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3869 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3871 /* Handle [in/out] first */
3872 if((*pType & 0xc000) == 0xc000)
3873 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3874 else if(*pType & 0x8000)
3875 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3876 else if(*pType & 0x4000)
3877 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3878 else
3879 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3881 if(*pType & 0x2000)
3882 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3884 if(*pType & 0x80)
3885 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3887 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3891 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3892 char *pNameTable)
3894 unsigned int ref;
3895 char *name;
3896 TLBRefType *ref_type;
3897 sltg_ref_lookup_t *table;
3898 HREFTYPE typelib_ref;
3900 if(pRef->magic != SLTG_REF_MAGIC) {
3901 FIXME("Ref magic = %x\n", pRef->magic);
3902 return NULL;
3904 name = ( (char*)pRef->names + pRef->number);
3906 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3907 table->num = pRef->number >> 3;
3909 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3911 /* We don't want the first href to be 0 */
3912 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3914 for(ref = 0; ref < pRef->number >> 3; ref++) {
3915 char *refname;
3916 unsigned int lib_offs, type_num;
3918 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3920 name += SLTG_ReadStringA(name, &refname);
3921 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3922 FIXME_(typelib)("Can't sscanf ref\n");
3923 if(lib_offs != 0xffff) {
3924 TLBImpLib *import;
3926 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3927 if(import->offset == lib_offs)
3928 break;
3930 if(&import->entry == &pTL->implib_list) {
3931 char fname[MAX_PATH+1];
3932 int len;
3933 GUID tmpguid;
3935 import = heap_alloc_zero(sizeof(*import));
3936 import->offset = lib_offs;
3937 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3938 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3939 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3940 &import->wVersionMajor,
3941 &import->wVersionMinor,
3942 &import->lcid, fname) != 4) {
3943 FIXME_(typelib)("can't sscanf ref %s\n",
3944 pNameTable + lib_offs + 40);
3946 len = strlen(fname);
3947 if(fname[len-1] != '#')
3948 FIXME("fname = %s\n", fname);
3949 fname[len-1] = '\0';
3950 import->name = TLB_MultiByteToBSTR(fname);
3951 list_add_tail(&pTL->implib_list, &import->entry);
3953 ref_type->pImpTLInfo = import;
3955 /* Store a reference to IDispatch */
3956 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3957 pTL->dispatch_href = typelib_ref;
3959 } else { /* internal ref */
3960 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3962 ref_type->reference = typelib_ref;
3963 ref_type->index = type_num;
3965 heap_free(refname);
3966 list_add_tail(&pTL->ref_list, &ref_type->entry);
3968 table->refs[ref] = typelib_ref;
3969 typelib_ref += 4;
3971 if((BYTE)*name != SLTG_REF_MAGIC)
3972 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3973 dump_TLBRefType(pTL);
3974 return table;
3977 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3978 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3980 SLTG_ImplInfo *info;
3981 TLBImplType *pImplType;
3982 /* I don't really get this structure, usually it's 0x16 bytes
3983 long, but iuser.tlb contains some that are 0x18 bytes long.
3984 That's ok because we can use the next ptr to jump to the next
3985 one. But how do we know the length of the last one? The WORD
3986 at offs 0x8 might be the clue. For now I'm just assuming that
3987 the last one is the regular 0x16 bytes. */
3989 info = (SLTG_ImplInfo*)pBlk;
3990 while(1){
3991 pTI->typeattr.cImplTypes++;
3992 if(info->next == 0xffff)
3993 break;
3994 info = (SLTG_ImplInfo*)(pBlk + info->next);
3997 info = (SLTG_ImplInfo*)pBlk;
3998 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
3999 pImplType = pTI->impltypes;
4000 while(1) {
4001 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4002 pImplType->implflags = info->impltypeflags;
4003 ++pImplType;
4005 if(info->next == 0xffff)
4006 break;
4007 if(OneOnly)
4008 FIXME_(typelib)("Interface inheriting more than one interface\n");
4009 info = (SLTG_ImplInfo*)(pBlk + info->next);
4011 info++; /* see comment at top of function */
4012 return (char*)info;
4015 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4016 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4018 TLBVarDesc *pVarDesc;
4019 const TLBString *prevName = NULL;
4020 SLTG_Variable *pItem;
4021 unsigned short i;
4022 WORD *pType;
4024 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4026 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4027 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4029 pVarDesc->vardesc.memid = pItem->memid;
4031 if (pItem->magic != SLTG_VAR_MAGIC &&
4032 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4033 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4034 return;
4037 if (pItem->name == 0xfffe)
4038 pVarDesc->Name = prevName;
4039 else
4040 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4042 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4043 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4044 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4046 if(pItem->flags & 0x02)
4047 pType = &pItem->type;
4048 else
4049 pType = (WORD*)(pBlk + pItem->type);
4051 if (pItem->flags & ~0xda)
4052 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4054 SLTG_DoElem(pType, pBlk,
4055 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4057 if (TRACE_ON(typelib)) {
4058 char buf[300];
4059 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4060 TRACE_(typelib)("elemdescVar: %s\n", buf);
4063 if (pItem->flags & 0x40) {
4064 TRACE_(typelib)("VAR_DISPATCH\n");
4065 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4067 else if (pItem->flags & 0x10) {
4068 TRACE_(typelib)("VAR_CONST\n");
4069 pVarDesc->vardesc.varkind = VAR_CONST;
4070 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4071 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4072 if (pItem->flags & 0x08)
4073 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4074 else {
4075 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4077 case VT_LPSTR:
4078 case VT_LPWSTR:
4079 case VT_BSTR:
4081 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4082 BSTR str;
4083 TRACE_(typelib)("len = %u\n", len);
4084 if (len == 0xffff) {
4085 str = NULL;
4086 } else {
4087 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4088 str = SysAllocStringLen(NULL, alloc_len);
4089 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4091 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4092 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4093 break;
4095 case VT_I2:
4096 case VT_UI2:
4097 case VT_I4:
4098 case VT_UI4:
4099 case VT_INT:
4100 case VT_UINT:
4101 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4102 *(INT*)(pBlk + pItem->byte_offs);
4103 break;
4104 default:
4105 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4109 else {
4110 TRACE_(typelib)("VAR_PERINSTANCE\n");
4111 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4112 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4115 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4116 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4118 if (pItem->flags & 0x80)
4119 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4121 prevName = pVarDesc->Name;
4123 pTI->typeattr.cVars = cVars;
4126 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4127 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4129 SLTG_Function *pFunc;
4130 unsigned short i;
4131 TLBFuncDesc *pFuncDesc;
4133 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4135 pFuncDesc = pTI->funcdescs;
4136 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4137 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4139 int param;
4140 WORD *pType, *pArg;
4142 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4143 case SLTG_FUNCTION_MAGIC:
4144 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4145 break;
4146 case SLTG_DISPATCH_FUNCTION_MAGIC:
4147 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4148 break;
4149 case SLTG_STATIC_FUNCTION_MAGIC:
4150 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4151 break;
4152 default:
4153 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4154 continue;
4156 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4158 pFuncDesc->funcdesc.memid = pFunc->dispid;
4159 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4160 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4161 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4162 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4163 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
4165 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4166 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4168 if(pFunc->retnextopt & 0x80)
4169 pType = &pFunc->rettype;
4170 else
4171 pType = (WORD*)(pBlk + pFunc->rettype);
4173 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4175 pFuncDesc->funcdesc.lprgelemdescParam =
4176 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4177 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4179 pArg = (WORD*)(pBlk + pFunc->arg_off);
4181 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4182 char *paramName = pNameTable + *pArg;
4183 BOOL HaveOffs;
4184 /* If arg type follows then paramName points to the 2nd
4185 letter of the name, else the next WORD is an offset to
4186 the arg type and paramName points to the first letter.
4187 So let's take one char off paramName and see if we're
4188 pointing at an alpha-numeric char. However if *pArg is
4189 0xffff or 0xfffe then the param has no name, the former
4190 meaning that the next WORD is the type, the latter
4191 meaning that the next WORD is an offset to the type. */
4193 HaveOffs = FALSE;
4194 if(*pArg == 0xffff)
4195 paramName = NULL;
4196 else if(*pArg == 0xfffe) {
4197 paramName = NULL;
4198 HaveOffs = TRUE;
4200 else if(paramName[-1] && !isalnum(paramName[-1]))
4201 HaveOffs = TRUE;
4203 pArg++;
4205 if(HaveOffs) { /* the next word is an offset to type */
4206 pType = (WORD*)(pBlk + *pArg);
4207 SLTG_DoElem(pType, pBlk,
4208 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4209 pArg++;
4210 } else {
4211 if(paramName)
4212 paramName--;
4213 pArg = SLTG_DoElem(pArg, pBlk,
4214 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4217 /* Are we an optional param ? */
4218 if(pFuncDesc->funcdesc.cParams - param <=
4219 pFuncDesc->funcdesc.cParamsOpt)
4220 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4222 if(paramName) {
4223 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4224 paramName - pNameTable, pTI->pTypeLib);
4225 } else {
4226 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4230 pTI->typeattr.cFuncs = cFuncs;
4233 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4234 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4235 SLTG_TypeInfoTail *pTITail)
4237 char *pFirstItem;
4238 sltg_ref_lookup_t *ref_lookup = NULL;
4240 if(pTIHeader->href_table != 0xffffffff) {
4241 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4242 pNameTable);
4245 pFirstItem = pBlk;
4247 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4248 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4250 heap_free(ref_lookup);
4254 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4255 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4256 const SLTG_TypeInfoTail *pTITail)
4258 char *pFirstItem;
4259 sltg_ref_lookup_t *ref_lookup = NULL;
4261 if(pTIHeader->href_table != 0xffffffff) {
4262 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4263 pNameTable);
4266 pFirstItem = pBlk;
4268 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4269 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4272 if (pTITail->funcs_off != 0xffff)
4273 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4275 heap_free(ref_lookup);
4277 if (TRACE_ON(typelib))
4278 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4281 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4282 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4283 const SLTG_TypeInfoTail *pTITail)
4285 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4288 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4289 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4290 const SLTG_TypeInfoTail *pTITail)
4292 WORD *pType;
4293 sltg_ref_lookup_t *ref_lookup = NULL;
4295 if (pTITail->simple_alias) {
4296 /* if simple alias, no more processing required */
4297 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4298 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4299 return;
4302 if(pTIHeader->href_table != 0xffffffff) {
4303 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4304 pNameTable);
4307 /* otherwise it is an offset to a type */
4308 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4310 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4311 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4313 heap_free(ref_lookup);
4316 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4317 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4318 const SLTG_TypeInfoTail *pTITail)
4320 sltg_ref_lookup_t *ref_lookup = NULL;
4321 if (pTIHeader->href_table != 0xffffffff)
4322 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4323 pNameTable);
4325 if (pTITail->vars_off != 0xffff)
4326 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4328 if (pTITail->funcs_off != 0xffff)
4329 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4331 if (pTITail->impls_off != 0xffff)
4332 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4334 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4335 * of dispinterface functions including the IDispatch ones, so
4336 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4337 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4339 heap_free(ref_lookup);
4340 if (TRACE_ON(typelib))
4341 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4344 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4345 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4346 const SLTG_TypeInfoTail *pTITail)
4348 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4351 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4352 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4353 const SLTG_TypeInfoTail *pTITail)
4355 sltg_ref_lookup_t *ref_lookup = NULL;
4356 if (pTIHeader->href_table != 0xffffffff)
4357 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4358 pNameTable);
4360 if (pTITail->vars_off != 0xffff)
4361 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4363 if (pTITail->funcs_off != 0xffff)
4364 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4365 heap_free(ref_lookup);
4366 if (TRACE_ON(typelib))
4367 dump_TypeInfo(pTI);
4370 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4371 manageable copy of it into this */
4372 typedef struct {
4373 WORD small_no;
4374 char *index_name;
4375 char *other_name;
4376 WORD res1a;
4377 WORD name_offs;
4378 WORD more_bytes;
4379 char *extra;
4380 WORD res20;
4381 DWORD helpcontext;
4382 WORD res26;
4383 GUID uuid;
4384 } SLTG_InternalOtherTypeInfo;
4386 /****************************************************************************
4387 * ITypeLib2_Constructor_SLTG
4389 * loading a SLTG typelib from an in-memory image
4391 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4393 ITypeLibImpl *pTypeLibImpl;
4394 SLTG_Header *pHeader;
4395 SLTG_BlkEntry *pBlkEntry;
4396 SLTG_Magic *pMagic;
4397 SLTG_Index *pIndex;
4398 SLTG_Pad9 *pPad9;
4399 LPVOID pBlk, pFirstBlk;
4400 SLTG_LibBlk *pLibBlk;
4401 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4402 char *pAfterOTIBlks = NULL;
4403 char *pNameTable, *ptr;
4404 int i;
4405 DWORD len, order;
4406 ITypeInfoImpl **ppTypeInfoImpl;
4408 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4411 pTypeLibImpl = TypeLibImpl_Constructor();
4412 if (!pTypeLibImpl) return NULL;
4414 pHeader = pLib;
4416 TRACE_(typelib)("header:\n");
4417 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4418 pHeader->nrOfFileBlks );
4419 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4420 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4421 pHeader->SLTG_magic);
4422 return NULL;
4425 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4426 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4428 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4429 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4431 /* Next we have a magic block */
4432 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4434 /* Let's see if we're still in sync */
4435 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4436 sizeof(SLTG_COMPOBJ_MAGIC))) {
4437 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4438 return NULL;
4440 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4441 sizeof(SLTG_DIR_MAGIC))) {
4442 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4443 return NULL;
4446 pIndex = (SLTG_Index*)(pMagic+1);
4448 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4450 pFirstBlk = pPad9 + 1;
4452 /* We'll set up a ptr to the main library block, which is the last one. */
4454 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4455 pBlkEntry[order].next != 0;
4456 order = pBlkEntry[order].next - 1) {
4457 pBlk = (char*)pBlk + pBlkEntry[order].len;
4459 pLibBlk = pBlk;
4461 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4463 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4464 interspersed */
4466 len += 0x40;
4468 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4470 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4473 ptr = (char*)pLibBlk + len;
4475 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4476 WORD w, extra;
4477 len = 0;
4479 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4481 w = *(WORD*)(ptr + 2);
4482 if(w != 0xffff) {
4483 len += w;
4484 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4485 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4486 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4488 w = *(WORD*)(ptr + 4 + len);
4489 if(w != 0xffff) {
4490 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4491 len += w;
4492 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4493 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4494 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4496 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4497 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4498 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4499 if(extra) {
4500 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4501 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4502 len += extra;
4504 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4505 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4506 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4507 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4508 len += sizeof(SLTG_OtherTypeInfo);
4509 ptr += len;
4512 pAfterOTIBlks = ptr;
4514 /* Skip this WORD and get the next DWORD */
4515 len = *(DWORD*)(pAfterOTIBlks + 2);
4517 /* Now add this to pLibBLk look at what we're pointing at and
4518 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4519 dust and we should be pointing at the beginning of the name
4520 table */
4522 pNameTable = (char*)pLibBlk + len;
4524 switch(*(WORD*)pNameTable) {
4525 case 0xffff:
4526 break;
4527 case 0x0200:
4528 pNameTable += 0x20;
4529 break;
4530 default:
4531 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4532 break;
4535 pNameTable += 0x216;
4537 pNameTable += 2;
4539 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4541 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4544 /* Hopefully we now have enough ptrs set up to actually read in
4545 some TypeInfos. It's not clear which order to do them in, so
4546 I'll just follow the links along the BlkEntry chain and read
4547 them in the order in which they are in the file */
4549 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4550 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4552 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4553 pBlkEntry[order].next != 0;
4554 order = pBlkEntry[order].next - 1, i++) {
4556 SLTG_TypeInfoHeader *pTIHeader;
4557 SLTG_TypeInfoTail *pTITail;
4558 SLTG_MemberHeader *pMemHeader;
4560 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4561 FIXME_(typelib)("Index strings don't match\n");
4562 heap_free(pOtherTypeInfoBlks);
4563 return NULL;
4566 pTIHeader = pBlk;
4567 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4568 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4569 heap_free(pOtherTypeInfoBlks);
4570 return NULL;
4572 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4573 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4574 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4576 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4577 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4578 (*ppTypeInfoImpl)->index = i;
4579 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4580 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4581 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4582 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4583 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4584 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4585 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4586 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4588 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4589 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4591 if((pTIHeader->typeflags1 & 7) != 2)
4592 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4593 if(pTIHeader->typeflags3 != 2)
4594 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4596 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4597 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4598 typekind_desc[pTIHeader->typekind],
4599 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4600 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4602 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4604 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4606 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4607 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4608 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4610 switch(pTIHeader->typekind) {
4611 case TKIND_ENUM:
4612 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4613 pTIHeader, pTITail);
4614 break;
4616 case TKIND_RECORD:
4617 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4618 pTIHeader, pTITail);
4619 break;
4621 case TKIND_INTERFACE:
4622 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4623 pTIHeader, pTITail);
4624 break;
4626 case TKIND_COCLASS:
4627 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4628 pTIHeader, pTITail);
4629 break;
4631 case TKIND_ALIAS:
4632 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4633 pTIHeader, pTITail);
4634 break;
4636 case TKIND_DISPATCH:
4637 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4638 pTIHeader, pTITail);
4639 break;
4641 case TKIND_MODULE:
4642 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4643 pTIHeader, pTITail);
4644 break;
4646 default:
4647 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4648 break;
4652 /* could get cFuncs, cVars and cImplTypes from here
4653 but we've already set those */
4654 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4655 X(06);
4656 X(16);
4657 X(18);
4658 X(1a);
4659 X(1e);
4660 X(24);
4661 X(26);
4662 X(2a);
4663 X(2c);
4664 X(2e);
4665 X(30);
4666 X(32);
4667 X(34);
4668 #undef X
4669 ++ppTypeInfoImpl;
4670 pBlk = (char*)pBlk + pBlkEntry[order].len;
4673 if(i != pTypeLibImpl->TypeInfoCount) {
4674 FIXME("Somehow processed %d TypeInfos\n", i);
4675 heap_free(pOtherTypeInfoBlks);
4676 return NULL;
4679 heap_free(pOtherTypeInfoBlks);
4680 return &pTypeLibImpl->ITypeLib2_iface;
4683 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4685 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4687 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4689 if(IsEqualIID(riid, &IID_IUnknown) ||
4690 IsEqualIID(riid,&IID_ITypeLib)||
4691 IsEqualIID(riid,&IID_ITypeLib2))
4693 *ppv = &This->ITypeLib2_iface;
4695 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4696 IsEqualIID(riid, &IID_ICreateTypeLib2))
4698 *ppv = &This->ICreateTypeLib2_iface;
4700 else
4702 *ppv = NULL;
4703 TRACE("-- Interface: E_NOINTERFACE\n");
4704 return E_NOINTERFACE;
4707 IUnknown_AddRef((IUnknown*)*ppv);
4708 return S_OK;
4711 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4713 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4714 ULONG ref = InterlockedIncrement(&This->ref);
4716 TRACE("(%p) ref=%u\n", This, ref);
4718 return ref;
4721 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4723 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4724 ULONG ref = InterlockedDecrement(&This->ref);
4726 TRACE("(%p) ref=%u\n",This, ref);
4728 if (!ref)
4730 TLBImpLib *pImpLib, *pImpLibNext;
4731 TLBRefType *ref_type, *ref_type_next;
4732 TLBString *tlbstr, *tlbstr_next;
4733 TLBGuid *tlbguid, *tlbguid_next;
4734 int i;
4736 /* remove cache entry */
4737 if(This->path)
4739 TRACE("removing from cache list\n");
4740 EnterCriticalSection(&cache_section);
4741 if(This->entry.next)
4742 list_remove(&This->entry);
4743 LeaveCriticalSection(&cache_section);
4744 heap_free(This->path);
4746 TRACE(" destroying ITypeLib(%p)\n",This);
4748 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4749 list_remove(&tlbstr->entry);
4750 SysFreeString(tlbstr->str);
4751 heap_free(tlbstr);
4754 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4755 list_remove(&tlbstr->entry);
4756 SysFreeString(tlbstr->str);
4757 heap_free(tlbstr);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4761 list_remove(&tlbguid->entry);
4762 heap_free(tlbguid);
4765 TLB_FreeCustData(&This->custdata_list);
4767 for (i = 0; i < This->ctTypeDesc; i++)
4768 if (This->pTypeDesc[i].vt == VT_CARRAY)
4769 heap_free(This->pTypeDesc[i].u.lpadesc);
4771 heap_free(This->pTypeDesc);
4773 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4775 if (pImpLib->pImpTypeLib)
4776 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4777 SysFreeString(pImpLib->name);
4779 list_remove(&pImpLib->entry);
4780 heap_free(pImpLib);
4783 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4785 list_remove(&ref_type->entry);
4786 heap_free(ref_type);
4789 for (i = 0; i < This->TypeInfoCount; ++i){
4790 heap_free(This->typeinfos[i]->tdescAlias);
4791 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4793 heap_free(This->typeinfos);
4794 heap_free(This);
4795 return 0;
4798 return ref;
4801 /* ITypeLib::GetTypeInfoCount
4803 * Returns the number of type descriptions in the type library
4805 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4807 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4808 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4809 return This->TypeInfoCount;
4812 /* ITypeLib::GetTypeInfo
4814 * retrieves the specified type description in the library.
4816 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4817 ITypeLib2 *iface,
4818 UINT index,
4819 ITypeInfo **ppTInfo)
4821 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4823 TRACE("%p %u %p\n", This, index, ppTInfo);
4825 if(!ppTInfo)
4826 return E_INVALIDARG;
4828 if(index >= This->TypeInfoCount)
4829 return TYPE_E_ELEMENTNOTFOUND;
4831 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4832 ITypeInfo_AddRef(*ppTInfo);
4834 return S_OK;
4838 /* ITypeLibs::GetTypeInfoType
4840 * Retrieves the type of a type description.
4842 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4843 ITypeLib2 *iface,
4844 UINT index,
4845 TYPEKIND *pTKind)
4847 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4849 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4851 if(!pTKind)
4852 return E_INVALIDARG;
4854 if(index >= This->TypeInfoCount)
4855 return TYPE_E_ELEMENTNOTFOUND;
4857 *pTKind = This->typeinfos[index]->typeattr.typekind;
4859 return S_OK;
4862 /* ITypeLib::GetTypeInfoOfGuid
4864 * Retrieves the type description that corresponds to the specified GUID.
4867 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4868 ITypeLib2 *iface,
4869 REFGUID guid,
4870 ITypeInfo **ppTInfo)
4872 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4873 int i;
4875 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4877 for(i = 0; i < This->TypeInfoCount; ++i){
4878 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4879 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4880 ITypeInfo_AddRef(*ppTInfo);
4881 return S_OK;
4885 return TYPE_E_ELEMENTNOTFOUND;
4888 /* ITypeLib::GetLibAttr
4890 * Retrieves the structure that contains the library's attributes.
4893 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4894 ITypeLib2 *iface,
4895 LPTLIBATTR *attr)
4897 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4899 TRACE("(%p, %p)\n", This, attr);
4901 if (!attr) return E_INVALIDARG;
4903 *attr = heap_alloc(sizeof(**attr));
4904 if (!*attr) return E_OUTOFMEMORY;
4906 (*attr)->guid = *TLB_get_guid_null(This->guid);
4907 (*attr)->lcid = This->set_lcid;
4908 (*attr)->syskind = This->syskind;
4909 (*attr)->wMajorVerNum = This->ver_major;
4910 (*attr)->wMinorVerNum = This->ver_minor;
4911 (*attr)->wLibFlags = This->libflags;
4913 return S_OK;
4916 /* ITypeLib::GetTypeComp
4918 * Enables a client compiler to bind to a library's types, variables,
4919 * constants, and global functions.
4922 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4923 ITypeLib2 *iface,
4924 ITypeComp **ppTComp)
4926 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4928 TRACE("(%p)->(%p)\n",This,ppTComp);
4929 *ppTComp = &This->ITypeComp_iface;
4930 ITypeComp_AddRef(*ppTComp);
4932 return S_OK;
4935 /* ITypeLib::GetDocumentation
4937 * Retrieves the library's documentation string, the complete Help file name
4938 * and path, and the context identifier for the library Help topic in the Help
4939 * file.
4941 * On a successful return all non-null BSTR pointers will have been set,
4942 * possibly to NULL.
4944 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4945 ITypeLib2 *iface,
4946 INT index,
4947 BSTR *pBstrName,
4948 BSTR *pBstrDocString,
4949 DWORD *pdwHelpContext,
4950 BSTR *pBstrHelpFile)
4952 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4953 HRESULT result = E_INVALIDARG;
4954 ITypeInfo *pTInfo;
4956 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4957 This, index,
4958 pBstrName, pBstrDocString,
4959 pdwHelpContext, pBstrHelpFile);
4961 if(index<0)
4963 /* documentation for the typelib */
4964 if(pBstrName)
4966 if (This->Name)
4968 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4969 goto memerr1;
4971 else
4972 *pBstrName = NULL;
4974 if(pBstrDocString)
4976 if (This->DocString)
4978 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4979 goto memerr2;
4981 else
4982 *pBstrDocString = NULL;
4984 if(pdwHelpContext)
4986 *pdwHelpContext = This->dwHelpContext;
4988 if(pBstrHelpFile)
4990 if (This->HelpFile)
4992 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
4993 goto memerr3;
4995 else
4996 *pBstrHelpFile = NULL;
4999 result = S_OK;
5001 else
5003 /* for a typeinfo */
5004 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5006 if(SUCCEEDED(result))
5008 result = ITypeInfo_GetDocumentation(pTInfo,
5009 MEMBERID_NIL,
5010 pBstrName,
5011 pBstrDocString,
5012 pdwHelpContext, pBstrHelpFile);
5014 ITypeInfo_Release(pTInfo);
5017 return result;
5018 memerr3:
5019 if (pBstrDocString) SysFreeString (*pBstrDocString);
5020 memerr2:
5021 if (pBstrName) SysFreeString (*pBstrName);
5022 memerr1:
5023 return STG_E_INSUFFICIENTMEMORY;
5026 /* ITypeLib::IsName
5028 * Indicates whether a passed-in string contains the name of a type or member
5029 * described in the library.
5032 static HRESULT WINAPI ITypeLib2_fnIsName(
5033 ITypeLib2 *iface,
5034 LPOLESTR szNameBuf,
5035 ULONG lHashVal,
5036 BOOL *pfName)
5038 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5039 int tic;
5040 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5042 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5043 pfName);
5045 *pfName=TRUE;
5046 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5047 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5048 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5049 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5050 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5051 int pc;
5052 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5053 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5054 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5055 goto ITypeLib2_fnIsName_exit;
5058 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5059 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5060 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5064 *pfName=FALSE;
5066 ITypeLib2_fnIsName_exit:
5067 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5068 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5070 return S_OK;
5073 /* ITypeLib::FindName
5075 * Finds occurrences of a type description in a type library. This may be used
5076 * to quickly verify that a name exists in a type library.
5079 static HRESULT WINAPI ITypeLib2_fnFindName(
5080 ITypeLib2 *iface,
5081 LPOLESTR name,
5082 ULONG hash,
5083 ITypeInfo **ppTInfo,
5084 MEMBERID *memid,
5085 UINT16 *found)
5087 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5088 int tic;
5089 UINT count = 0;
5090 UINT len;
5092 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5094 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5095 return E_INVALIDARG;
5097 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5098 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5099 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5100 TLBVarDesc *var;
5101 UINT fdc;
5103 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5104 memid[count] = MEMBERID_NIL;
5105 goto ITypeLib2_fnFindName_exit;
5108 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5109 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5111 if(!TLB_str_memcmp(name, func->Name, len)) {
5112 memid[count] = func->funcdesc.memid;
5113 goto ITypeLib2_fnFindName_exit;
5117 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5118 if (var) {
5119 memid[count] = var->vardesc.memid;
5120 goto ITypeLib2_fnFindName_exit;
5123 continue;
5124 ITypeLib2_fnFindName_exit:
5125 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5126 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5127 count++;
5129 TRACE("found %d typeinfos\n", count);
5131 *found = count;
5133 return S_OK;
5136 /* ITypeLib::ReleaseTLibAttr
5138 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5141 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5142 ITypeLib2 *iface,
5143 TLIBATTR *pTLibAttr)
5145 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5146 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5147 heap_free(pTLibAttr);
5150 /* ITypeLib2::GetCustData
5152 * gets the custom data
5154 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5155 ITypeLib2 * iface,
5156 REFGUID guid,
5157 VARIANT *pVarVal)
5159 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5160 TLBCustData *pCData;
5162 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5164 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5165 if(!pCData)
5166 return TYPE_E_ELEMENTNOTFOUND;
5168 VariantInit(pVarVal);
5169 VariantCopy(pVarVal, &pCData->data);
5171 return S_OK;
5174 /* ITypeLib2::GetLibStatistics
5176 * Returns statistics about a type library that are required for efficient
5177 * sizing of hash tables.
5180 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5181 ITypeLib2 * iface,
5182 ULONG *pcUniqueNames,
5183 ULONG *pcchUniqueNames)
5185 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5187 FIXME("(%p): stub!\n", This);
5189 if(pcUniqueNames) *pcUniqueNames=1;
5190 if(pcchUniqueNames) *pcchUniqueNames=1;
5191 return S_OK;
5194 /* ITypeLib2::GetDocumentation2
5196 * Retrieves the library's documentation string, the complete Help file name
5197 * and path, the localization context to use, and the context ID for the
5198 * library Help topic in the Help file.
5201 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5202 ITypeLib2 * iface,
5203 INT index,
5204 LCID lcid,
5205 BSTR *pbstrHelpString,
5206 DWORD *pdwHelpStringContext,
5207 BSTR *pbstrHelpStringDll)
5209 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5210 HRESULT result;
5211 ITypeInfo *pTInfo;
5213 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5215 /* the help string should be obtained from the helpstringdll,
5216 * using the _DLLGetDocumentation function, based on the supplied
5217 * lcid. Nice to do sometime...
5219 if(index<0)
5221 /* documentation for the typelib */
5222 if(pbstrHelpString)
5223 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5224 if(pdwHelpStringContext)
5225 *pdwHelpStringContext=This->dwHelpContext;
5226 if(pbstrHelpStringDll)
5227 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5229 result = S_OK;
5231 else
5233 /* for a typeinfo */
5234 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5236 if(SUCCEEDED(result))
5238 ITypeInfo2 * pTInfo2;
5239 result = ITypeInfo_QueryInterface(pTInfo,
5240 &IID_ITypeInfo2,
5241 (LPVOID*) &pTInfo2);
5243 if(SUCCEEDED(result))
5245 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5246 MEMBERID_NIL,
5247 lcid,
5248 pbstrHelpString,
5249 pdwHelpStringContext,
5250 pbstrHelpStringDll);
5252 ITypeInfo2_Release(pTInfo2);
5255 ITypeInfo_Release(pTInfo);
5258 return result;
5261 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5263 TLBCustData *pCData;
5264 unsigned int ct;
5265 CUSTDATAITEM *cdi;
5267 ct = list_count(custdata_list);
5269 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5270 if(!pCustData->prgCustData)
5271 return E_OUTOFMEMORY;
5273 pCustData->cCustData = ct;
5275 cdi = pCustData->prgCustData;
5276 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5277 cdi->guid = *TLB_get_guid_null(pCData->guid);
5278 VariantCopy(&cdi->varValue, &pCData->data);
5279 ++cdi;
5282 return S_OK;
5286 /* ITypeLib2::GetAllCustData
5288 * Gets all custom data items for the library.
5291 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5292 ITypeLib2 * iface,
5293 CUSTDATA *pCustData)
5295 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5296 TRACE("(%p)->(%p)\n", This, pCustData);
5297 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5300 static const ITypeLib2Vtbl tlbvt = {
5301 ITypeLib2_fnQueryInterface,
5302 ITypeLib2_fnAddRef,
5303 ITypeLib2_fnRelease,
5304 ITypeLib2_fnGetTypeInfoCount,
5305 ITypeLib2_fnGetTypeInfo,
5306 ITypeLib2_fnGetTypeInfoType,
5307 ITypeLib2_fnGetTypeInfoOfGuid,
5308 ITypeLib2_fnGetLibAttr,
5309 ITypeLib2_fnGetTypeComp,
5310 ITypeLib2_fnGetDocumentation,
5311 ITypeLib2_fnIsName,
5312 ITypeLib2_fnFindName,
5313 ITypeLib2_fnReleaseTLibAttr,
5315 ITypeLib2_fnGetCustData,
5316 ITypeLib2_fnGetLibStatistics,
5317 ITypeLib2_fnGetDocumentation2,
5318 ITypeLib2_fnGetAllCustData
5322 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5324 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5326 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5329 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5331 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5333 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5336 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5338 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5340 return ITypeLib2_Release(&This->ITypeLib2_iface);
5343 static HRESULT WINAPI ITypeLibComp_fnBind(
5344 ITypeComp * iface,
5345 OLECHAR * szName,
5346 ULONG lHash,
5347 WORD wFlags,
5348 ITypeInfo ** ppTInfo,
5349 DESCKIND * pDescKind,
5350 BINDPTR * pBindPtr)
5352 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5353 BOOL typemismatch = FALSE;
5354 int i;
5356 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5358 *pDescKind = DESCKIND_NONE;
5359 pBindPtr->lptcomp = NULL;
5360 *ppTInfo = NULL;
5362 for(i = 0; i < This->TypeInfoCount; ++i){
5363 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5364 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5366 /* FIXME: check wFlags here? */
5367 /* FIXME: we should use a hash table to look this info up using lHash
5368 * instead of an O(n) search */
5369 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5370 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5372 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5374 *pDescKind = DESCKIND_TYPECOMP;
5375 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5376 ITypeComp_AddRef(pBindPtr->lptcomp);
5377 TRACE("module or enum: %s\n", debugstr_w(szName));
5378 return S_OK;
5382 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5383 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5385 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5386 HRESULT hr;
5388 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5389 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5391 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5392 return S_OK;
5394 else if (hr == TYPE_E_TYPEMISMATCH)
5395 typemismatch = TRUE;
5398 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5399 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5401 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5402 HRESULT hr;
5403 ITypeInfo *subtypeinfo;
5404 BINDPTR subbindptr;
5405 DESCKIND subdesckind;
5407 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5408 &subtypeinfo, &subdesckind, &subbindptr);
5409 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5411 TYPEDESC tdesc_appobject;
5412 const VARDESC vardesc_appobject =
5414 -2, /* memid */
5415 NULL, /* lpstrSchema */
5417 0 /* oInst */
5420 /* ELEMDESC */
5422 /* TYPEDESC */
5424 &tdesc_appobject
5426 VT_PTR
5429 0, /* wVarFlags */
5430 VAR_STATIC /* varkind */
5433 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5434 tdesc_appobject.vt = VT_USERDEFINED;
5436 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5438 /* cleanup things filled in by Bind call so we can put our
5439 * application object data in there instead */
5440 switch (subdesckind)
5442 case DESCKIND_FUNCDESC:
5443 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5444 break;
5445 case DESCKIND_VARDESC:
5446 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5447 break;
5448 default:
5449 break;
5451 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5453 if (pTypeInfo->hreftype == -1)
5454 FIXME("no hreftype for interface %p\n", pTypeInfo);
5456 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5457 if (FAILED(hr))
5458 return hr;
5460 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5461 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5462 ITypeInfo_AddRef(*ppTInfo);
5463 return S_OK;
5465 else if (hr == TYPE_E_TYPEMISMATCH)
5466 typemismatch = TRUE;
5470 if (typemismatch)
5472 TRACE("type mismatch %s\n", debugstr_w(szName));
5473 return TYPE_E_TYPEMISMATCH;
5475 else
5477 TRACE("name not found %s\n", debugstr_w(szName));
5478 return S_OK;
5482 static HRESULT WINAPI ITypeLibComp_fnBindType(
5483 ITypeComp * iface,
5484 OLECHAR * szName,
5485 ULONG lHash,
5486 ITypeInfo ** ppTInfo,
5487 ITypeComp ** ppTComp)
5489 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5490 ITypeInfoImpl *info;
5492 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5494 if(!szName || !ppTInfo || !ppTComp)
5495 return E_INVALIDARG;
5497 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5498 if(!info){
5499 *ppTInfo = NULL;
5500 *ppTComp = NULL;
5501 return S_OK;
5504 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5505 ITypeInfo_AddRef(*ppTInfo);
5506 *ppTComp = &info->ITypeComp_iface;
5507 ITypeComp_AddRef(*ppTComp);
5509 return S_OK;
5512 static const ITypeCompVtbl tlbtcvt =
5515 ITypeLibComp_fnQueryInterface,
5516 ITypeLibComp_fnAddRef,
5517 ITypeLibComp_fnRelease,
5519 ITypeLibComp_fnBind,
5520 ITypeLibComp_fnBindType
5523 /*================== ITypeInfo(2) Methods ===================================*/
5524 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5526 ITypeInfoImpl *pTypeInfoImpl;
5528 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5529 if (pTypeInfoImpl)
5531 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5532 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5533 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5534 pTypeInfoImpl->ref = 0;
5535 pTypeInfoImpl->hreftype = -1;
5536 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5537 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5538 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5539 list_init(pTypeInfoImpl->pcustdata_list);
5541 TRACE("(%p)\n", pTypeInfoImpl);
5542 return pTypeInfoImpl;
5545 /* ITypeInfo::QueryInterface
5547 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5548 ITypeInfo2 *iface,
5549 REFIID riid,
5550 VOID **ppvObject)
5552 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5554 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5556 *ppvObject=NULL;
5557 if(IsEqualIID(riid, &IID_IUnknown) ||
5558 IsEqualIID(riid,&IID_ITypeInfo)||
5559 IsEqualIID(riid,&IID_ITypeInfo2))
5560 *ppvObject = &This->ITypeInfo2_iface;
5561 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5562 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5563 *ppvObject = &This->ICreateTypeInfo2_iface;
5564 else if(IsEqualIID(riid, &IID_ITypeComp))
5565 *ppvObject = &This->ITypeComp_iface;
5567 if(*ppvObject){
5568 IUnknown_AddRef((IUnknown*)*ppvObject);
5569 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5570 return S_OK;
5572 TRACE("-- Interface: E_NOINTERFACE\n");
5573 return E_NOINTERFACE;
5576 /* ITypeInfo::AddRef
5578 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5580 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5581 ULONG ref = InterlockedIncrement(&This->ref);
5583 TRACE("(%p)->ref is %u\n",This, ref);
5585 if (ref == 1 /* incremented from 0 */)
5586 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5588 return ref;
5591 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5593 UINT i;
5595 TRACE("destroying ITypeInfo(%p)\n",This);
5597 for (i = 0; i < This->typeattr.cFuncs; ++i)
5599 int j;
5600 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5601 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5603 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5604 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5605 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5606 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5608 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5609 heap_free(pFInfo->pParamDesc);
5610 TLB_FreeCustData(&pFInfo->custdata_list);
5612 heap_free(This->funcdescs);
5614 for(i = 0; i < This->typeattr.cVars; ++i)
5616 TLBVarDesc *pVInfo = &This->vardescs[i];
5617 if (pVInfo->vardesc_create) {
5618 TLB_FreeVarDesc(pVInfo->vardesc_create);
5619 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5620 VariantClear(pVInfo->vardesc.u.lpvarValue);
5621 heap_free(pVInfo->vardesc.u.lpvarValue);
5623 TLB_FreeCustData(&pVInfo->custdata_list);
5625 heap_free(This->vardescs);
5627 if(This->impltypes){
5628 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5629 TLBImplType *pImpl = &This->impltypes[i];
5630 TLB_FreeCustData(&pImpl->custdata_list);
5632 heap_free(This->impltypes);
5635 TLB_FreeCustData(&This->custdata_list);
5637 heap_free(This);
5640 /* ITypeInfo::Release
5642 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5644 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5645 ULONG ref = InterlockedDecrement(&This->ref);
5647 TRACE("(%p)->(%u)\n",This, ref);
5649 if (!ref)
5651 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5652 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5653 if (not_attached_to_typelib)
5654 heap_free(This);
5655 /* otherwise This will be freed when typelib is freed */
5658 return ref;
5661 /* ITypeInfo::GetTypeAttr
5663 * Retrieves a TYPEATTR structure that contains the attributes of the type
5664 * description.
5667 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5668 LPTYPEATTR *ppTypeAttr)
5670 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5671 SIZE_T size;
5673 TRACE("(%p)\n",This);
5675 size = sizeof(**ppTypeAttr);
5676 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5677 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5679 *ppTypeAttr = heap_alloc(size);
5680 if (!*ppTypeAttr)
5681 return E_OUTOFMEMORY;
5683 **ppTypeAttr = This->typeattr;
5684 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5686 if (This->tdescAlias)
5687 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5689 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5690 /* This should include all the inherited funcs */
5691 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5692 /* This is always the size of IDispatch's vtbl */
5693 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5694 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5696 return S_OK;
5699 /* ITypeInfo::GetTypeComp
5701 * Retrieves the ITypeComp interface for the type description, which enables a
5702 * client compiler to bind to the type description's members.
5705 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5706 ITypeComp * *ppTComp)
5708 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5710 TRACE("(%p)->(%p)\n", This, ppTComp);
5712 *ppTComp = &This->ITypeComp_iface;
5713 ITypeComp_AddRef(*ppTComp);
5714 return S_OK;
5717 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5719 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5720 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5721 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5722 return size;
5725 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5727 *dest = *src;
5728 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5729 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5731 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5732 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5733 *buffer += sizeof(PARAMDESCEX);
5734 *pparamdescex_dest = *pparamdescex_src;
5735 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5736 VariantInit(&pparamdescex_dest->varDefaultValue);
5737 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5738 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5740 else
5741 dest->u.paramdesc.pparamdescex = NULL;
5742 return S_OK;
5745 static HRESULT TLB_SanitizeBSTR(BSTR str)
5747 UINT len = SysStringLen(str), i;
5748 for (i = 0; i < len; ++i)
5749 if (str[i] > 0x7f)
5750 str[i] = '?';
5751 return S_OK;
5754 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5756 if (V_VT(var) == VT_INT)
5757 return VariantChangeType(var, var, 0, VT_I4);
5758 else if (V_VT(var) == VT_UINT)
5759 return VariantChangeType(var, var, 0, VT_UI4);
5760 else if (V_VT(var) == VT_BSTR)
5761 return TLB_SanitizeBSTR(V_BSTR(var));
5763 return S_OK;
5766 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5768 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5769 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5772 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5774 FUNCDESC *dest;
5775 char *buffer;
5776 SIZE_T size = sizeof(*src);
5777 SHORT i;
5778 HRESULT hr;
5780 size += sizeof(*src->lprgscode) * src->cScodes;
5781 size += TLB_SizeElemDesc(&src->elemdescFunc);
5782 for (i = 0; i < src->cParams; i++)
5784 size += sizeof(ELEMDESC);
5785 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5788 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5789 if (!dest) return E_OUTOFMEMORY;
5791 *dest = *src;
5792 if (dispinterface) /* overwrite funckind */
5793 dest->funckind = FUNC_DISPATCH;
5794 buffer = (char *)(dest + 1);
5796 dest->oVft = dest->oVft & 0xFFFC;
5798 if (dest->cScodes) {
5799 dest->lprgscode = (SCODE *)buffer;
5800 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5801 buffer += sizeof(*src->lprgscode) * src->cScodes;
5802 } else
5803 dest->lprgscode = NULL;
5805 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5806 if (FAILED(hr))
5808 SysFreeString((BSTR)dest);
5809 return hr;
5812 if (dest->cParams) {
5813 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5814 buffer += sizeof(ELEMDESC) * src->cParams;
5815 for (i = 0; i < src->cParams; i++)
5817 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5818 if (FAILED(hr))
5819 break;
5821 if (FAILED(hr))
5823 /* undo the above actions */
5824 for (i = i - 1; i >= 0; i--)
5825 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5826 TLB_FreeElemDesc(&dest->elemdescFunc);
5827 SysFreeString((BSTR)dest);
5828 return hr;
5830 } else
5831 dest->lprgelemdescParam = NULL;
5833 /* special treatment for dispinterfaces: this makes functions appear
5834 * to return their [retval] value when it is really returning an
5835 * HRESULT */
5836 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5838 if (dest->cParams &&
5839 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5841 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5842 if (elemdesc->tdesc.vt != VT_PTR)
5844 ERR("elemdesc should have started with VT_PTR instead of:\n");
5845 if (ERR_ON(ole))
5846 dump_ELEMDESC(elemdesc);
5847 return E_UNEXPECTED;
5850 /* copy last parameter to the return value. we are using a flat
5851 * buffer so there is no danger of leaking memory in
5852 * elemdescFunc */
5853 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5855 /* remove the last parameter */
5856 dest->cParams--;
5858 else
5859 /* otherwise this function is made to appear to have no return
5860 * value */
5861 dest->elemdescFunc.tdesc.vt = VT_VOID;
5865 *dest_ptr = dest;
5866 return S_OK;
5869 static void TLB_FreeVarDesc(VARDESC *var_desc)
5871 TLB_FreeElemDesc(&var_desc->elemdescVar);
5872 if (var_desc->varkind == VAR_CONST)
5873 VariantClear(var_desc->u.lpvarValue);
5874 SysFreeString((BSTR)var_desc);
5877 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5879 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5881 if (index >= This->typeattr.cFuncs)
5882 return TYPE_E_ELEMENTNOTFOUND;
5884 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5885 return S_OK;
5888 /* internal function to make the inherited interfaces' methods appear
5889 * part of the interface */
5890 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5891 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5893 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5894 HRESULT hr;
5895 UINT implemented_funcs = 0;
5897 if (funcs)
5898 *funcs = 0;
5899 else
5900 *hrefoffset = DISPATCH_HREF_OFFSET;
5902 if(This->impltypes)
5904 ITypeInfo *pSubTypeInfo;
5905 UINT sub_funcs;
5907 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5908 if (FAILED(hr))
5909 return hr;
5911 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5912 index,
5913 ppFuncDesc,
5914 &sub_funcs, hrefoffset);
5915 implemented_funcs += sub_funcs;
5916 ITypeInfo_Release(pSubTypeInfo);
5917 if (SUCCEEDED(hr))
5918 return hr;
5919 *hrefoffset += DISPATCH_HREF_OFFSET;
5922 if (funcs)
5923 *funcs = implemented_funcs + This->typeattr.cFuncs;
5924 else
5925 *hrefoffset = 0;
5927 if (index < implemented_funcs)
5928 return E_INVALIDARG;
5929 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5930 ppFuncDesc);
5933 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5935 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5936 while (TRUE)
5938 switch (pTypeDesc->vt)
5940 case VT_USERDEFINED:
5941 pTypeDesc->u.hreftype += hrefoffset;
5942 return;
5943 case VT_PTR:
5944 case VT_SAFEARRAY:
5945 pTypeDesc = pTypeDesc->u.lptdesc;
5946 break;
5947 case VT_CARRAY:
5948 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5949 break;
5950 default:
5951 return;
5956 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5958 SHORT i;
5959 for (i = 0; i < pFuncDesc->cParams; i++)
5960 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5961 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5964 /* ITypeInfo::GetFuncDesc
5966 * Retrieves the FUNCDESC structure that contains information about a
5967 * specified function.
5970 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5971 LPFUNCDESC *ppFuncDesc)
5973 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5974 const FUNCDESC *internal_funcdesc;
5975 HRESULT hr;
5976 UINT hrefoffset = 0;
5978 TRACE("(%p) index %d\n", This, index);
5980 if (!ppFuncDesc)
5981 return E_INVALIDARG;
5983 if (This->needs_layout)
5984 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5986 if (This->typeattr.typekind == TKIND_DISPATCH)
5987 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5988 &internal_funcdesc, NULL,
5989 &hrefoffset);
5990 else
5991 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5992 &internal_funcdesc);
5993 if (FAILED(hr))
5995 WARN("description for function %d not found\n", index);
5996 return hr;
5999 hr = TLB_AllocAndInitFuncDesc(
6000 internal_funcdesc,
6001 ppFuncDesc,
6002 This->typeattr.typekind == TKIND_DISPATCH);
6004 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6005 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6007 TRACE("-- 0x%08x\n", hr);
6008 return hr;
6011 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6013 VARDESC *dest;
6014 char *buffer;
6015 SIZE_T size = sizeof(*src);
6016 HRESULT hr;
6018 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6019 if (src->varkind == VAR_CONST)
6020 size += sizeof(VARIANT);
6021 size += TLB_SizeElemDesc(&src->elemdescVar);
6023 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6024 if (!dest) return E_OUTOFMEMORY;
6026 *dest = *src;
6027 buffer = (char *)(dest + 1);
6028 if (src->lpstrSchema)
6030 int len;
6031 dest->lpstrSchema = (LPOLESTR)buffer;
6032 len = strlenW(src->lpstrSchema);
6033 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6034 buffer += (len + 1) * sizeof(WCHAR);
6037 if (src->varkind == VAR_CONST)
6039 HRESULT hr;
6041 dest->u.lpvarValue = (VARIANT *)buffer;
6042 *dest->u.lpvarValue = *src->u.lpvarValue;
6043 buffer += sizeof(VARIANT);
6044 VariantInit(dest->u.lpvarValue);
6045 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6046 if (FAILED(hr))
6048 SysFreeString((BSTR)dest);
6049 return hr;
6052 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6053 if (FAILED(hr))
6055 if (src->varkind == VAR_CONST)
6056 VariantClear(dest->u.lpvarValue);
6057 SysFreeString((BSTR)dest);
6058 return hr;
6060 *dest_ptr = dest;
6061 return S_OK;
6064 /* ITypeInfo::GetVarDesc
6066 * Retrieves a VARDESC structure that describes the specified variable.
6069 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6070 LPVARDESC *ppVarDesc)
6072 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6073 const TLBVarDesc *pVDesc = &This->vardescs[index];
6075 TRACE("(%p) index %d\n", This, index);
6077 if(index >= This->typeattr.cVars)
6078 return TYPE_E_ELEMENTNOTFOUND;
6080 if (This->needs_layout)
6081 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6083 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6086 /* ITypeInfo_GetNames
6088 * Retrieves the variable with the specified member ID (or the name of the
6089 * property or method and its parameters) that correspond to the specified
6090 * function ID.
6092 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6093 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6095 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6096 const TLBFuncDesc *pFDesc;
6097 const TLBVarDesc *pVDesc;
6098 int i;
6099 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6101 if(!rgBstrNames)
6102 return E_INVALIDARG;
6104 *pcNames = 0;
6106 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6107 if(pFDesc)
6109 if(!cMaxNames || !pFDesc->Name)
6110 return S_OK;
6112 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6113 ++(*pcNames);
6115 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6116 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6117 return S_OK;
6118 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6119 ++(*pcNames);
6121 return S_OK;
6124 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6125 if(pVDesc)
6127 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6128 *pcNames=1;
6130 else
6132 if(This->impltypes &&
6133 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6134 /* recursive search */
6135 ITypeInfo *pTInfo;
6136 HRESULT result;
6137 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6138 if(SUCCEEDED(result))
6140 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6141 ITypeInfo_Release(pTInfo);
6142 return result;
6144 WARN("Could not search inherited interface!\n");
6146 else
6148 WARN("no names found\n");
6150 *pcNames=0;
6151 return TYPE_E_ELEMENTNOTFOUND;
6153 return S_OK;
6157 /* ITypeInfo::GetRefTypeOfImplType
6159 * If a type description describes a COM class, it retrieves the type
6160 * description of the implemented interface types. For an interface,
6161 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6162 * if any exist.
6165 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6166 ITypeInfo2 *iface,
6167 UINT index,
6168 HREFTYPE *pRefType)
6170 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6171 HRESULT hr = S_OK;
6173 TRACE("(%p) index %d\n", This, index);
6174 if (TRACE_ON(ole)) dump_TypeInfo(This);
6176 if(index==(UINT)-1)
6178 /* only valid on dual interfaces;
6179 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6182 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6184 *pRefType = -2;
6186 else
6188 hr = TYPE_E_ELEMENTNOTFOUND;
6191 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6193 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6194 *pRefType = This->pTypeLib->dispatch_href;
6196 else
6198 if(index >= This->typeattr.cImplTypes)
6199 hr = TYPE_E_ELEMENTNOTFOUND;
6200 else{
6201 *pRefType = This->impltypes[index].hRef;
6202 if (This->typeattr.typekind == TKIND_INTERFACE)
6203 *pRefType |= 0x2;
6207 if(TRACE_ON(ole))
6209 if(SUCCEEDED(hr))
6210 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6211 else
6212 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6215 return hr;
6218 /* ITypeInfo::GetImplTypeFlags
6220 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6221 * or base interface in a type description.
6223 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6224 UINT index, INT *pImplTypeFlags)
6226 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6228 TRACE("(%p) index %d\n", This, index);
6230 if(!pImplTypeFlags)
6231 return E_INVALIDARG;
6233 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6234 *pImplTypeFlags = 0;
6235 return S_OK;
6238 if(index >= This->typeattr.cImplTypes)
6239 return TYPE_E_ELEMENTNOTFOUND;
6241 *pImplTypeFlags = This->impltypes[index].implflags;
6243 return S_OK;
6246 /* GetIDsOfNames
6247 * Maps between member names and member IDs, and parameter names and
6248 * parameter IDs.
6250 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6251 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6253 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6254 const TLBVarDesc *pVDesc;
6255 HRESULT ret=S_OK;
6256 UINT i, fdc;
6258 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6259 cNames);
6261 /* init out parameters in case of failure */
6262 for (i = 0; i < cNames; i++)
6263 pMemId[i] = MEMBERID_NIL;
6265 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6266 int j;
6267 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6268 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6269 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6270 for(i=1; i < cNames; i++){
6271 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6272 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6273 break;
6274 if( j<pFDesc->funcdesc.cParams)
6275 pMemId[i]=j;
6276 else
6277 ret=DISP_E_UNKNOWNNAME;
6279 TRACE("-- 0x%08x\n", ret);
6280 return ret;
6283 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6284 if(pVDesc){
6285 if(cNames)
6286 *pMemId = pVDesc->vardesc.memid;
6287 return ret;
6289 /* not found, see if it can be found in an inherited interface */
6290 if(This->impltypes) {
6291 /* recursive search */
6292 ITypeInfo *pTInfo;
6293 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6294 if(SUCCEEDED(ret)){
6295 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6296 ITypeInfo_Release(pTInfo);
6297 return ret;
6299 WARN("Could not search inherited interface!\n");
6300 } else
6301 WARN("no names found\n");
6302 return DISP_E_UNKNOWNNAME;
6306 #ifdef __i386__
6308 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6309 __ASM_GLOBAL_FUNC( call_method,
6310 "pushl %ebp\n\t"
6311 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6312 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6313 "movl %esp,%ebp\n\t"
6314 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6315 "pushl %esi\n\t"
6316 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6317 "pushl %edi\n\t"
6318 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6319 "movl 12(%ebp),%edx\n\t"
6320 "movl %esp,%edi\n\t"
6321 "shll $2,%edx\n\t"
6322 "jz 1f\n\t"
6323 "subl %edx,%edi\n\t"
6324 "andl $~15,%edi\n\t"
6325 "movl %edi,%esp\n\t"
6326 "movl 12(%ebp),%ecx\n\t"
6327 "movl 16(%ebp),%esi\n\t"
6328 "cld\n\t"
6329 "rep; movsl\n"
6330 "1:\tcall *8(%ebp)\n\t"
6331 "subl %esp,%edi\n\t"
6332 "movl 20(%ebp),%ecx\n\t"
6333 "movl %edi,(%ecx)\n\t"
6334 "leal -8(%ebp),%esp\n\t"
6335 "popl %edi\n\t"
6336 __ASM_CFI(".cfi_same_value %edi\n\t")
6337 "popl %esi\n\t"
6338 __ASM_CFI(".cfi_same_value %esi\n\t")
6339 "popl %ebp\n\t"
6340 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6341 __ASM_CFI(".cfi_same_value %ebp\n\t")
6342 "ret" )
6344 /* same function but returning floating point */
6345 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
6347 /* ITypeInfo::Invoke
6349 * Invokes a method, or accesses a property of an object, that implements the
6350 * interface described by the type description.
6352 DWORD
6353 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
6354 DWORD res;
6355 int stack_offset;
6357 if (TRACE_ON(ole)) {
6358 int i;
6359 TRACE("Calling %p(",func);
6360 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
6361 if (nrargs > 30) TRACE("...");
6362 TRACE(")\n");
6365 switch (callconv) {
6366 case CC_STDCALL:
6367 case CC_CDECL:
6368 res = call_method( func, nrargs, args, &stack_offset );
6369 break;
6370 default:
6371 FIXME("unsupported calling convention %d\n",callconv);
6372 res = -1;
6373 break;
6375 TRACE("returns %08x\n",res);
6376 return res;
6379 #elif defined(__x86_64__)
6381 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6382 __ASM_GLOBAL_FUNC( call_method,
6383 "pushq %rbp\n\t"
6384 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6385 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6386 "movq %rsp,%rbp\n\t"
6387 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6388 "pushq %rsi\n\t"
6389 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6390 "pushq %rdi\n\t"
6391 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6392 "movq %rcx,%rax\n\t"
6393 "movq $4,%rcx\n\t"
6394 "cmp %rcx,%rdx\n\t"
6395 "cmovgq %rdx,%rcx\n\t"
6396 "leaq 0(,%rcx,8),%rdx\n\t"
6397 "subq %rdx,%rsp\n\t"
6398 "andq $~15,%rsp\n\t"
6399 "movq %rsp,%rdi\n\t"
6400 "movq %r8,%rsi\n\t"
6401 "rep; movsq\n\t"
6402 "movq 0(%rsp),%rcx\n\t"
6403 "movq 8(%rsp),%rdx\n\t"
6404 "movq 16(%rsp),%r8\n\t"
6405 "movq 24(%rsp),%r9\n\t"
6406 "movq 0(%rsp),%xmm0\n\t"
6407 "movq 8(%rsp),%xmm1\n\t"
6408 "movq 16(%rsp),%xmm2\n\t"
6409 "movq 24(%rsp),%xmm3\n\t"
6410 "callq *%rax\n\t"
6411 "leaq -16(%rbp),%rsp\n\t"
6412 "popq %rdi\n\t"
6413 __ASM_CFI(".cfi_same_value %rdi\n\t")
6414 "popq %rsi\n\t"
6415 __ASM_CFI(".cfi_same_value %rsi\n\t")
6416 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6417 "popq %rbp\n\t"
6418 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6419 __ASM_CFI(".cfi_same_value %rbp\n\t")
6420 "ret")
6422 /* same function but returning floating point */
6423 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
6425 #endif /* __x86_64__ */
6427 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6429 HRESULT hr = S_OK;
6430 ITypeInfo *tinfo2 = NULL;
6431 TYPEATTR *tattr = NULL;
6433 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6434 if (hr)
6436 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6437 "hr = 0x%08x\n",
6438 tdesc->u.hreftype, hr);
6439 return hr;
6441 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6442 if (hr)
6444 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6445 ITypeInfo_Release(tinfo2);
6446 return hr;
6449 switch (tattr->typekind)
6451 case TKIND_ENUM:
6452 *vt |= VT_I4;
6453 break;
6455 case TKIND_ALIAS:
6456 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6457 break;
6459 case TKIND_INTERFACE:
6460 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6461 *vt |= VT_DISPATCH;
6462 else
6463 *vt |= VT_UNKNOWN;
6464 break;
6466 case TKIND_DISPATCH:
6467 *vt |= VT_DISPATCH;
6468 break;
6470 case TKIND_COCLASS:
6471 *vt |= VT_DISPATCH;
6472 break;
6474 case TKIND_RECORD:
6475 FIXME("TKIND_RECORD unhandled.\n");
6476 hr = E_NOTIMPL;
6477 break;
6479 case TKIND_UNION:
6480 FIXME("TKIND_UNION unhandled.\n");
6481 hr = E_NOTIMPL;
6482 break;
6484 default:
6485 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6486 hr = E_NOTIMPL;
6487 break;
6489 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6490 ITypeInfo_Release(tinfo2);
6491 return hr;
6494 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6496 HRESULT hr = S_OK;
6498 /* enforce only one level of pointer indirection */
6499 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6501 tdesc = tdesc->u.lptdesc;
6503 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6504 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6505 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6506 if ((tdesc->vt == VT_USERDEFINED) ||
6507 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6509 VARTYPE vt_userdefined = 0;
6510 const TYPEDESC *tdesc_userdefined = tdesc;
6511 if (tdesc->vt == VT_PTR)
6513 vt_userdefined = VT_BYREF;
6514 tdesc_userdefined = tdesc->u.lptdesc;
6516 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6517 if ((hr == S_OK) &&
6518 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6519 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6521 *vt |= vt_userdefined;
6522 return S_OK;
6525 *vt = VT_BYREF;
6528 switch (tdesc->vt)
6530 case VT_HRESULT:
6531 *vt |= VT_ERROR;
6532 break;
6533 case VT_USERDEFINED:
6534 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6535 break;
6536 case VT_VOID:
6537 case VT_CARRAY:
6538 case VT_PTR:
6539 case VT_LPSTR:
6540 case VT_LPWSTR:
6541 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6542 hr = DISP_E_BADVARTYPE;
6543 break;
6544 case VT_SAFEARRAY:
6545 *vt |= VT_ARRAY;
6546 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6547 break;
6548 case VT_INT:
6549 *vt |= VT_I4;
6550 break;
6551 case VT_UINT:
6552 *vt |= VT_UI4;
6553 break;
6554 default:
6555 *vt |= tdesc->vt;
6556 break;
6558 return hr;
6561 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6563 ITypeInfo *tinfo2;
6564 TYPEATTR *tattr;
6565 HRESULT hres;
6567 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6568 if(FAILED(hres))
6569 return hres;
6571 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6572 if(FAILED(hres)) {
6573 ITypeInfo_Release(tinfo2);
6574 return hres;
6577 switch(tattr->typekind) {
6578 case TKIND_ALIAS:
6579 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6580 break;
6582 case TKIND_INTERFACE:
6583 case TKIND_DISPATCH:
6584 *guid = tattr->guid;
6585 break;
6587 default:
6588 ERR("Unexpected typekind %d\n", tattr->typekind);
6589 hres = E_UNEXPECTED;
6592 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6593 ITypeInfo_Release(tinfo2);
6594 return hres;
6597 /***********************************************************************
6598 * DispCallFunc (OLEAUT32.@)
6600 * Invokes a function of the specified calling convention, passing the
6601 * specified arguments and returns the result.
6603 * PARAMS
6604 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6605 * oVft [I] The offset in the vtable. See notes.
6606 * cc [I] Calling convention of the function to call.
6607 * vtReturn [I] The return type of the function.
6608 * cActuals [I] Number of parameters.
6609 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6610 * prgpvarg [I] The arguments to pass.
6611 * pvargResult [O] The return value of the function. Can be NULL.
6613 * RETURNS
6614 * Success: S_OK.
6615 * Failure: HRESULT code.
6617 * NOTES
6618 * The HRESULT return value of this function is not affected by the return
6619 * value of the user supplied function, which is returned in pvargResult.
6621 * If pvInstance is NULL then a non-object function is to be called and oVft
6622 * is the address of the function to call.
6624 * The cc parameter can be one of the following values:
6625 *|CC_FASTCALL
6626 *|CC_CDECL
6627 *|CC_PASCAL
6628 *|CC_STDCALL
6629 *|CC_FPFASTCALL
6630 *|CC_SYSCALL
6631 *|CC_MPWCDECL
6632 *|CC_MPWPASCAL
6635 HRESULT WINAPI
6636 DispCallFunc(
6637 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6638 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6640 #ifdef __i386__
6641 int argspos, stack_offset;
6642 void *func;
6643 UINT i;
6644 DWORD *args;
6646 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6647 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6648 pvargResult, V_VT(pvargResult));
6650 if (cc != CC_STDCALL && cc != CC_CDECL)
6652 FIXME("unsupported calling convention %d\n",cc);
6653 return E_INVALIDARG;
6656 /* maximum size for an argument is sizeof(VARIANT) */
6657 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6659 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6660 argspos = 1;
6661 if (pvInstance)
6663 const FARPROC *vtable = *(FARPROC **)pvInstance;
6664 func = vtable[oVft/sizeof(void *)];
6665 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6667 else func = (void *)oVft;
6669 for (i = 0; i < cActuals; i++)
6671 VARIANT *arg = prgpvarg[i];
6673 switch (prgvt[i])
6675 case VT_EMPTY:
6676 break;
6677 case VT_I8:
6678 case VT_UI8:
6679 case VT_R8:
6680 case VT_DATE:
6681 case VT_CY:
6682 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6683 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6684 break;
6685 case VT_DECIMAL:
6686 case VT_VARIANT:
6687 memcpy( &args[argspos], arg, sizeof(*arg) );
6688 argspos += sizeof(*arg) / sizeof(DWORD);
6689 break;
6690 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6691 args[argspos++] = V_BOOL(arg);
6692 break;
6693 default:
6694 args[argspos++] = V_UI4(arg);
6695 break;
6697 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6700 switch (vtReturn)
6702 case VT_EMPTY:
6703 call_method( func, argspos - 1, args + 1, &stack_offset );
6704 break;
6705 case VT_R4:
6706 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6707 break;
6708 case VT_R8:
6709 case VT_DATE:
6710 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6711 break;
6712 case VT_DECIMAL:
6713 case VT_VARIANT:
6714 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6715 call_method( func, argspos, args, &stack_offset );
6716 break;
6717 case VT_I8:
6718 case VT_UI8:
6719 case VT_CY:
6720 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6721 break;
6722 case VT_HRESULT:
6723 WARN("invalid return type %u\n", vtReturn);
6724 heap_free( args );
6725 return E_INVALIDARG;
6726 default:
6727 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6728 break;
6730 heap_free( args );
6731 if (stack_offset && cc == CC_STDCALL)
6733 WARN( "stack pointer off by %d\n", stack_offset );
6734 return DISP_E_BADCALLEE;
6736 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6737 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6738 return S_OK;
6740 #elif defined(__x86_64__)
6741 int argspos;
6742 UINT i;
6743 DWORD_PTR *args;
6744 void *func;
6746 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6747 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6748 pvargResult, V_VT(pvargResult));
6750 if (cc != CC_STDCALL && cc != CC_CDECL)
6752 FIXME("unsupported calling convention %d\n",cc);
6753 return E_INVALIDARG;
6756 /* maximum size for an argument is sizeof(DWORD_PTR) */
6757 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6759 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6760 argspos = 1;
6761 if (pvInstance)
6763 const FARPROC *vtable = *(FARPROC **)pvInstance;
6764 func = vtable[oVft/sizeof(void *)];
6765 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6767 else func = (void *)oVft;
6769 for (i = 0; i < cActuals; i++)
6771 VARIANT *arg = prgpvarg[i];
6773 switch (prgvt[i])
6775 case VT_DECIMAL:
6776 case VT_VARIANT:
6777 args[argspos++] = (ULONG_PTR)arg;
6778 break;
6779 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6780 args[argspos++] = V_BOOL(arg);
6781 break;
6782 default:
6783 args[argspos++] = V_UI8(arg);
6784 break;
6786 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6789 switch (vtReturn)
6791 case VT_R4:
6792 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6793 break;
6794 case VT_R8:
6795 case VT_DATE:
6796 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6797 break;
6798 case VT_DECIMAL:
6799 case VT_VARIANT:
6800 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6801 call_method( func, argspos, args );
6802 break;
6803 case VT_HRESULT:
6804 WARN("invalid return type %u\n", vtReturn);
6805 heap_free( args );
6806 return E_INVALIDARG;
6807 default:
6808 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6809 break;
6811 heap_free( args );
6812 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6813 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6814 return S_OK;
6816 #else
6817 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6818 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6819 return E_NOTIMPL;
6820 #endif
6823 static inline BOOL func_restricted( const FUNCDESC *desc )
6825 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6828 #define INVBUF_ELEMENT_SIZE \
6829 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6830 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6831 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6832 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6833 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6834 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6835 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6836 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6838 static HRESULT WINAPI ITypeInfo_fnInvoke(
6839 ITypeInfo2 *iface,
6840 VOID *pIUnk,
6841 MEMBERID memid,
6842 UINT16 wFlags,
6843 DISPPARAMS *pDispParams,
6844 VARIANT *pVarResult,
6845 EXCEPINFO *pExcepInfo,
6846 UINT *pArgErr)
6848 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6849 int i;
6850 unsigned int var_index;
6851 TYPEKIND type_kind;
6852 HRESULT hres;
6853 const TLBFuncDesc *pFuncInfo;
6854 UINT fdc;
6856 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6857 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6860 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6861 return DISP_E_MEMBERNOTFOUND;
6863 if (!pDispParams)
6865 ERR("NULL pDispParams not allowed\n");
6866 return E_INVALIDARG;
6869 dump_DispParms(pDispParams);
6871 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6873 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6874 pDispParams->cNamedArgs, pDispParams->cArgs);
6875 return E_INVALIDARG;
6878 /* we do this instead of using GetFuncDesc since it will return a fake
6879 * FUNCDESC for dispinterfaces and we want the real function description */
6880 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
6881 pFuncInfo = &This->funcdescs[fdc];
6882 if ((memid == pFuncInfo->funcdesc.memid) &&
6883 (wFlags & pFuncInfo->funcdesc.invkind) &&
6884 !func_restricted( &pFuncInfo->funcdesc ))
6885 break;
6888 if (fdc < This->typeattr.cFuncs) {
6889 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6891 if (TRACE_ON(ole))
6893 TRACE("invoking:\n");
6894 dump_TLBFuncDescOne(pFuncInfo);
6897 switch (func_desc->funckind) {
6898 case FUNC_PUREVIRTUAL:
6899 case FUNC_VIRTUAL: {
6900 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6901 VARIANT varresult;
6902 VARIANT retval; /* pointer for storing byref retvals in */
6903 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6904 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6905 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6906 UINT cNamedArgs = pDispParams->cNamedArgs;
6907 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6908 UINT vargs_converted=0;
6910 hres = S_OK;
6912 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6914 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6916 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6917 hres = DISP_E_PARAMNOTFOUND;
6918 goto func_fail;
6922 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6924 ERR("functions with the vararg attribute do not support named arguments\n");
6925 hres = DISP_E_NONAMEDARGS;
6926 goto func_fail;
6929 for (i = 0; i < func_desc->cParams; i++)
6931 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6932 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6933 if (FAILED(hres))
6934 goto func_fail;
6937 TRACE("changing args\n");
6938 for (i = 0; i < func_desc->cParams; i++)
6940 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6941 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6942 VARIANTARG *src_arg;
6944 if (wParamFlags & PARAMFLAG_FLCID)
6946 VARIANTARG *arg;
6947 arg = prgpvarg[i] = &rgvarg[i];
6948 V_VT(arg) = VT_I4;
6949 V_I4(arg) = This->pTypeLib->lcid;
6950 continue;
6953 src_arg = NULL;
6955 if (cNamedArgs)
6957 USHORT j;
6958 for (j = 0; j < cNamedArgs; j++)
6959 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6961 src_arg = &pDispParams->rgvarg[j];
6962 break;
6966 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6968 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6969 vargs_converted++;
6972 if (wParamFlags & PARAMFLAG_FRETVAL)
6974 /* under most conditions the caller is not allowed to
6975 * pass in a dispparam arg in the index of what would be
6976 * the retval parameter. however, there is an exception
6977 * where the extra parameter is used in an extra
6978 * IDispatch::Invoke below */
6979 if ((i < pDispParams->cArgs) &&
6980 ((func_desc->cParams != 1) || !pVarResult ||
6981 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6983 hres = DISP_E_BADPARAMCOUNT;
6984 break;
6987 /* note: this check is placed so that if the caller passes
6988 * in a VARIANTARG for the retval we just ignore it, like
6989 * native does */
6990 if (i == func_desc->cParams - 1)
6992 VARIANTARG *arg;
6993 arg = prgpvarg[i] = &rgvarg[i];
6994 memset(arg, 0, sizeof(*arg));
6995 V_VT(arg) = rgvt[i];
6996 memset(&retval, 0, sizeof(retval));
6997 V_BYREF(arg) = &retval;
6999 else
7001 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7002 hres = E_UNEXPECTED;
7003 break;
7006 else if (src_arg)
7008 TRACE("%s\n", debugstr_variant(src_arg));
7010 if(rgvt[i]!=V_VT(src_arg))
7012 if (rgvt[i] == VT_VARIANT)
7013 hres = VariantCopy(&rgvarg[i], src_arg);
7014 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7016 if (rgvt[i] == V_VT(src_arg))
7017 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7018 else
7020 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7021 if (wParamFlags & PARAMFLAG_FIN)
7022 hres = VariantCopy(&missing_arg[i], src_arg);
7023 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7025 V_VT(&rgvarg[i]) = rgvt[i];
7027 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7029 SAFEARRAY *a;
7030 SAFEARRAYBOUND bound;
7031 VARIANT *v;
7032 LONG j;
7033 bound.lLbound = 0;
7034 bound.cElements = pDispParams->cArgs-i;
7035 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7037 ERR("SafeArrayCreate failed\n");
7038 break;
7040 hres = SafeArrayAccessData(a, (LPVOID)&v);
7041 if (hres != S_OK)
7043 ERR("SafeArrayAccessData failed with %x\n", hres);
7044 SafeArrayDestroy(a);
7045 break;
7047 for (j = 0; j < bound.cElements; j++)
7048 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7049 hres = SafeArrayUnaccessData(a);
7050 if (hres != S_OK)
7052 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7053 SafeArrayDestroy(a);
7054 break;
7056 if (rgvt[i] & VT_BYREF)
7057 V_BYREF(&rgvarg[i]) = &a;
7058 else
7059 V_ARRAY(&rgvarg[i]) = a;
7060 V_VT(&rgvarg[i]) = rgvt[i];
7062 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7064 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7065 if (wParamFlags & PARAMFLAG_FIN)
7066 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7067 else
7068 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7069 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7070 V_VT(&rgvarg[i]) = rgvt[i];
7072 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7074 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7075 V_VT(&rgvarg[i]) = rgvt[i];
7077 else
7079 /* FIXME: this doesn't work for VT_BYREF arguments if
7080 * they are not the same type as in the paramdesc */
7081 V_VT(&rgvarg[i]) = V_VT(src_arg);
7082 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7083 V_VT(&rgvarg[i]) = rgvt[i];
7086 if (FAILED(hres))
7088 ERR("failed to convert param %d to %s from %s\n", i,
7089 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7090 break;
7092 prgpvarg[i] = &rgvarg[i];
7094 else
7096 prgpvarg[i] = src_arg;
7099 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7100 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7101 && V_UNKNOWN(prgpvarg[i])) {
7102 IUnknown *userdefined_iface;
7103 GUID guid;
7105 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
7106 if(FAILED(hres))
7107 break;
7109 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7110 if(FAILED(hres)) {
7111 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7112 break;
7115 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7116 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7119 else if (wParamFlags & PARAMFLAG_FOPT)
7121 VARIANTARG *arg;
7122 arg = prgpvarg[i] = &rgvarg[i];
7123 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7125 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7126 if (FAILED(hres))
7127 break;
7129 else
7131 VARIANTARG *missing_arg;
7132 /* if the function wants a pointer to a variant then
7133 * set that up, otherwise just pass the VT_ERROR in
7134 * the argument by value */
7135 if (rgvt[i] & VT_BYREF)
7137 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7138 V_VT(arg) = VT_VARIANT | VT_BYREF;
7139 V_VARIANTREF(arg) = missing_arg;
7141 else
7142 missing_arg = arg;
7143 V_VT(missing_arg) = VT_ERROR;
7144 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7147 else
7149 hres = DISP_E_BADPARAMCOUNT;
7150 break;
7153 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7155 /* VT_VOID is a special case for return types, so it is not
7156 * handled in the general function */
7157 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7158 V_VT(&varresult) = VT_EMPTY;
7159 else
7161 V_VT(&varresult) = 0;
7162 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7163 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7166 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7167 V_VT(&varresult), func_desc->cParams, rgvt,
7168 prgpvarg, &varresult);
7170 vargs_converted = 0;
7172 for (i = 0; i < func_desc->cParams; i++)
7174 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7175 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7177 if (wParamFlags & PARAMFLAG_FLCID)
7178 continue;
7179 else if (wParamFlags & PARAMFLAG_FRETVAL)
7181 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7183 if (pVarResult)
7185 VariantInit(pVarResult);
7186 /* deref return value */
7187 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7190 VARIANT_ClearInd(prgpvarg[i]);
7192 else if (vargs_converted < pDispParams->cArgs)
7194 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7195 if (wParamFlags & PARAMFLAG_FOUT)
7197 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7199 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7201 if (FAILED(hres))
7203 ERR("failed to convert param %d to vt %d\n", i,
7204 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7205 break;
7209 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7210 func_desc->cParamsOpt < 0 &&
7211 i == func_desc->cParams-1)
7213 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7214 LONG j, ubound;
7215 VARIANT *v;
7216 hres = SafeArrayGetUBound(a, 1, &ubound);
7217 if (hres != S_OK)
7219 ERR("SafeArrayGetUBound failed with %x\n", hres);
7220 break;
7222 hres = SafeArrayAccessData(a, (LPVOID)&v);
7223 if (hres != S_OK)
7225 ERR("SafeArrayAccessData failed with %x\n", hres);
7226 break;
7228 for (j = 0; j <= ubound; j++)
7229 VariantClear(&v[j]);
7230 hres = SafeArrayUnaccessData(a);
7231 if (hres != S_OK)
7233 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7234 break;
7237 VariantClear(&rgvarg[i]);
7238 vargs_converted++;
7240 else if (wParamFlags & PARAMFLAG_FOPT)
7242 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7243 VariantClear(&rgvarg[i]);
7246 VariantClear(&missing_arg[i]);
7249 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7251 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7252 hres = DISP_E_EXCEPTION;
7253 if (pExcepInfo)
7255 IErrorInfo *pErrorInfo;
7256 pExcepInfo->scode = V_ERROR(&varresult);
7257 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7259 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7260 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7261 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7262 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7264 IErrorInfo_Release(pErrorInfo);
7268 if (V_VT(&varresult) != VT_ERROR)
7270 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7272 if (pVarResult)
7274 VariantClear(pVarResult);
7275 *pVarResult = varresult;
7277 else
7278 VariantClear(&varresult);
7281 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7282 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7283 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7284 (pDispParams->cArgs != 0))
7286 if (V_VT(pVarResult) == VT_DISPATCH)
7288 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7289 /* Note: not VariantClear; we still need the dispatch
7290 * pointer to be valid */
7291 VariantInit(pVarResult);
7292 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7293 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
7294 pDispParams, pVarResult, pExcepInfo, pArgErr);
7295 IDispatch_Release(pDispatch);
7297 else
7299 VariantClear(pVarResult);
7300 hres = DISP_E_NOTACOLLECTION;
7304 func_fail:
7305 heap_free(buffer);
7306 break;
7308 case FUNC_DISPATCH: {
7309 IDispatch *disp;
7311 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7312 if (SUCCEEDED(hres)) {
7313 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7314 hres = IDispatch_Invoke(
7315 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7316 pVarResult,pExcepInfo,pArgErr
7318 if (FAILED(hres))
7319 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7320 IDispatch_Release(disp);
7321 } else
7322 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7323 break;
7325 default:
7326 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7327 hres = E_FAIL;
7328 break;
7331 TRACE("-- 0x%08x\n", hres);
7332 return hres;
7334 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7335 VARDESC *var_desc;
7337 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7338 if(FAILED(hres)) return hres;
7340 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7341 dump_VARDESC(var_desc);
7342 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7343 return E_NOTIMPL;
7346 /* not found, look for it in inherited interfaces */
7347 ITypeInfo2_GetTypeKind(iface, &type_kind);
7348 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7349 if(This->impltypes) {
7350 /* recursive search */
7351 ITypeInfo *pTInfo;
7352 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7353 if(SUCCEEDED(hres)){
7354 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7355 ITypeInfo_Release(pTInfo);
7356 return hres;
7358 WARN("Could not search inherited interface!\n");
7361 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7362 return DISP_E_MEMBERNOTFOUND;
7365 /* ITypeInfo::GetDocumentation
7367 * Retrieves the documentation string, the complete Help file name and path,
7368 * and the context ID for the Help topic for a specified type description.
7370 * (Can be tested by the Visual Basic Editor in Word for instance.)
7372 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7373 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7374 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7376 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7377 const TLBFuncDesc *pFDesc;
7378 const TLBVarDesc *pVDesc;
7379 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7380 " HelpContext(%p) HelpFile(%p)\n",
7381 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7382 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7383 if(pBstrName)
7384 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7385 if(pBstrDocString)
7386 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7387 if(pdwHelpContext)
7388 *pdwHelpContext=This->dwHelpContext;
7389 if(pBstrHelpFile)
7390 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7391 return S_OK;
7392 }else {/* for a member */
7393 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7394 if(pFDesc){
7395 if(pBstrName)
7396 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7397 if(pBstrDocString)
7398 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7399 if(pdwHelpContext)
7400 *pdwHelpContext=pFDesc->helpcontext;
7401 if(pBstrHelpFile)
7402 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7403 return S_OK;
7405 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7406 if(pVDesc){
7407 if(pBstrName)
7408 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7409 if(pBstrDocString)
7410 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7411 if(pdwHelpContext)
7412 *pdwHelpContext=pVDesc->HelpContext;
7413 if(pBstrHelpFile)
7414 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7415 return S_OK;
7419 if(This->impltypes &&
7420 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7421 /* recursive search */
7422 ITypeInfo *pTInfo;
7423 HRESULT result;
7424 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7425 if(SUCCEEDED(result)) {
7426 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7427 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7428 ITypeInfo_Release(pTInfo);
7429 return result;
7431 WARN("Could not search inherited interface!\n");
7434 WARN("member %d not found\n", memid);
7435 return TYPE_E_ELEMENTNOTFOUND;
7438 /* ITypeInfo::GetDllEntry
7440 * Retrieves a description or specification of an entry point for a function
7441 * in a DLL.
7443 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7444 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7445 WORD *pwOrdinal)
7447 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7448 const TLBFuncDesc *pFDesc;
7450 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7452 if (pBstrDllName) *pBstrDllName = NULL;
7453 if (pBstrName) *pBstrName = NULL;
7454 if (pwOrdinal) *pwOrdinal = 0;
7456 if (This->typeattr.typekind != TKIND_MODULE)
7457 return TYPE_E_BADMODULEKIND;
7459 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7460 if(pFDesc){
7461 dump_TypeInfo(This);
7462 if (TRACE_ON(ole))
7463 dump_TLBFuncDescOne(pFDesc);
7465 if (pBstrDllName)
7466 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7468 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7469 if (pBstrName)
7470 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7471 if (pwOrdinal)
7472 *pwOrdinal = -1;
7473 return S_OK;
7475 if (pBstrName)
7476 *pBstrName = NULL;
7477 if (pwOrdinal)
7478 *pwOrdinal = LOWORD(pFDesc->Entry);
7479 return S_OK;
7481 return TYPE_E_ELEMENTNOTFOUND;
7484 /* internal function to make the inherited interfaces' methods appear
7485 * part of the interface */
7486 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7487 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7489 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7490 HRESULT hr;
7492 TRACE("%p, 0x%x\n", iface, *hRefType);
7494 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7496 ITypeInfo *pSubTypeInfo;
7498 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7499 if (FAILED(hr))
7500 return hr;
7502 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7503 hRefType, ppTInfo);
7504 ITypeInfo_Release(pSubTypeInfo);
7505 if (SUCCEEDED(hr))
7506 return hr;
7508 *hRefType -= DISPATCH_HREF_OFFSET;
7510 if (!(*hRefType & DISPATCH_HREF_MASK))
7511 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7512 else
7513 return E_FAIL;
7516 struct search_res_tlb_params
7518 const GUID *guid;
7519 ITypeLib *pTLib;
7522 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7524 struct search_res_tlb_params *params = (LPVOID)lParam;
7525 static const WCHAR formatW[] = {'\\','%','d',0};
7526 WCHAR szPath[MAX_PATH+1];
7527 ITypeLib *pTLib = NULL;
7528 HRESULT ret;
7529 DWORD len;
7531 if (IS_INTRESOURCE(lpszName) == FALSE)
7532 return TRUE;
7534 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7535 return TRUE;
7537 if (snprintfW(szPath + len, sizeof(szPath)/sizeof(WCHAR) - len, formatW, LOWORD(lpszName)) < 0)
7538 return TRUE;
7540 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7541 if (SUCCEEDED(ret))
7543 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7544 if (IsEqualGUID(params->guid, impl->guid))
7546 params->pTLib = pTLib;
7547 return FALSE; /* stop enumeration */
7549 ITypeLib_Release(pTLib);
7552 return TRUE;
7555 /* ITypeInfo::GetRefTypeInfo
7557 * If a type description references other type descriptions, it retrieves
7558 * the referenced type descriptions.
7560 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7561 ITypeInfo2 *iface,
7562 HREFTYPE hRefType,
7563 ITypeInfo **ppTInfo)
7565 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7566 HRESULT result = E_FAIL;
7568 if(!ppTInfo)
7569 return E_INVALIDARG;
7571 if ((INT)hRefType < 0) {
7572 ITypeInfoImpl *pTypeInfoImpl;
7574 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7575 !(This->typeattr.typekind == TKIND_INTERFACE ||
7576 This->typeattr.typekind == TKIND_DISPATCH))
7577 return TYPE_E_ELEMENTNOTFOUND;
7579 /* when we meet a DUAL typeinfo, we must create the alternate
7580 * version of it.
7582 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7584 *pTypeInfoImpl = *This;
7585 pTypeInfoImpl->ref = 0;
7586 list_init(&pTypeInfoImpl->custdata_list);
7588 if (This->typeattr.typekind == TKIND_INTERFACE)
7589 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7590 else
7591 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7593 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7594 /* the AddRef implicitly adds a reference to the parent typelib, which
7595 * stops the copied data from being destroyed until the new typeinfo's
7596 * refcount goes to zero, but we need to signal to the new instance to
7597 * not free its data structures when it is destroyed */
7598 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7600 ITypeInfo_AddRef(*ppTInfo);
7602 result = S_OK;
7603 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7604 (This->typeattr.typekind == TKIND_DISPATCH))
7606 HREFTYPE href_dispatch = hRefType;
7607 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7608 } else {
7609 TLBRefType *ref_type;
7610 ITypeLib *pTLib = NULL;
7611 UINT i;
7613 if(!(hRefType & 0x1)){
7614 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7616 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7618 result = S_OK;
7619 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7620 ITypeInfo_AddRef(*ppTInfo);
7621 goto end;
7626 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7628 if(ref_type->reference == (hRefType & (~0x3)))
7629 break;
7631 if(&ref_type->entry == &This->pTypeLib->ref_list)
7633 FIXME("Can't find pRefType for ref %x\n", hRefType);
7634 goto end;
7637 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7638 UINT Index;
7639 TRACE("internal reference\n");
7640 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7641 } else {
7642 if(ref_type->pImpTLInfo->pImpTypeLib) {
7643 TRACE("typeinfo in imported typelib that is already loaded\n");
7644 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7645 ITypeLib_AddRef(pTLib);
7646 result = S_OK;
7647 } else {
7648 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7649 struct search_res_tlb_params params;
7650 BSTR libnam;
7652 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7654 /* Search in resource table */
7655 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7656 params.pTLib = NULL;
7657 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7658 pTLib = params.pTLib;
7659 result = S_OK;
7661 if (!pTLib)
7663 /* Search on disk */
7664 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7665 ref_type->pImpTLInfo->wVersionMajor,
7666 ref_type->pImpTLInfo->wVersionMinor,
7667 This->pTypeLib->syskind,
7668 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7669 if (FAILED(result))
7670 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7672 result = LoadTypeLib(libnam, &pTLib);
7673 SysFreeString(libnam);
7676 if(SUCCEEDED(result)) {
7677 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7678 ITypeLib_AddRef(pTLib);
7682 if(SUCCEEDED(result)) {
7683 if(ref_type->index == TLB_REF_USE_GUID)
7684 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7685 else
7686 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7688 if (pTLib != NULL)
7689 ITypeLib_Release(pTLib);
7692 end:
7693 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7694 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7695 return result;
7698 /* ITypeInfo::AddressOfMember
7700 * Retrieves the addresses of static functions or variables, such as those
7701 * defined in a DLL.
7703 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7704 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7706 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7707 HRESULT hr;
7708 BSTR dll, entry;
7709 WORD ordinal;
7710 HMODULE module;
7712 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7714 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7715 if (FAILED(hr))
7716 return hr;
7718 module = LoadLibraryW(dll);
7719 if (!module)
7721 ERR("couldn't load %s\n", debugstr_w(dll));
7722 SysFreeString(dll);
7723 SysFreeString(entry);
7724 return STG_E_FILENOTFOUND;
7726 /* FIXME: store library somewhere where we can free it */
7728 if (entry)
7730 LPSTR entryA;
7731 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7732 entryA = heap_alloc(len);
7733 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7735 *ppv = GetProcAddress(module, entryA);
7736 if (!*ppv)
7737 ERR("function not found %s\n", debugstr_a(entryA));
7739 heap_free(entryA);
7741 else
7743 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7744 if (!*ppv)
7745 ERR("function not found %d\n", ordinal);
7748 SysFreeString(dll);
7749 SysFreeString(entry);
7751 if (!*ppv)
7752 return TYPE_E_DLLFUNCTIONNOTFOUND;
7754 return S_OK;
7757 /* ITypeInfo::CreateInstance
7759 * Creates a new instance of a type that describes a component object class
7760 * (coclass).
7762 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7763 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7765 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7766 HRESULT hr;
7767 TYPEATTR *pTA;
7769 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7771 *ppvObj = NULL;
7773 if(pOuterUnk)
7775 WARN("Not able to aggregate\n");
7776 return CLASS_E_NOAGGREGATION;
7779 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7780 if(FAILED(hr)) return hr;
7782 if(pTA->typekind != TKIND_COCLASS)
7784 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7785 hr = E_INVALIDARG;
7786 goto end;
7789 hr = S_FALSE;
7790 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7792 IUnknown *pUnk;
7793 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7794 TRACE("GetActiveObject rets %08x\n", hr);
7795 if(hr == S_OK)
7797 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7798 IUnknown_Release(pUnk);
7802 if(hr != S_OK)
7803 hr = CoCreateInstance(&pTA->guid, NULL,
7804 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7805 riid, ppvObj);
7807 end:
7808 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7809 return hr;
7812 /* ITypeInfo::GetMops
7814 * Retrieves marshalling information.
7816 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7817 BSTR *pBstrMops)
7819 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7820 FIXME("(%p %d) stub!\n", This, memid);
7821 *pBstrMops = NULL;
7822 return S_OK;
7825 /* ITypeInfo::GetContainingTypeLib
7827 * Retrieves the containing type library and the index of the type description
7828 * within that type library.
7830 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7831 ITypeLib * *ppTLib, UINT *pIndex)
7833 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7835 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7836 if (pIndex) {
7837 *pIndex=This->index;
7838 TRACE("returning pIndex=%d\n", *pIndex);
7841 if (ppTLib) {
7842 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
7843 ITypeLib_AddRef(*ppTLib);
7844 TRACE("returning ppTLib=%p\n", *ppTLib);
7847 return S_OK;
7850 /* ITypeInfo::ReleaseTypeAttr
7852 * Releases a TYPEATTR previously returned by Get
7855 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7856 TYPEATTR* pTypeAttr)
7858 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7859 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7860 heap_free(pTypeAttr);
7863 /* ITypeInfo::ReleaseFuncDesc
7865 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7867 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7868 ITypeInfo2 *iface,
7869 FUNCDESC *pFuncDesc)
7871 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7872 SHORT i;
7874 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7876 for (i = 0; i < pFuncDesc->cParams; i++)
7877 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7878 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7880 SysFreeString((BSTR)pFuncDesc);
7883 /* ITypeInfo::ReleaseVarDesc
7885 * Releases a VARDESC previously returned by GetVarDesc.
7887 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7888 VARDESC *pVarDesc)
7890 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7891 TRACE("(%p)->(%p)\n", This, pVarDesc);
7893 TLB_FreeVarDesc(pVarDesc);
7896 /* ITypeInfo2::GetTypeKind
7898 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7901 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7902 TYPEKIND *pTypeKind)
7904 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7905 *pTypeKind = This->typeattr.typekind;
7906 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7907 return S_OK;
7910 /* ITypeInfo2::GetTypeFlags
7912 * Returns the type flags without any allocations. This returns a DWORD type
7913 * flag, which expands the type flags without growing the TYPEATTR (type
7914 * attribute).
7917 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7919 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7920 *pTypeFlags=This->typeattr.wTypeFlags;
7921 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7922 return S_OK;
7925 /* ITypeInfo2::GetFuncIndexOfMemId
7926 * Binds to a specific member based on a known DISPID, where the member name
7927 * is not known (for example, when binding to a default member).
7930 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7931 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7933 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7934 UINT fdc;
7935 HRESULT result;
7937 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7938 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7939 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7940 break;
7942 if(fdc < This->typeattr.cFuncs) {
7943 *pFuncIndex = fdc;
7944 result = S_OK;
7945 } else
7946 result = TYPE_E_ELEMENTNOTFOUND;
7948 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7949 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7950 return result;
7953 /* TypeInfo2::GetVarIndexOfMemId
7955 * Binds to a specific member based on a known DISPID, where the member name
7956 * is not known (for example, when binding to a default member).
7959 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7960 MEMBERID memid, UINT *pVarIndex)
7962 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7963 TLBVarDesc *pVarInfo;
7965 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7967 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7968 if(!pVarInfo)
7969 return TYPE_E_ELEMENTNOTFOUND;
7971 *pVarIndex = (pVarInfo - This->vardescs);
7973 return S_OK;
7976 /* ITypeInfo2::GetCustData
7978 * Gets the custom data
7980 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7981 ITypeInfo2 * iface,
7982 REFGUID guid,
7983 VARIANT *pVarVal)
7985 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7986 TLBCustData *pCData;
7988 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7990 if(!guid || !pVarVal)
7991 return E_INVALIDARG;
7993 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
7995 VariantInit( pVarVal);
7996 if (pCData)
7997 VariantCopy( pVarVal, &pCData->data);
7998 else
7999 VariantClear( pVarVal );
8000 return S_OK;
8003 /* ITypeInfo2::GetFuncCustData
8005 * Gets the custom data
8007 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8008 ITypeInfo2 * iface,
8009 UINT index,
8010 REFGUID guid,
8011 VARIANT *pVarVal)
8013 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8014 TLBCustData *pCData;
8015 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8017 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8019 if(index >= This->typeattr.cFuncs)
8020 return TYPE_E_ELEMENTNOTFOUND;
8022 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8023 if(!pCData)
8024 return TYPE_E_ELEMENTNOTFOUND;
8026 VariantInit(pVarVal);
8027 VariantCopy(pVarVal, &pCData->data);
8029 return S_OK;
8032 /* ITypeInfo2::GetParamCustData
8034 * Gets the custom data
8036 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8037 ITypeInfo2 * iface,
8038 UINT indexFunc,
8039 UINT indexParam,
8040 REFGUID guid,
8041 VARIANT *pVarVal)
8043 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8044 TLBCustData *pCData;
8045 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8047 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8048 debugstr_guid(guid), pVarVal);
8050 if(indexFunc >= This->typeattr.cFuncs)
8051 return TYPE_E_ELEMENTNOTFOUND;
8053 if(indexParam >= pFDesc->funcdesc.cParams)
8054 return TYPE_E_ELEMENTNOTFOUND;
8056 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8057 if(!pCData)
8058 return TYPE_E_ELEMENTNOTFOUND;
8060 VariantInit(pVarVal);
8061 VariantCopy(pVarVal, &pCData->data);
8063 return S_OK;
8066 /* ITypeInfo2::GetVarCustData
8068 * Gets the custom data
8070 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8071 ITypeInfo2 * iface,
8072 UINT index,
8073 REFGUID guid,
8074 VARIANT *pVarVal)
8076 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8077 TLBCustData *pCData;
8078 TLBVarDesc *pVDesc = &This->vardescs[index];
8080 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8082 if(index >= This->typeattr.cVars)
8083 return TYPE_E_ELEMENTNOTFOUND;
8085 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8086 if(!pCData)
8087 return TYPE_E_ELEMENTNOTFOUND;
8089 VariantInit(pVarVal);
8090 VariantCopy(pVarVal, &pCData->data);
8092 return S_OK;
8095 /* ITypeInfo2::GetImplCustData
8097 * Gets the custom data
8099 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8100 ITypeInfo2 * iface,
8101 UINT index,
8102 REFGUID guid,
8103 VARIANT *pVarVal)
8105 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8106 TLBCustData *pCData;
8107 TLBImplType *pRDesc = &This->impltypes[index];
8109 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8111 if(index >= This->typeattr.cImplTypes)
8112 return TYPE_E_ELEMENTNOTFOUND;
8114 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8115 if(!pCData)
8116 return TYPE_E_ELEMENTNOTFOUND;
8118 VariantInit(pVarVal);
8119 VariantCopy(pVarVal, &pCData->data);
8121 return S_OK;
8124 /* ITypeInfo2::GetDocumentation2
8126 * Retrieves the documentation string, the complete Help file name and path,
8127 * the localization context to use, and the context ID for the library Help
8128 * topic in the Help file.
8131 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8132 ITypeInfo2 * iface,
8133 MEMBERID memid,
8134 LCID lcid,
8135 BSTR *pbstrHelpString,
8136 DWORD *pdwHelpStringContext,
8137 BSTR *pbstrHelpStringDll)
8139 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8140 const TLBFuncDesc *pFDesc;
8141 const TLBVarDesc *pVDesc;
8142 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8143 "HelpStringContext(%p) HelpStringDll(%p)\n",
8144 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8145 pbstrHelpStringDll );
8146 /* the help string should be obtained from the helpstringdll,
8147 * using the _DLLGetDocumentation function, based on the supplied
8148 * lcid. Nice to do sometime...
8150 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8151 if(pbstrHelpString)
8152 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8153 if(pdwHelpStringContext)
8154 *pdwHelpStringContext=This->dwHelpStringContext;
8155 if(pbstrHelpStringDll)
8156 *pbstrHelpStringDll=
8157 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8158 return S_OK;
8159 }else {/* for a member */
8160 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8161 if(pFDesc){
8162 if(pbstrHelpString)
8163 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8164 if(pdwHelpStringContext)
8165 *pdwHelpStringContext=pFDesc->HelpStringContext;
8166 if(pbstrHelpStringDll)
8167 *pbstrHelpStringDll=
8168 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8169 return S_OK;
8171 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8172 if(pVDesc){
8173 if(pbstrHelpString)
8174 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8175 if(pdwHelpStringContext)
8176 *pdwHelpStringContext=pVDesc->HelpStringContext;
8177 if(pbstrHelpStringDll)
8178 *pbstrHelpStringDll=
8179 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8180 return S_OK;
8183 return TYPE_E_ELEMENTNOTFOUND;
8186 /* ITypeInfo2::GetAllCustData
8188 * Gets all custom data items for the Type info.
8191 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8192 ITypeInfo2 * iface,
8193 CUSTDATA *pCustData)
8195 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8197 TRACE("%p %p\n", This, pCustData);
8199 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8202 /* ITypeInfo2::GetAllFuncCustData
8204 * Gets all custom data items for the specified Function
8207 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8208 ITypeInfo2 * iface,
8209 UINT index,
8210 CUSTDATA *pCustData)
8212 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8213 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8215 TRACE("%p %u %p\n", This, index, pCustData);
8217 if(index >= This->typeattr.cFuncs)
8218 return TYPE_E_ELEMENTNOTFOUND;
8220 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8223 /* ITypeInfo2::GetAllParamCustData
8225 * Gets all custom data items for the Functions
8228 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8229 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8231 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8232 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8234 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8236 if(indexFunc >= This->typeattr.cFuncs)
8237 return TYPE_E_ELEMENTNOTFOUND;
8239 if(indexParam >= pFDesc->funcdesc.cParams)
8240 return TYPE_E_ELEMENTNOTFOUND;
8242 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8245 /* ITypeInfo2::GetAllVarCustData
8247 * Gets all custom data items for the specified Variable
8250 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8251 UINT index, CUSTDATA *pCustData)
8253 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8254 TLBVarDesc * pVDesc = &This->vardescs[index];
8256 TRACE("%p %u %p\n", This, index, pCustData);
8258 if(index >= This->typeattr.cVars)
8259 return TYPE_E_ELEMENTNOTFOUND;
8261 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8264 /* ITypeInfo2::GetAllImplCustData
8266 * Gets all custom data items for the specified implementation type
8269 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8270 ITypeInfo2 * iface,
8271 UINT index,
8272 CUSTDATA *pCustData)
8274 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8275 TLBImplType *pRDesc = &This->impltypes[index];
8277 TRACE("%p %u %p\n", This, index, pCustData);
8279 if(index >= This->typeattr.cImplTypes)
8280 return TYPE_E_ELEMENTNOTFOUND;
8282 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8285 static const ITypeInfo2Vtbl tinfvt =
8288 ITypeInfo_fnQueryInterface,
8289 ITypeInfo_fnAddRef,
8290 ITypeInfo_fnRelease,
8292 ITypeInfo_fnGetTypeAttr,
8293 ITypeInfo_fnGetTypeComp,
8294 ITypeInfo_fnGetFuncDesc,
8295 ITypeInfo_fnGetVarDesc,
8296 ITypeInfo_fnGetNames,
8297 ITypeInfo_fnGetRefTypeOfImplType,
8298 ITypeInfo_fnGetImplTypeFlags,
8299 ITypeInfo_fnGetIDsOfNames,
8300 ITypeInfo_fnInvoke,
8301 ITypeInfo_fnGetDocumentation,
8302 ITypeInfo_fnGetDllEntry,
8303 ITypeInfo_fnGetRefTypeInfo,
8304 ITypeInfo_fnAddressOfMember,
8305 ITypeInfo_fnCreateInstance,
8306 ITypeInfo_fnGetMops,
8307 ITypeInfo_fnGetContainingTypeLib,
8308 ITypeInfo_fnReleaseTypeAttr,
8309 ITypeInfo_fnReleaseFuncDesc,
8310 ITypeInfo_fnReleaseVarDesc,
8312 ITypeInfo2_fnGetTypeKind,
8313 ITypeInfo2_fnGetTypeFlags,
8314 ITypeInfo2_fnGetFuncIndexOfMemId,
8315 ITypeInfo2_fnGetVarIndexOfMemId,
8316 ITypeInfo2_fnGetCustData,
8317 ITypeInfo2_fnGetFuncCustData,
8318 ITypeInfo2_fnGetParamCustData,
8319 ITypeInfo2_fnGetVarCustData,
8320 ITypeInfo2_fnGetImplTypeCustData,
8321 ITypeInfo2_fnGetDocumentation2,
8322 ITypeInfo2_fnGetAllCustData,
8323 ITypeInfo2_fnGetAllFuncCustData,
8324 ITypeInfo2_fnGetAllParamCustData,
8325 ITypeInfo2_fnGetAllVarCustData,
8326 ITypeInfo2_fnGetAllImplTypeCustData,
8329 /******************************************************************************
8330 * CreateDispTypeInfo [OLEAUT32.31]
8332 * Build type information for an object so it can be called through an
8333 * IDispatch interface.
8335 * RETURNS
8336 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8337 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8339 * NOTES
8340 * This call allows an objects methods to be accessed through IDispatch, by
8341 * building an ITypeInfo object that IDispatch can use to call through.
8343 HRESULT WINAPI CreateDispTypeInfo(
8344 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8345 LCID lcid, /* [I] Locale Id */
8346 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8348 ITypeInfoImpl *pTIClass, *pTIIface;
8349 ITypeLibImpl *pTypeLibImpl;
8350 unsigned int param, func;
8351 TLBFuncDesc *pFuncDesc;
8352 TLBRefType *ref;
8354 TRACE("\n");
8355 pTypeLibImpl = TypeLibImpl_Constructor();
8356 if (!pTypeLibImpl) return E_FAIL;
8358 pTypeLibImpl->TypeInfoCount = 2;
8359 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8361 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8362 pTIIface->pTypeLib = pTypeLibImpl;
8363 pTIIface->index = 0;
8364 pTIIface->Name = NULL;
8365 pTIIface->dwHelpContext = -1;
8366 pTIIface->guid = NULL;
8367 pTIIface->typeattr.lcid = lcid;
8368 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8369 pTIIface->typeattr.wMajorVerNum = 0;
8370 pTIIface->typeattr.wMinorVerNum = 0;
8371 pTIIface->typeattr.cbAlignment = 2;
8372 pTIIface->typeattr.cbSizeInstance = -1;
8373 pTIIface->typeattr.cbSizeVft = -1;
8374 pTIIface->typeattr.cFuncs = 0;
8375 pTIIface->typeattr.cImplTypes = 0;
8376 pTIIface->typeattr.cVars = 0;
8377 pTIIface->typeattr.wTypeFlags = 0;
8378 pTIIface->hreftype = 0;
8380 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8381 pFuncDesc = pTIIface->funcdescs;
8382 for(func = 0; func < pidata->cMembers; func++) {
8383 METHODDATA *md = pidata->pmethdata + func;
8384 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8385 pFuncDesc->funcdesc.memid = md->dispid;
8386 pFuncDesc->funcdesc.lprgscode = NULL;
8387 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8388 pFuncDesc->funcdesc.invkind = md->wFlags;
8389 pFuncDesc->funcdesc.callconv = md->cc;
8390 pFuncDesc->funcdesc.cParams = md->cArgs;
8391 pFuncDesc->funcdesc.cParamsOpt = 0;
8392 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8393 pFuncDesc->funcdesc.cScodes = 0;
8394 pFuncDesc->funcdesc.wFuncFlags = 0;
8395 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8396 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8397 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8398 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8399 md->cArgs * sizeof(ELEMDESC));
8400 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8401 for(param = 0; param < md->cArgs; param++) {
8402 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8403 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8405 pFuncDesc->helpcontext = 0;
8406 pFuncDesc->HelpStringContext = 0;
8407 pFuncDesc->HelpString = NULL;
8408 pFuncDesc->Entry = NULL;
8409 list_init(&pFuncDesc->custdata_list);
8410 pTIIface->typeattr.cFuncs++;
8411 ++pFuncDesc;
8414 dump_TypeInfo(pTIIface);
8416 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8417 pTIClass->pTypeLib = pTypeLibImpl;
8418 pTIClass->index = 1;
8419 pTIClass->Name = NULL;
8420 pTIClass->dwHelpContext = -1;
8421 pTIClass->guid = NULL;
8422 pTIClass->typeattr.lcid = lcid;
8423 pTIClass->typeattr.typekind = TKIND_COCLASS;
8424 pTIClass->typeattr.wMajorVerNum = 0;
8425 pTIClass->typeattr.wMinorVerNum = 0;
8426 pTIClass->typeattr.cbAlignment = 2;
8427 pTIClass->typeattr.cbSizeInstance = -1;
8428 pTIClass->typeattr.cbSizeVft = -1;
8429 pTIClass->typeattr.cFuncs = 0;
8430 pTIClass->typeattr.cImplTypes = 1;
8431 pTIClass->typeattr.cVars = 0;
8432 pTIClass->typeattr.wTypeFlags = 0;
8433 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8435 pTIClass->impltypes = TLBImplType_Alloc(1);
8437 ref = heap_alloc_zero(sizeof(*ref));
8438 ref->pImpTLInfo = TLB_REF_INTERNAL;
8439 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8441 dump_TypeInfo(pTIClass);
8443 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8445 ITypeInfo_AddRef(*pptinfo);
8446 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8448 return S_OK;
8452 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8454 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8456 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8459 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8461 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8463 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8466 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8468 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8470 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8473 static HRESULT WINAPI ITypeComp_fnBind(
8474 ITypeComp * iface,
8475 OLECHAR * szName,
8476 ULONG lHash,
8477 WORD wFlags,
8478 ITypeInfo ** ppTInfo,
8479 DESCKIND * pDescKind,
8480 BINDPTR * pBindPtr)
8482 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8483 const TLBFuncDesc *pFDesc;
8484 const TLBVarDesc *pVDesc;
8485 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8486 UINT fdc;
8488 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8490 *pDescKind = DESCKIND_NONE;
8491 pBindPtr->lpfuncdesc = NULL;
8492 *ppTInfo = NULL;
8494 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8495 pFDesc = &This->funcdescs[fdc];
8496 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8497 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8498 break;
8499 else
8500 /* name found, but wrong flags */
8501 hr = TYPE_E_TYPEMISMATCH;
8505 if (fdc < This->typeattr.cFuncs)
8507 HRESULT hr = TLB_AllocAndInitFuncDesc(
8508 &pFDesc->funcdesc,
8509 &pBindPtr->lpfuncdesc,
8510 This->typeattr.typekind == TKIND_DISPATCH);
8511 if (FAILED(hr))
8512 return hr;
8513 *pDescKind = DESCKIND_FUNCDESC;
8514 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8515 ITypeInfo_AddRef(*ppTInfo);
8516 return S_OK;
8517 } else {
8518 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8519 if(pVDesc){
8520 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8521 if (FAILED(hr))
8522 return hr;
8523 *pDescKind = DESCKIND_VARDESC;
8524 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8525 ITypeInfo_AddRef(*ppTInfo);
8526 return S_OK;
8530 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8531 /* recursive search */
8532 ITypeInfo *pTInfo;
8533 ITypeComp *pTComp;
8534 HRESULT hr;
8535 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8536 if (SUCCEEDED(hr))
8538 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8539 ITypeInfo_Release(pTInfo);
8541 if (SUCCEEDED(hr))
8543 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8544 ITypeComp_Release(pTComp);
8545 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8546 This->typeattr.typekind == TKIND_DISPATCH)
8548 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8549 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8550 SysFreeString((BSTR)tmp);
8552 return hr;
8554 WARN("Could not search inherited interface!\n");
8556 if (hr == DISP_E_MEMBERNOTFOUND)
8557 hr = S_OK;
8558 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8559 return hr;
8562 static HRESULT WINAPI ITypeComp_fnBindType(
8563 ITypeComp * iface,
8564 OLECHAR * szName,
8565 ULONG lHash,
8566 ITypeInfo ** ppTInfo,
8567 ITypeComp ** ppTComp)
8569 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8571 /* strange behaviour (does nothing) but like the
8572 * original */
8574 if (!ppTInfo || !ppTComp)
8575 return E_POINTER;
8577 *ppTInfo = NULL;
8578 *ppTComp = NULL;
8580 return S_OK;
8583 static const ITypeCompVtbl tcompvt =
8586 ITypeComp_fnQueryInterface,
8587 ITypeComp_fnAddRef,
8588 ITypeComp_fnRelease,
8590 ITypeComp_fnBind,
8591 ITypeComp_fnBindType
8594 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8595 ICreateTypeLib2** ppctlib)
8597 ITypeLibImpl *This;
8598 HRESULT hres;
8600 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8602 if (!szFile) return E_INVALIDARG;
8604 This = TypeLibImpl_Constructor();
8605 if (!This)
8606 return E_OUTOFMEMORY;
8608 This->lcid = GetSystemDefaultLCID();
8609 This->syskind = syskind;
8610 This->ptr_size = get_ptr_size(syskind);
8612 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8613 if (!This->path) {
8614 ITypeLib2_Release(&This->ITypeLib2_iface);
8615 return E_OUTOFMEMORY;
8617 lstrcpyW(This->path, szFile);
8619 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8620 ITypeLib2_Release(&This->ITypeLib2_iface);
8621 return hres;
8624 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8625 REFIID riid, void **object)
8627 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8629 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8632 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8634 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8636 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8639 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8641 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8643 return ITypeLib2_Release(&This->ITypeLib2_iface);
8646 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8647 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8649 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8650 ITypeInfoImpl *info;
8651 HRESULT hres;
8653 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8655 if (!ctinfo || !name)
8656 return E_INVALIDARG;
8658 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8659 if (info)
8660 return TYPE_E_NAMECONFLICT;
8662 if (This->typeinfos)
8663 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8664 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8665 else
8666 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8668 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8670 info->pTypeLib = This;
8671 info->Name = TLB_append_str(&This->name_list, name);
8672 info->index = This->TypeInfoCount;
8673 info->typeattr.typekind = kind;
8674 info->typeattr.cbAlignment = 4;
8676 switch (info->typeattr.typekind) {
8677 case TKIND_ENUM:
8678 case TKIND_INTERFACE:
8679 case TKIND_DISPATCH:
8680 case TKIND_COCLASS:
8681 info->typeattr.cbSizeInstance = This->ptr_size;
8682 break;
8683 case TKIND_RECORD:
8684 case TKIND_UNION:
8685 info->typeattr.cbSizeInstance = 0;
8686 break;
8687 case TKIND_MODULE:
8688 info->typeattr.cbSizeInstance = 2;
8689 break;
8690 case TKIND_ALIAS:
8691 info->typeattr.cbSizeInstance = -0x75;
8692 break;
8693 default:
8694 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8695 info->typeattr.cbSizeInstance = 0xdeadbeef;
8696 break;
8699 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8700 &IID_ICreateTypeInfo, (void **)ctinfo);
8701 if (FAILED(hres)) {
8702 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8703 return hres;
8706 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8708 ++This->TypeInfoCount;
8710 return S_OK;
8713 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8714 LPOLESTR name)
8716 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8718 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8720 if (!name)
8721 return E_INVALIDARG;
8723 This->Name = TLB_append_str(&This->name_list, name);
8725 return S_OK;
8728 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8729 WORD majorVerNum, WORD minorVerNum)
8731 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8733 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8735 This->ver_major = majorVerNum;
8736 This->ver_minor = minorVerNum;
8738 return S_OK;
8741 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8742 REFGUID guid)
8744 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8746 TRACE("%p %s\n", This, debugstr_guid(guid));
8748 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8750 return S_OK;
8753 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8754 LPOLESTR doc)
8756 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8758 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8760 if (!doc)
8761 return E_INVALIDARG;
8763 This->DocString = TLB_append_str(&This->string_list, doc);
8765 return S_OK;
8768 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8769 LPOLESTR helpFileName)
8771 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8773 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
8775 if (!helpFileName)
8776 return E_INVALIDARG;
8778 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
8780 return S_OK;
8783 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
8784 DWORD helpContext)
8786 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8788 TRACE("%p %d\n", This, helpContext);
8790 This->dwHelpContext = helpContext;
8792 return S_OK;
8795 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
8796 LCID lcid)
8798 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8800 TRACE("%p %x\n", This, lcid);
8802 This->set_lcid = lcid;
8804 return S_OK;
8807 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
8808 UINT libFlags)
8810 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8812 TRACE("%p %x\n", This, libFlags);
8814 This->libflags = libFlags;
8816 return S_OK;
8819 typedef struct tagWMSFT_SegContents {
8820 DWORD len;
8821 void *data;
8822 } WMSFT_SegContents;
8824 typedef struct tagWMSFT_TLBFile {
8825 MSFT_Header header;
8826 WMSFT_SegContents typeinfo_seg;
8827 WMSFT_SegContents impfile_seg;
8828 WMSFT_SegContents impinfo_seg;
8829 WMSFT_SegContents ref_seg;
8830 WMSFT_SegContents guidhash_seg;
8831 WMSFT_SegContents guid_seg;
8832 WMSFT_SegContents namehash_seg;
8833 WMSFT_SegContents name_seg;
8834 WMSFT_SegContents string_seg;
8835 WMSFT_SegContents typdesc_seg;
8836 WMSFT_SegContents arraydesc_seg;
8837 WMSFT_SegContents custdata_seg;
8838 WMSFT_SegContents cdguids_seg;
8839 MSFT_SegDir segdir;
8840 WMSFT_SegContents aux_seg;
8841 } WMSFT_TLBFile;
8843 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
8844 WMSFT_TLBFile *file)
8846 TLBString *str;
8847 UINT last_offs;
8848 char *data;
8850 file->string_seg.len = 0;
8851 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8852 int size;
8854 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
8855 if (size == 0)
8856 return E_UNEXPECTED;
8858 size += sizeof(INT16);
8859 if (size % 4)
8860 size = (size + 4) & ~0x3;
8861 if (size < 8)
8862 size = 8;
8864 file->string_seg.len += size;
8866 /* temporarily use str->offset to store the length of the aligned,
8867 * converted string */
8868 str->offset = size;
8871 file->string_seg.data = data = heap_alloc(file->string_seg.len);
8873 last_offs = 0;
8874 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
8875 int size;
8877 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8878 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
8879 if (size == 0) {
8880 heap_free(file->string_seg.data);
8881 return E_UNEXPECTED;
8884 *((INT16*)data) = size;
8886 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
8888 size = str->offset;
8889 data += size;
8890 str->offset = last_offs;
8891 last_offs += size;
8894 return S_OK;
8897 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
8898 WMSFT_TLBFile *file)
8900 TLBString *str;
8901 UINT last_offs;
8902 char *data;
8903 MSFT_NameIntro *last_intro = NULL;
8905 file->header.nametablecount = 0;
8906 file->header.nametablechars = 0;
8908 file->name_seg.len = 0;
8909 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8910 int size;
8912 size = strlenW(str->str);
8913 file->header.nametablechars += size;
8914 file->header.nametablecount++;
8916 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
8917 if (size == 0)
8918 return E_UNEXPECTED;
8920 size += sizeof(MSFT_NameIntro);
8921 if (size % 4)
8922 size = (size + 4) & ~0x3;
8923 if (size < 8)
8924 size = 8;
8926 file->name_seg.len += size;
8928 /* temporarily use str->offset to store the length of the aligned,
8929 * converted string */
8930 str->offset = size;
8933 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
8934 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
8936 last_offs = 0;
8937 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
8938 int size, hash;
8939 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
8941 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
8942 data + sizeof(MSFT_NameIntro),
8943 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
8944 if (size == 0) {
8945 heap_free(file->name_seg.data);
8946 return E_UNEXPECTED;
8948 data[sizeof(MSFT_NameIntro) + size] = '\0';
8950 intro->hreftype = -1; /* TODO? */
8951 intro->namelen = size & 0xFF;
8952 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
8953 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
8954 intro->namelen |= hash << 16;
8955 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
8956 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
8958 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
8959 str->offset - size - sizeof(MSFT_NameIntro));
8961 /* update str->offset to actual value to use in other
8962 * compilation functions that require positions within
8963 * the string table */
8964 last_intro = intro;
8965 size = str->offset;
8966 data += size;
8967 str->offset = last_offs;
8968 last_offs += size;
8971 if(last_intro)
8972 last_intro->hreftype = 0; /* last one is 0? */
8974 return S_OK;
8977 static inline int hash_guid(GUID *guid)
8979 int i, hash = 0;
8981 for (i = 0; i < 8; i ++)
8982 hash ^= ((const short *)guid)[i];
8984 return hash & 0x1f;
8987 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
8989 TLBGuid *guid;
8990 MSFT_GuidEntry *entry;
8991 DWORD offs;
8992 int hash_key, *guidhashtab;
8994 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
8995 file->guid_seg.data = heap_alloc(file->guid_seg.len);
8997 entry = file->guid_seg.data;
8998 offs = 0;
8999 guidhashtab = file->guidhash_seg.data;
9000 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9001 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9002 entry->hreftype = guid->hreftype;
9004 hash_key = hash_guid(&guid->guid);
9005 entry->next_hash = guidhashtab[hash_key];
9006 guidhashtab[hash_key] = offs;
9008 guid->offset = offs;
9009 offs += sizeof(MSFT_GuidEntry);
9010 ++entry;
9013 return S_OK;
9016 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9018 VARIANT v = *value;
9019 VARTYPE arg_type = V_VT(value);
9020 int mask = 0;
9021 HRESULT hres;
9022 DWORD ret = file->custdata_seg.len;
9024 if(arg_type == VT_INT)
9025 arg_type = VT_I4;
9026 if(arg_type == VT_UINT)
9027 arg_type = VT_UI4;
9029 v = *value;
9030 if(V_VT(value) != arg_type) {
9031 hres = VariantChangeType(&v, value, 0, arg_type);
9032 if(FAILED(hres)){
9033 ERR("VariantChangeType failed: %08x\n", hres);
9034 return -1;
9038 /* Check if default value can be stored in-place */
9039 switch(arg_type){
9040 case VT_I4:
9041 case VT_UI4:
9042 mask = 0x3ffffff;
9043 if(V_UI4(&v) > 0x3ffffff)
9044 break;
9045 /* fall through */
9046 case VT_I1:
9047 case VT_UI1:
9048 case VT_BOOL:
9049 if(!mask)
9050 mask = 0xff;
9051 /* fall through */
9052 case VT_I2:
9053 case VT_UI2:
9054 if(!mask)
9055 mask = 0xffff;
9056 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9059 /* have to allocate space in custdata_seg */
9060 switch(arg_type) {
9061 case VT_I4:
9062 case VT_R4:
9063 case VT_UI4:
9064 case VT_INT:
9065 case VT_UINT:
9066 case VT_HRESULT:
9067 case VT_PTR: {
9068 /* Construct the data to be allocated */
9069 int *data;
9071 if(file->custdata_seg.data){
9072 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9073 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9074 file->custdata_seg.len += sizeof(int) * 2;
9075 }else{
9076 file->custdata_seg.len = sizeof(int) * 2;
9077 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9080 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9081 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9083 /* TODO: Check if the encoded data is already present in custdata_seg */
9085 return ret;
9088 case VT_BSTR: {
9089 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9090 char *data;
9092 if(file->custdata_seg.data){
9093 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9094 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9095 file->custdata_seg.len += len;
9096 }else{
9097 file->custdata_seg.len = len;
9098 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9101 *((unsigned short *)data) = V_VT(value);
9102 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9103 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9104 if(V_BSTR(&v)[i] <= 0x7f)
9105 data[i+6] = V_BSTR(&v)[i];
9106 else
9107 data[i+6] = '?';
9109 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9110 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9111 data[i] = 0x57;
9113 /* TODO: Check if the encoded data is already present in custdata_seg */
9115 return ret;
9117 default:
9118 FIXME("Argument type not yet handled\n");
9119 return -1;
9123 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9125 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9127 DWORD offs = file->arraydesc_seg.len;
9128 DWORD *encoded;
9129 USHORT i;
9131 /* TODO: we should check for duplicates, but that's harder because each
9132 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9133 * at the library-level) */
9135 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9136 if(!file->arraydesc_seg.data)
9137 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9138 else
9139 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9140 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9142 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9143 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9144 for(i = 0; i < desc->cDims; ++i){
9145 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9146 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9149 return offs;
9152 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9154 DWORD junk;
9155 INT16 junk2;
9156 DWORD offs = 0;
9157 DWORD encoded[2];
9158 VARTYPE vt, subtype;
9159 char *data;
9161 if(!desc)
9162 return -1;
9164 if(!out_mix)
9165 out_mix = &junk;
9166 if(!out_size)
9167 out_size = &junk2;
9169 vt = desc->vt & VT_TYPEMASK;
9171 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9172 DWORD mix;
9173 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9174 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9175 *out_mix = 0x7FFF;
9176 *out_size += 2 * sizeof(DWORD);
9177 }else if(vt == VT_CARRAY){
9178 encoded[0] = desc->vt | (0x7FFE << 16);
9179 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9180 *out_mix = 0x7FFE;
9181 }else if(vt == VT_USERDEFINED){
9182 encoded[0] = desc->vt | (0x7FFF << 16);
9183 encoded[1] = desc->u.hreftype;
9184 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9185 }else{
9186 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9188 switch(vt){
9189 case VT_INT:
9190 subtype = VT_I4;
9191 break;
9192 case VT_UINT:
9193 subtype = VT_UI4;
9194 break;
9195 case VT_VOID:
9196 subtype = VT_EMPTY;
9197 break;
9198 default:
9199 subtype = vt;
9200 break;
9203 *out_mix = subtype;
9204 return 0x80000000 | (subtype << 16) | desc->vt;
9207 data = file->typdesc_seg.data;
9208 while(offs < file->typdesc_seg.len){
9209 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9210 return offs;
9211 offs += sizeof(encoded);
9214 file->typdesc_seg.len += sizeof(encoded);
9215 if(!file->typdesc_seg.data)
9216 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9217 else
9218 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9220 memcpy(&data[offs], encoded, sizeof(encoded));
9222 return offs;
9225 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9227 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9228 DWORD ret = cdguids_seg->len, offs;
9229 MSFT_CDGuid *cdguid;
9230 TLBCustData *cd;
9232 if(list_empty(custdata_list))
9233 return -1;
9235 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9236 if(!cdguids_seg->data){
9237 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9238 }else {
9239 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9240 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9243 offs = ret + sizeof(MSFT_CDGuid);
9244 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9245 cdguid->GuidOffset = cd->guid->offset;
9246 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9247 cdguid->next = offs;
9248 offs += sizeof(MSFT_CDGuid);
9249 ++cdguid;
9252 --cdguid;
9253 cdguid->next = -1;
9255 return ret;
9258 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9259 WMSFT_TLBFile *file)
9261 WMSFT_SegContents *aux_seg = &file->aux_seg;
9262 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9263 MSFT_VarRecord *varrecord;
9264 MSFT_FuncRecord *funcrecord;
9265 MEMBERID *memid;
9266 DWORD *name, *offsets, offs;
9268 for(i = 0; i < info->typeattr.cFuncs; ++i){
9269 TLBFuncDesc *desc = &info->funcdescs[i];
9271 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9273 /* optional fields */
9274 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9275 if(!list_empty(&desc->custdata_list))
9276 recorded_size += 7 * sizeof(INT);
9277 else if(desc->HelpStringContext != 0)
9278 recorded_size += 6 * sizeof(INT);
9279 /* res9? resA? */
9280 else if(desc->Entry)
9281 recorded_size += 3 * sizeof(INT);
9282 else if(desc->HelpString)
9283 recorded_size += 2 * sizeof(INT);
9284 else if(desc->helpcontext)
9285 recorded_size += sizeof(INT);
9287 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9289 for(j = 0; j < desc->funcdesc.cParams; ++j){
9290 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9291 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9292 break;
9296 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9299 for(i = 0; i < info->typeattr.cVars; ++i){
9300 TLBVarDesc *desc = &info->vardescs[i];
9302 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9304 /* optional fields */
9305 if(desc->HelpStringContext != 0)
9306 recorded_size += 5 * sizeof(INT);
9307 else if(!list_empty(&desc->custdata_list))
9308 recorded_size += 4 * sizeof(INT);
9309 /* res9? */
9310 else if(desc->HelpString)
9311 recorded_size += 2 * sizeof(INT);
9312 else if(desc->HelpContext != 0)
9313 recorded_size += sizeof(INT);
9315 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9318 if(!recorded_size && !extra_size)
9319 return ret;
9321 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9323 aux_seg->len += recorded_size + extra_size;
9325 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9327 if(aux_seg->data)
9328 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9329 else
9330 aux_seg->data = heap_alloc(aux_seg->len);
9332 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9334 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9335 offs = 0;
9337 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9338 for(i = 0; i < info->typeattr.cFuncs; ++i){
9339 TLBFuncDesc *desc = &info->funcdescs[i];
9340 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9342 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9343 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9344 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9345 funcrecord->VtableOffset = desc->funcdesc.oVft;
9347 /* FKCCIC:
9348 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9349 * ^^^funckind
9350 * ^^^ ^invkind
9351 * ^has_cust_data
9352 * ^^^^callconv
9353 * ^has_param_defaults
9354 * ^oEntry_is_intresource
9356 funcrecord->FKCCIC =
9357 desc->funcdesc.funckind |
9358 (desc->funcdesc.invkind << 3) |
9359 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9360 (desc->funcdesc.callconv << 8);
9362 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9363 funcrecord->FKCCIC |= 0x2000;
9365 for(j = 0; j < desc->funcdesc.cParams; ++j){
9366 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9367 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9368 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9371 if(paramdefault_size > 0)
9372 funcrecord->FKCCIC |= 0x1000;
9374 funcrecord->nrargs = desc->funcdesc.cParams;
9375 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9377 /* optional fields */
9378 /* res9? resA? */
9379 if(!list_empty(&desc->custdata_list)){
9380 size += 7 * sizeof(INT);
9381 funcrecord->HelpContext = desc->helpcontext;
9382 if(desc->HelpString)
9383 funcrecord->oHelpString = desc->HelpString->offset;
9384 else
9385 funcrecord->oHelpString = -1;
9386 if(!desc->Entry)
9387 funcrecord->oEntry = -1;
9388 else if(IS_INTRESOURCE(desc->Entry))
9389 funcrecord->oEntry = LOWORD(desc->Entry);
9390 else
9391 funcrecord->oEntry = desc->Entry->offset;
9392 funcrecord->res9 = -1;
9393 funcrecord->resA = -1;
9394 funcrecord->HelpStringContext = desc->HelpStringContext;
9395 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9396 }else if(desc->HelpStringContext != 0){
9397 size += 6 * sizeof(INT);
9398 funcrecord->HelpContext = desc->helpcontext;
9399 if(desc->HelpString)
9400 funcrecord->oHelpString = desc->HelpString->offset;
9401 else
9402 funcrecord->oHelpString = -1;
9403 if(!desc->Entry)
9404 funcrecord->oEntry = -1;
9405 else if(IS_INTRESOURCE(desc->Entry))
9406 funcrecord->oEntry = LOWORD(desc->Entry);
9407 else
9408 funcrecord->oEntry = desc->Entry->offset;
9409 funcrecord->res9 = -1;
9410 funcrecord->resA = -1;
9411 funcrecord->HelpStringContext = desc->HelpStringContext;
9412 }else if(desc->Entry){
9413 size += 3 * sizeof(INT);
9414 funcrecord->HelpContext = desc->helpcontext;
9415 if(desc->HelpString)
9416 funcrecord->oHelpString = desc->HelpString->offset;
9417 else
9418 funcrecord->oHelpString = -1;
9419 if(!desc->Entry)
9420 funcrecord->oEntry = -1;
9421 else if(IS_INTRESOURCE(desc->Entry))
9422 funcrecord->oEntry = LOWORD(desc->Entry);
9423 else
9424 funcrecord->oEntry = desc->Entry->offset;
9425 }else if(desc->HelpString){
9426 size += 2 * sizeof(INT);
9427 funcrecord->HelpContext = desc->helpcontext;
9428 funcrecord->oHelpString = desc->HelpString->offset;
9429 }else if(desc->helpcontext){
9430 size += sizeof(INT);
9431 funcrecord->HelpContext = desc->helpcontext;
9434 paramdefault = (DWORD*)((char *)funcrecord + size);
9435 size += paramdefault_size;
9437 for(j = 0; j < desc->funcdesc.cParams; ++j){
9438 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9440 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9441 if(desc->pParamDesc[j].Name)
9442 info->oName = desc->pParamDesc[j].Name->offset;
9443 else
9444 info->oName = -1;
9445 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9447 if(paramdefault_size){
9448 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9449 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9450 else if(paramdefault_size)
9451 *paramdefault = -1;
9452 ++paramdefault;
9455 size += sizeof(MSFT_ParameterInfo);
9458 funcrecord->Info = size | (i << 16); /* is it just the index? */
9460 *offsets = offs;
9461 offs += size;
9462 ++offsets;
9464 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9467 varrecord = (MSFT_VarRecord*)funcrecord;
9468 for(i = 0; i < info->typeattr.cVars; ++i){
9469 TLBVarDesc *desc = &info->vardescs[i];
9470 DWORD size = 5 * sizeof(INT);
9472 varrecord->vardescsize = sizeof(desc->vardesc);
9473 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9474 varrecord->Flags = desc->vardesc.wVarFlags;
9475 varrecord->VarKind = desc->vardesc.varkind;
9477 if(desc->vardesc.varkind == VAR_CONST){
9478 varrecord->vardescsize += sizeof(VARIANT);
9479 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9480 }else
9481 varrecord->OffsValue = desc->vardesc.u.oInst;
9483 /* res9? */
9484 if(desc->HelpStringContext != 0){
9485 size += 5 * sizeof(INT);
9486 varrecord->HelpContext = desc->HelpContext;
9487 if(desc->HelpString)
9488 varrecord->HelpString = desc->HelpString->offset;
9489 else
9490 varrecord->HelpString = -1;
9491 varrecord->res9 = -1;
9492 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9493 varrecord->HelpStringContext = desc->HelpStringContext;
9494 }else if(!list_empty(&desc->custdata_list)){
9495 size += 4 * sizeof(INT);
9496 varrecord->HelpContext = desc->HelpContext;
9497 if(desc->HelpString)
9498 varrecord->HelpString = desc->HelpString->offset;
9499 else
9500 varrecord->HelpString = -1;
9501 varrecord->res9 = -1;
9502 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9503 }else if(desc->HelpString){
9504 size += 2 * sizeof(INT);
9505 varrecord->HelpContext = desc->HelpContext;
9506 if(desc->HelpString)
9507 varrecord->HelpString = desc->HelpString->offset;
9508 else
9509 varrecord->HelpString = -1;
9510 }else if(desc->HelpContext != 0){
9511 size += sizeof(INT);
9512 varrecord->HelpContext = desc->HelpContext;
9515 varrecord->Info = size | (i << 16);
9517 *offsets = offs;
9518 offs += size;
9519 ++offsets;
9521 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9524 memid = (MEMBERID*)varrecord;
9525 for(i = 0; i < info->typeattr.cFuncs; ++i){
9526 TLBFuncDesc *desc = &info->funcdescs[i];
9527 *memid = desc->funcdesc.memid;
9528 ++memid;
9530 for(i = 0; i < info->typeattr.cVars; ++i){
9531 TLBVarDesc *desc = &info->vardescs[i];
9532 *memid = desc->vardesc.memid;
9533 ++memid;
9536 name = (UINT*)memid;
9537 for(i = 0; i < info->typeattr.cFuncs; ++i){
9538 TLBFuncDesc *desc = &info->funcdescs[i];
9539 if(desc->Name)
9540 *name = desc->Name->offset;
9541 else
9542 *name = -1;
9543 ++name;
9545 for(i = 0; i < info->typeattr.cVars; ++i){
9546 TLBVarDesc *desc = &info->vardescs[i];
9547 if(desc->Name)
9548 *name = desc->Name->offset;
9549 else
9550 *name = -1;
9551 ++name;
9554 return ret;
9557 typedef struct tagWMSFT_RefChunk {
9558 DWORD href;
9559 DWORD res04;
9560 DWORD res08;
9561 DWORD next;
9562 } WMSFT_RefChunk;
9564 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9566 DWORD offs = file->ref_seg.len, i;
9567 WMSFT_RefChunk *chunk;
9569 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9570 if(!file->ref_seg.data)
9571 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9572 else
9573 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9575 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9577 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9578 chunk->href = info->impltypes[i].hRef;
9579 chunk->res04 = info->impltypes[i].implflags;
9580 chunk->res08 = -1;
9581 if(i < info->typeattr.cImplTypes - 1)
9582 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9583 else
9584 chunk->next = -1;
9585 ++chunk;
9588 return offs;
9591 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9593 DWORD size;
9595 size = sizeof(MSFT_TypeInfoBase);
9597 if(data){
9598 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9599 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9600 base->typekind = TKIND_DISPATCH;
9601 else
9602 base->typekind = info->typeattr.typekind;
9603 base->typekind |= index << 16; /* TODO: There are some other flags here */
9604 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9605 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9606 base->res2 = 0;
9607 base->res3 = 0;
9608 base->res4 = 3;
9609 base->res5 = 0;
9610 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9611 base->res7 = 0;
9612 base->res8 = 0;
9613 base->res9 = 0;
9614 base->resA = 0;
9615 if(info->guid)
9616 base->posguid = info->guid->offset;
9617 else
9618 base->posguid = -1;
9619 base->flags = info->typeattr.wTypeFlags;
9620 if(info->Name) {
9621 base->NameOffset = info->Name->offset;
9623 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9624 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9625 }else {
9626 base->NameOffset = -1;
9628 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9629 if(info->DocString)
9630 base->docstringoffs = info->DocString->offset;
9631 else
9632 base->docstringoffs = -1;
9633 base->helpstringcontext = info->dwHelpStringContext;
9634 base->helpcontext = info->dwHelpContext;
9635 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9636 base->cImplTypes = info->typeattr.cImplTypes;
9637 base->cbSizeVft = info->typeattr.cbSizeVft;
9638 base->size = info->typeattr.cbSizeInstance;
9639 if(info->typeattr.typekind == TKIND_COCLASS){
9640 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9641 }else if(info->typeattr.typekind == TKIND_ALIAS){
9642 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9643 }else if(info->typeattr.typekind == TKIND_MODULE){
9644 if(info->DllName)
9645 base->datatype1 = info->DllName->offset;
9646 else
9647 base->datatype1 = -1;
9648 }else{
9649 if(info->typeattr.cImplTypes > 0)
9650 base->datatype1 = info->impltypes[0].hRef;
9651 else
9652 base->datatype1 = -1;
9654 base->datatype2 = index; /* FIXME: i think there's more here */
9655 base->res18 = 0;
9656 base->res19 = -1;
9659 return size;
9662 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9664 UINT i;
9666 file->typeinfo_seg.len = 0;
9667 for(i = 0; i < This->TypeInfoCount; ++i){
9668 ITypeInfoImpl *info = This->typeinfos[i];
9669 *junk = file->typeinfo_seg.len;
9670 ++junk;
9671 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9674 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9675 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9677 file->aux_seg.len = 0;
9678 file->aux_seg.data = NULL;
9680 file->typeinfo_seg.len = 0;
9681 for(i = 0; i < This->TypeInfoCount; ++i){
9682 ITypeInfoImpl *info = This->typeinfos[i];
9683 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9684 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9688 typedef struct tagWMSFT_ImpFile {
9689 INT guid_offs;
9690 LCID lcid;
9691 DWORD version;
9692 } WMSFT_ImpFile;
9694 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9696 TLBImpLib *implib;
9697 WMSFT_ImpFile *impfile;
9698 char *data;
9699 DWORD last_offs = 0;
9701 file->impfile_seg.len = 0;
9702 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9703 int size = 0;
9705 if(implib->name){
9706 WCHAR *path = strrchrW(implib->name, '\\');
9707 if(path)
9708 ++path;
9709 else
9710 path = implib->name;
9711 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9712 if (size == 0)
9713 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9716 size += sizeof(INT16);
9717 if (size % 4)
9718 size = (size + 4) & ~0x3;
9719 if (size < 8)
9720 size = 8;
9722 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9725 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9727 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9728 int strlen = 0, size;
9730 impfile = (WMSFT_ImpFile*)data;
9731 impfile->guid_offs = implib->guid->offset;
9732 impfile->lcid = implib->lcid;
9733 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9735 data += sizeof(WMSFT_ImpFile);
9737 if(implib->name){
9738 WCHAR *path= strrchrW(implib->name, '\\');
9739 if(path)
9740 ++path;
9741 else
9742 path = implib->name;
9743 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9744 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9745 if (strlen == 0)
9746 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9749 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9751 size = strlen + sizeof(INT16);
9752 if (size % 4)
9753 size = (size + 4) & ~0x3;
9754 if (size < 8)
9755 size = 8;
9756 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9758 data += size;
9759 implib->offset = last_offs;
9760 last_offs += size + sizeof(WMSFT_ImpFile);
9764 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9766 MSFT_ImpInfo *info;
9767 TLBRefType *ref_type;
9768 UINT i = 0;
9770 WMSFT_compile_impfile(This, file);
9772 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
9773 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
9775 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
9776 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
9777 if(ref_type->index == TLB_REF_USE_GUID){
9778 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
9779 info->oGuid = ref_type->guid->offset;
9780 }else
9781 info->oGuid = ref_type->index;
9782 info->oImpFile = ref_type->pImpTLInfo->offset;
9783 ++i;
9784 ++info;
9788 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9790 file->guidhash_seg.len = 0x80;
9791 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
9792 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
9795 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
9797 file->namehash_seg.len = 0x200;
9798 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
9799 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
9802 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
9804 if(contents && contents->len){
9805 segdir->offset = *running_offset;
9806 segdir->length = contents->len;
9807 *running_offset += segdir->length;
9808 }else{
9809 segdir->offset = -1;
9810 segdir->length = 0;
9813 /* TODO: do these ever change? */
9814 segdir->res08 = -1;
9815 segdir->res0c = 0xf;
9818 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
9820 DWORD written;
9821 if(segment)
9822 WriteFile(outfile, segment->data, segment->len, &written, NULL);
9825 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
9826 DWORD file_len)
9828 DWORD i;
9829 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
9831 for(i = 0; i < This->TypeInfoCount; ++i){
9832 base->memoffset += file_len;
9833 ++base;
9836 return S_OK;
9839 static void WMSFT_free_file(WMSFT_TLBFile *file)
9841 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
9842 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
9843 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
9844 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
9845 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
9846 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
9847 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
9848 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
9849 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
9850 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
9851 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
9852 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
9853 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
9854 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
9857 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
9859 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9860 WMSFT_TLBFile file;
9861 DWORD written, junk_size, junk_offs, running_offset;
9862 BOOL br;
9863 HANDLE outfile;
9864 HRESULT hres;
9865 DWORD *junk;
9866 UINT i;
9868 TRACE("%p\n", This);
9870 for(i = 0; i < This->TypeInfoCount; ++i)
9871 if(This->typeinfos[i]->needs_layout)
9872 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
9874 memset(&file, 0, sizeof(file));
9876 file.header.magic1 = 0x5446534D;
9877 file.header.magic2 = 0x00010002;
9878 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
9879 file.header.lcid2 = This->set_lcid;
9880 file.header.varflags = 0x40 | This->syskind;
9881 if (This->HelpFile)
9882 file.header.varflags |= 0x10;
9883 if (This->HelpStringDll)
9884 file.header.varflags |= HELPDLLFLAG;
9885 file.header.version = (This->ver_minor << 16) | This->ver_major;
9886 file.header.flags = This->libflags;
9887 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
9888 file.header.helpcontext = This->dwHelpContext;
9889 file.header.res44 = 0x20;
9890 file.header.res48 = 0x80;
9891 file.header.dispatchpos = This->dispatch_href;
9893 WMSFT_compile_namehash(This, &file);
9894 /* do name and string compilation to get offsets for other compilations */
9895 hres = WMSFT_compile_names(This, &file);
9896 if (FAILED(hres)){
9897 WMSFT_free_file(&file);
9898 return hres;
9901 hres = WMSFT_compile_strings(This, &file);
9902 if (FAILED(hres)){
9903 WMSFT_free_file(&file);
9904 return hres;
9907 WMSFT_compile_guidhash(This, &file);
9908 hres = WMSFT_compile_guids(This, &file);
9909 if (FAILED(hres)){
9910 WMSFT_free_file(&file);
9911 return hres;
9914 if(This->HelpFile)
9915 file.header.helpfile = This->HelpFile->offset;
9916 else
9917 file.header.helpfile = -1;
9919 if(This->DocString)
9920 file.header.helpstring = This->DocString->offset;
9921 else
9922 file.header.helpstring = -1;
9924 /* do some more segment compilation */
9925 file.header.nimpinfos = list_count(&This->ref_list);
9926 file.header.nrtypeinfos = This->TypeInfoCount;
9928 if(This->Name)
9929 file.header.NameOffset = This->Name->offset;
9930 else
9931 file.header.NameOffset = -1;
9933 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
9935 if(This->guid)
9936 file.header.posguid = This->guid->offset;
9937 else
9938 file.header.posguid = -1;
9940 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
9941 if(file.header.varflags & HELPDLLFLAG)
9942 junk_size += sizeof(DWORD);
9943 if(junk_size){
9944 junk = heap_alloc_zero(junk_size);
9945 if(file.header.varflags & HELPDLLFLAG){
9946 *junk = This->HelpStringDll->offset;
9947 junk_offs = 1;
9948 }else
9949 junk_offs = 0;
9950 }else{
9951 junk = NULL;
9952 junk_offs = 0;
9955 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
9956 WMSFT_compile_impinfo(This, &file);
9958 running_offset = 0;
9960 TRACE("header at: 0x%x\n", running_offset);
9961 running_offset += sizeof(file.header);
9963 TRACE("junk at: 0x%x\n", running_offset);
9964 running_offset += junk_size;
9966 TRACE("segdir at: 0x%x\n", running_offset);
9967 running_offset += sizeof(file.segdir);
9969 TRACE("typeinfo at: 0x%x\n", running_offset);
9970 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
9972 TRACE("guidhashtab at: 0x%x\n", running_offset);
9973 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
9975 TRACE("guidtab at: 0x%x\n", running_offset);
9976 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
9978 TRACE("reftab at: 0x%x\n", running_offset);
9979 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
9981 TRACE("impinfo at: 0x%x\n", running_offset);
9982 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
9984 TRACE("impfiles at: 0x%x\n", running_offset);
9985 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
9987 TRACE("namehashtab at: 0x%x\n", running_offset);
9988 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
9990 TRACE("nametab at: 0x%x\n", running_offset);
9991 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
9993 TRACE("stringtab at: 0x%x\n", running_offset);
9994 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
9996 TRACE("typdesc at: 0x%x\n", running_offset);
9997 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
9999 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10000 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10002 TRACE("custdata at: 0x%x\n", running_offset);
10003 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10005 TRACE("cdguids at: 0x%x\n", running_offset);
10006 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10008 TRACE("res0e at: 0x%x\n", running_offset);
10009 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10011 TRACE("res0f at: 0x%x\n", running_offset);
10012 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10014 TRACE("aux_seg at: 0x%x\n", running_offset);
10016 WMSFT_fixup_typeinfos(This, &file, running_offset);
10018 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10019 FILE_ATTRIBUTE_NORMAL, 0);
10020 if (outfile == INVALID_HANDLE_VALUE){
10021 WMSFT_free_file(&file);
10022 heap_free(junk);
10023 return TYPE_E_IOERROR;
10026 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10027 if (!br) {
10028 WMSFT_free_file(&file);
10029 CloseHandle(outfile);
10030 heap_free(junk);
10031 return TYPE_E_IOERROR;
10034 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10035 heap_free(junk);
10036 if (!br) {
10037 WMSFT_free_file(&file);
10038 CloseHandle(outfile);
10039 return TYPE_E_IOERROR;
10042 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10043 if (!br) {
10044 WMSFT_free_file(&file);
10045 CloseHandle(outfile);
10046 return TYPE_E_IOERROR;
10049 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10050 WMSFT_write_segment(outfile, &file.guidhash_seg);
10051 WMSFT_write_segment(outfile, &file.guid_seg);
10052 WMSFT_write_segment(outfile, &file.ref_seg);
10053 WMSFT_write_segment(outfile, &file.impinfo_seg);
10054 WMSFT_write_segment(outfile, &file.impfile_seg);
10055 WMSFT_write_segment(outfile, &file.namehash_seg);
10056 WMSFT_write_segment(outfile, &file.name_seg);
10057 WMSFT_write_segment(outfile, &file.string_seg);
10058 WMSFT_write_segment(outfile, &file.typdesc_seg);
10059 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10060 WMSFT_write_segment(outfile, &file.custdata_seg);
10061 WMSFT_write_segment(outfile, &file.cdguids_seg);
10062 WMSFT_write_segment(outfile, &file.aux_seg);
10064 WMSFT_free_file(&file);
10066 CloseHandle(outfile);
10068 return S_OK;
10071 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10072 LPOLESTR name)
10074 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10075 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10076 return E_NOTIMPL;
10079 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10080 REFGUID guid, VARIANT *varVal)
10082 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10083 TLBGuid *tlbguid;
10085 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10087 if (!guid || !varVal)
10088 return E_INVALIDARG;
10090 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10092 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10095 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10096 ULONG helpStringContext)
10098 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10099 FIXME("%p %u - stub\n", This, helpStringContext);
10100 return E_NOTIMPL;
10103 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10104 LPOLESTR filename)
10106 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10107 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10109 if (!filename)
10110 return E_INVALIDARG;
10112 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10114 return S_OK;
10117 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10118 ICreateTypeLib2_fnQueryInterface,
10119 ICreateTypeLib2_fnAddRef,
10120 ICreateTypeLib2_fnRelease,
10121 ICreateTypeLib2_fnCreateTypeInfo,
10122 ICreateTypeLib2_fnSetName,
10123 ICreateTypeLib2_fnSetVersion,
10124 ICreateTypeLib2_fnSetGuid,
10125 ICreateTypeLib2_fnSetDocString,
10126 ICreateTypeLib2_fnSetHelpFileName,
10127 ICreateTypeLib2_fnSetHelpContext,
10128 ICreateTypeLib2_fnSetLcid,
10129 ICreateTypeLib2_fnSetLibFlags,
10130 ICreateTypeLib2_fnSaveAllChanges,
10131 ICreateTypeLib2_fnDeleteTypeInfo,
10132 ICreateTypeLib2_fnSetCustData,
10133 ICreateTypeLib2_fnSetHelpStringContext,
10134 ICreateTypeLib2_fnSetHelpStringDll
10137 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10138 REFIID riid, void **object)
10140 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10142 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10145 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10147 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10149 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10152 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10154 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10156 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10159 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10160 REFGUID guid)
10162 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10164 TRACE("%p %s\n", This, debugstr_guid(guid));
10166 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10168 return S_OK;
10171 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10172 UINT typeFlags)
10174 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10175 WORD old_flags;
10176 HRESULT hres;
10178 TRACE("%p %x\n", This, typeFlags);
10180 if (typeFlags & TYPEFLAG_FDUAL) {
10181 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10182 ITypeLib *stdole;
10183 ITypeInfo *dispatch;
10184 HREFTYPE hreftype;
10185 HRESULT hres;
10187 hres = LoadTypeLib(stdole2tlb, &stdole);
10188 if(FAILED(hres))
10189 return hres;
10191 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10192 ITypeLib_Release(stdole);
10193 if(FAILED(hres))
10194 return hres;
10196 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10197 ITypeInfo_Release(dispatch);
10198 if(FAILED(hres))
10199 return hres;
10202 old_flags = This->typeattr.wTypeFlags;
10203 This->typeattr.wTypeFlags = typeFlags;
10205 hres = ICreateTypeInfo2_LayOut(iface);
10206 if (FAILED(hres)) {
10207 This->typeattr.wTypeFlags = old_flags;
10208 return hres;
10211 return S_OK;
10214 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10215 LPOLESTR doc)
10217 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10219 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10221 if (!doc)
10222 return E_INVALIDARG;
10224 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10226 return S_OK;
10229 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10230 DWORD helpContext)
10232 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10234 TRACE("%p %d\n", This, helpContext);
10236 This->dwHelpContext = helpContext;
10238 return S_OK;
10241 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10242 WORD majorVerNum, WORD minorVerNum)
10244 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10246 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10248 This->typeattr.wMajorVerNum = majorVerNum;
10249 This->typeattr.wMinorVerNum = minorVerNum;
10251 return S_OK;
10254 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10255 ITypeInfo *typeInfo, HREFTYPE *refType)
10257 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10258 UINT index;
10259 ITypeLib *container;
10260 TLBRefType *ref_type;
10261 TLBImpLib *implib;
10262 TYPEATTR *typeattr;
10263 TLIBATTR *libattr;
10264 HRESULT hres;
10266 TRACE("%p %p %p\n", This, typeInfo, refType);
10268 if (!typeInfo || !refType)
10269 return E_INVALIDARG;
10271 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10272 if (FAILED(hres))
10273 return hres;
10275 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10276 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10278 ITypeLib_Release(container);
10280 *refType = target->hreftype;
10282 return S_OK;
10285 hres = ITypeLib_GetLibAttr(container, &libattr);
10286 if (FAILED(hres)) {
10287 ITypeLib_Release(container);
10288 return hres;
10291 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10292 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10293 implib->lcid == libattr->lcid &&
10294 implib->wVersionMajor == libattr->wMajorVerNum &&
10295 implib->wVersionMinor == libattr->wMinorVerNum)
10296 break;
10299 if(&implib->entry == &This->pTypeLib->implib_list){
10300 implib = heap_alloc_zero(sizeof(TLBImpLib));
10302 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10303 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10304 implib->name = SysAllocString(our_container->path);
10305 }else{
10306 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10307 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10308 if(FAILED(hres)){
10309 implib->name = NULL;
10310 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10314 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10315 implib->lcid = libattr->lcid;
10316 implib->wVersionMajor = libattr->wMajorVerNum;
10317 implib->wVersionMinor = libattr->wMinorVerNum;
10319 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10322 ITypeLib_ReleaseTLibAttr(container, libattr);
10323 ITypeLib_Release(container);
10325 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10326 if (FAILED(hres))
10327 return hres;
10329 index = 0;
10330 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10331 if(ref_type->index == TLB_REF_USE_GUID &&
10332 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10333 ref_type->tkind == typeattr->typekind)
10334 break;
10335 ++index;
10338 if(&ref_type->entry == &This->pTypeLib->ref_list){
10339 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10341 ref_type->tkind = typeattr->typekind;
10342 ref_type->pImpTLInfo = implib;
10343 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10345 ref_type->index = TLB_REF_USE_GUID;
10347 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10349 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10352 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10354 *refType = ref_type->reference | 0x1;
10356 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10357 This->pTypeLib->dispatch_href = *refType;
10359 return S_OK;
10362 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10363 UINT index, FUNCDESC *funcDesc)
10365 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10366 TLBFuncDesc tmp_func_desc, *func_desc;
10367 int buf_size, i;
10368 char *buffer;
10369 HRESULT hres;
10371 TRACE("%p %u %p\n", This, index, funcDesc);
10373 if (!funcDesc || funcDesc->oVft & 3)
10374 return E_INVALIDARG;
10376 switch (This->typeattr.typekind) {
10377 case TKIND_MODULE:
10378 if (funcDesc->funckind != FUNC_STATIC)
10379 return TYPE_E_BADMODULEKIND;
10380 break;
10381 case TKIND_DISPATCH:
10382 if (funcDesc->funckind != FUNC_DISPATCH)
10383 return TYPE_E_BADMODULEKIND;
10384 break;
10385 default:
10386 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10387 return TYPE_E_BADMODULEKIND;
10390 if (index > This->typeattr.cFuncs)
10391 return TYPE_E_ELEMENTNOTFOUND;
10393 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10394 !funcDesc->cParams)
10395 return TYPE_E_INCONSISTENTPROPFUNCS;
10397 #ifdef _WIN64
10398 if(This->pTypeLib->syskind == SYS_WIN64 &&
10399 funcDesc->oVft % 8 != 0)
10400 return E_INVALIDARG;
10401 #endif
10403 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10404 TLBFuncDesc_Constructor(&tmp_func_desc);
10406 tmp_func_desc.funcdesc = *funcDesc;
10408 if (tmp_func_desc.funcdesc.oVft != 0)
10409 tmp_func_desc.funcdesc.oVft |= 1;
10411 if (funcDesc->cScodes && funcDesc->lprgscode) {
10412 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10413 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10414 } else {
10415 tmp_func_desc.funcdesc.lprgscode = NULL;
10416 tmp_func_desc.funcdesc.cScodes = 0;
10419 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10420 for (i = 0; i < funcDesc->cParams; ++i) {
10421 buf_size += sizeof(ELEMDESC);
10422 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10424 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10425 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10427 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10428 if (FAILED(hres)) {
10429 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10430 heap_free(tmp_func_desc.funcdesc.lprgscode);
10431 return hres;
10434 for (i = 0; i < funcDesc->cParams; ++i) {
10435 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10436 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10437 if (FAILED(hres)) {
10438 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10439 heap_free(tmp_func_desc.funcdesc.lprgscode);
10440 return hres;
10442 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10443 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10444 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10445 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10446 if (FAILED(hres)) {
10447 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10448 heap_free(tmp_func_desc.funcdesc.lprgscode);
10449 return hres;
10454 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10456 if (This->funcdescs) {
10457 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10458 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10460 if (index < This->typeattr.cFuncs) {
10461 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10462 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10463 func_desc = This->funcdescs + index;
10464 } else
10465 func_desc = This->funcdescs + This->typeattr.cFuncs;
10467 /* move custdata lists to the new memory location */
10468 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10469 if(index != i){
10470 TLBFuncDesc *fd = &This->funcdescs[i];
10471 if(fd->custdata_list.prev == fd->custdata_list.next)
10472 list_init(&fd->custdata_list);
10473 else{
10474 fd->custdata_list.prev->next = &fd->custdata_list;
10475 fd->custdata_list.next->prev = &fd->custdata_list;
10479 } else
10480 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10482 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10483 list_init(&func_desc->custdata_list);
10485 ++This->typeattr.cFuncs;
10487 This->needs_layout = TRUE;
10489 return S_OK;
10492 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10493 UINT index, HREFTYPE refType)
10495 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10496 TLBImplType *impl_type;
10497 HRESULT hres;
10499 TRACE("%p %u %d\n", This, index, refType);
10501 switch(This->typeattr.typekind){
10502 case TKIND_COCLASS: {
10503 if (index == -1) {
10504 FIXME("Unhandled index: -1\n");
10505 return E_NOTIMPL;
10508 if(index != This->typeattr.cImplTypes)
10509 return TYPE_E_ELEMENTNOTFOUND;
10511 break;
10513 case TKIND_INTERFACE:
10514 case TKIND_DISPATCH:
10515 if (index != 0 || This->typeattr.cImplTypes)
10516 return TYPE_E_ELEMENTNOTFOUND;
10517 break;
10518 default:
10519 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10520 return E_NOTIMPL;
10523 if (This->impltypes){
10524 UINT i;
10526 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10527 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10529 if (index < This->typeattr.cImplTypes) {
10530 memmove(This->impltypes + index + 1, This->impltypes + index,
10531 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10532 impl_type = This->impltypes + index;
10533 } else
10534 impl_type = This->impltypes + This->typeattr.cImplTypes;
10536 /* move custdata lists to the new memory location */
10537 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10538 if(index != i){
10539 TLBImplType *it = &This->impltypes[i];
10540 if(it->custdata_list.prev == it->custdata_list.next)
10541 list_init(&it->custdata_list);
10542 else{
10543 it->custdata_list.prev->next = &it->custdata_list;
10544 it->custdata_list.next->prev = &it->custdata_list;
10548 } else
10549 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10551 memset(impl_type, 0, sizeof(TLBImplType));
10552 TLBImplType_Constructor(impl_type);
10553 impl_type->hRef = refType;
10555 ++This->typeattr.cImplTypes;
10557 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10558 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10560 hres = ICreateTypeInfo2_LayOut(iface);
10561 if (FAILED(hres))
10562 return hres;
10564 return S_OK;
10567 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10568 UINT index, INT implTypeFlags)
10570 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10571 TLBImplType *impl_type = &This->impltypes[index];
10573 TRACE("%p %u %x\n", This, index, implTypeFlags);
10575 if (This->typeattr.typekind != TKIND_COCLASS)
10576 return TYPE_E_BADMODULEKIND;
10578 if (index >= This->typeattr.cImplTypes)
10579 return TYPE_E_ELEMENTNOTFOUND;
10581 impl_type->implflags = implTypeFlags;
10583 return S_OK;
10586 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10587 WORD alignment)
10589 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10591 TRACE("%p %d\n", This, alignment);
10593 This->typeattr.cbAlignment = alignment;
10595 return S_OK;
10598 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10599 LPOLESTR schema)
10601 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10603 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10605 if (!schema)
10606 return E_INVALIDARG;
10608 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10610 This->typeattr.lpstrSchema = This->Schema->str;
10612 return S_OK;
10615 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10616 UINT index, VARDESC *varDesc)
10618 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10619 TLBVarDesc *var_desc;
10621 TRACE("%p %u %p\n", This, index, varDesc);
10623 if (This->vardescs){
10624 UINT i;
10626 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10627 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10629 if (index < This->typeattr.cVars) {
10630 memmove(This->vardescs + index + 1, This->vardescs + index,
10631 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10632 var_desc = This->vardescs + index;
10633 } else
10634 var_desc = This->vardescs + This->typeattr.cVars;
10636 /* move custdata lists to the new memory location */
10637 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10638 if(index != i){
10639 TLBVarDesc *var = &This->vardescs[i];
10640 if(var->custdata_list.prev == var->custdata_list.next)
10641 list_init(&var->custdata_list);
10642 else{
10643 var->custdata_list.prev->next = &var->custdata_list;
10644 var->custdata_list.next->prev = &var->custdata_list;
10648 } else
10649 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10651 TLBVarDesc_Constructor(var_desc);
10652 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10653 var_desc->vardesc = *var_desc->vardesc_create;
10655 ++This->typeattr.cVars;
10657 This->needs_layout = TRUE;
10659 return S_OK;
10662 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10663 UINT index, LPOLESTR *names, UINT numNames)
10665 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10666 TLBFuncDesc *func_desc = &This->funcdescs[index];
10667 int i;
10669 TRACE("%p %u %p %u\n", This, index, names, numNames);
10671 if (!names)
10672 return E_INVALIDARG;
10674 if (index >= This->typeattr.cFuncs || numNames == 0)
10675 return TYPE_E_ELEMENTNOTFOUND;
10677 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10678 if(numNames > func_desc->funcdesc.cParams)
10679 return TYPE_E_ELEMENTNOTFOUND;
10680 } else
10681 if(numNames > func_desc->funcdesc.cParams + 1)
10682 return TYPE_E_ELEMENTNOTFOUND;
10684 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10685 TLBFuncDesc *iter = &This->funcdescs[i];
10686 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10687 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10688 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10689 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10690 continue;
10691 return TYPE_E_AMBIGUOUSNAME;
10695 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10697 for (i = 1; i < numNames; ++i) {
10698 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10699 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10702 return S_OK;
10705 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10706 UINT index, LPOLESTR name)
10708 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10710 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10712 if(!name)
10713 return E_INVALIDARG;
10715 if(index >= This->typeattr.cVars)
10716 return TYPE_E_ELEMENTNOTFOUND;
10718 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10719 return S_OK;
10722 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10723 TYPEDESC *tdescAlias)
10725 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10726 HRESULT hr;
10728 TRACE("%p %p\n", This, tdescAlias);
10730 if(!tdescAlias)
10731 return E_INVALIDARG;
10733 if(This->typeattr.typekind != TKIND_ALIAS)
10734 return TYPE_E_BADMODULEKIND;
10736 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10737 if(FAILED(hr))
10738 return hr;
10740 heap_free(This->tdescAlias);
10741 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10742 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10744 return S_OK;
10747 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10748 UINT index, LPOLESTR dllName, LPOLESTR procName)
10750 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10751 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10752 return E_NOTIMPL;
10755 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10756 UINT index, LPOLESTR docString)
10758 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10759 TLBFuncDesc *func_desc = &This->funcdescs[index];
10761 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10763 if(!docString)
10764 return E_INVALIDARG;
10766 if(index >= This->typeattr.cFuncs)
10767 return TYPE_E_ELEMENTNOTFOUND;
10769 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10771 return S_OK;
10774 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
10775 UINT index, LPOLESTR docString)
10777 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10778 TLBVarDesc *var_desc = &This->vardescs[index];
10780 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10782 if(!docString)
10783 return E_INVALIDARG;
10785 if(index >= This->typeattr.cVars)
10786 return TYPE_E_ELEMENTNOTFOUND;
10788 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10790 return S_OK;
10793 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
10794 UINT index, DWORD helpContext)
10796 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10797 TLBFuncDesc *func_desc = &This->funcdescs[index];
10799 TRACE("%p %u %d\n", This, index, helpContext);
10801 if(index >= This->typeattr.cFuncs)
10802 return TYPE_E_ELEMENTNOTFOUND;
10804 func_desc->helpcontext = helpContext;
10806 return S_OK;
10809 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
10810 UINT index, DWORD helpContext)
10812 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10813 TLBVarDesc *var_desc = &This->vardescs[index];
10815 TRACE("%p %u %d\n", This, index, helpContext);
10817 if(index >= This->typeattr.cVars)
10818 return TYPE_E_ELEMENTNOTFOUND;
10820 var_desc->HelpContext = helpContext;
10822 return S_OK;
10825 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
10826 UINT index, BSTR bstrMops)
10828 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10829 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
10830 return E_NOTIMPL;
10833 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
10834 IDLDESC *idlDesc)
10836 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10838 TRACE("%p %p\n", This, idlDesc);
10840 if (!idlDesc)
10841 return E_INVALIDARG;
10843 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
10844 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
10846 return S_OK;
10849 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
10851 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10852 ITypeInfo *tinfo;
10853 TLBFuncDesc *func_desc;
10854 UINT user_vft = 0, i, depth = 0;
10855 HRESULT hres = S_OK;
10857 TRACE("%p\n", This);
10859 This->needs_layout = FALSE;
10861 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
10862 if (FAILED(hres))
10863 return hres;
10865 if (This->typeattr.typekind == TKIND_INTERFACE) {
10866 ITypeInfo *inh;
10867 TYPEATTR *attr;
10868 HREFTYPE inh_href;
10870 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
10872 if (SUCCEEDED(hres)) {
10873 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
10875 if (SUCCEEDED(hres)) {
10876 hres = ITypeInfo_GetTypeAttr(inh, &attr);
10877 if (FAILED(hres)) {
10878 ITypeInfo_Release(inh);
10879 ITypeInfo_Release(tinfo);
10880 return hres;
10882 This->typeattr.cbSizeVft = attr->cbSizeVft;
10883 ITypeInfo_ReleaseTypeAttr(inh, attr);
10886 ++depth;
10887 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
10888 if(SUCCEEDED(hres)){
10889 ITypeInfo *next;
10890 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
10891 if(SUCCEEDED(hres)){
10892 ITypeInfo_Release(inh);
10893 inh = next;
10896 }while(SUCCEEDED(hres));
10897 hres = S_OK;
10899 ITypeInfo_Release(inh);
10900 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10901 This->typeattr.cbSizeVft = 0;
10902 hres = S_OK;
10903 } else {
10904 ITypeInfo_Release(tinfo);
10905 return hres;
10907 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
10908 This->typeattr.cbSizeVft = 0;
10909 hres = S_OK;
10910 } else {
10911 ITypeInfo_Release(tinfo);
10912 return hres;
10914 } else if (This->typeattr.typekind == TKIND_DISPATCH)
10915 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
10916 else
10917 This->typeattr.cbSizeVft = 0;
10919 func_desc = This->funcdescs;
10920 i = 0;
10921 while (i < This->typeattr.cFuncs) {
10922 if (!(func_desc->funcdesc.oVft & 0x1))
10923 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
10925 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
10926 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
10928 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
10930 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
10931 TLBFuncDesc *iter;
10932 UINT j = 0;
10933 BOOL reset = FALSE;
10935 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
10937 iter = This->funcdescs;
10938 while (j < This->typeattr.cFuncs) {
10939 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
10940 if (!reset) {
10941 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
10942 reset = TRUE;
10943 } else
10944 ++func_desc->funcdesc.memid;
10945 iter = This->funcdescs;
10946 j = 0;
10947 } else {
10948 ++iter;
10949 ++j;
10954 ++func_desc;
10955 ++i;
10958 if (user_vft > This->typeattr.cbSizeVft)
10959 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
10961 for(i = 0; i < This->typeattr.cVars; ++i){
10962 TLBVarDesc *var_desc = &This->vardescs[i];
10963 if(var_desc->vardesc.memid == MEMBERID_NIL){
10964 UINT j = 0;
10965 BOOL reset = FALSE;
10966 TLBVarDesc *iter;
10968 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
10970 iter = This->vardescs;
10971 while (j < This->typeattr.cVars) {
10972 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
10973 if (!reset) {
10974 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
10975 reset = TRUE;
10976 } else
10977 ++var_desc->vardesc.memid;
10978 iter = This->vardescs;
10979 j = 0;
10980 } else {
10981 ++iter;
10982 ++j;
10988 ITypeInfo_Release(tinfo);
10989 return hres;
10992 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
10993 UINT index)
10995 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10996 FIXME("%p %u - stub\n", This, index);
10997 return E_NOTIMPL;
11000 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11001 MEMBERID memid, INVOKEKIND invKind)
11003 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11004 FIXME("%p %x %d - stub\n", This, memid, invKind);
11005 return E_NOTIMPL;
11008 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11009 UINT index)
11011 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11012 FIXME("%p %u - stub\n", This, index);
11013 return E_NOTIMPL;
11016 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11017 MEMBERID memid)
11019 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11020 FIXME("%p %x - stub\n", This, memid);
11021 return E_NOTIMPL;
11024 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11025 UINT index)
11027 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11028 FIXME("%p %u - stub\n", This, index);
11029 return E_NOTIMPL;
11032 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11033 REFGUID guid, VARIANT *varVal)
11035 TLBGuid *tlbguid;
11037 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11039 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11041 if (!guid || !varVal)
11042 return E_INVALIDARG;
11044 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11046 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11049 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11050 UINT index, REFGUID guid, VARIANT *varVal)
11052 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11053 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11054 return E_NOTIMPL;
11057 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11058 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11060 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11061 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11062 return E_NOTIMPL;
11065 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11066 UINT index, REFGUID guid, VARIANT *varVal)
11068 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11069 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11070 return E_NOTIMPL;
11073 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11074 UINT index, REFGUID guid, VARIANT *varVal)
11076 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11077 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11078 return E_NOTIMPL;
11081 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11082 ULONG helpStringContext)
11084 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11086 TRACE("%p %u\n", This, helpStringContext);
11088 This->dwHelpStringContext = helpStringContext;
11090 return S_OK;
11093 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11094 UINT index, ULONG helpStringContext)
11096 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11097 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11098 return E_NOTIMPL;
11101 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11102 UINT index, ULONG helpStringContext)
11104 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11105 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11106 return E_NOTIMPL;
11109 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11111 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11112 FIXME("%p - stub\n", This);
11113 return E_NOTIMPL;
11116 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11117 LPOLESTR name)
11119 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11121 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11123 if (!name)
11124 return E_INVALIDARG;
11126 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11128 return S_OK;
11131 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11132 ICreateTypeInfo2_fnQueryInterface,
11133 ICreateTypeInfo2_fnAddRef,
11134 ICreateTypeInfo2_fnRelease,
11135 ICreateTypeInfo2_fnSetGuid,
11136 ICreateTypeInfo2_fnSetTypeFlags,
11137 ICreateTypeInfo2_fnSetDocString,
11138 ICreateTypeInfo2_fnSetHelpContext,
11139 ICreateTypeInfo2_fnSetVersion,
11140 ICreateTypeInfo2_fnAddRefTypeInfo,
11141 ICreateTypeInfo2_fnAddFuncDesc,
11142 ICreateTypeInfo2_fnAddImplType,
11143 ICreateTypeInfo2_fnSetImplTypeFlags,
11144 ICreateTypeInfo2_fnSetAlignment,
11145 ICreateTypeInfo2_fnSetSchema,
11146 ICreateTypeInfo2_fnAddVarDesc,
11147 ICreateTypeInfo2_fnSetFuncAndParamNames,
11148 ICreateTypeInfo2_fnSetVarName,
11149 ICreateTypeInfo2_fnSetTypeDescAlias,
11150 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11151 ICreateTypeInfo2_fnSetFuncDocString,
11152 ICreateTypeInfo2_fnSetVarDocString,
11153 ICreateTypeInfo2_fnSetFuncHelpContext,
11154 ICreateTypeInfo2_fnSetVarHelpContext,
11155 ICreateTypeInfo2_fnSetMops,
11156 ICreateTypeInfo2_fnSetTypeIdldesc,
11157 ICreateTypeInfo2_fnLayOut,
11158 ICreateTypeInfo2_fnDeleteFuncDesc,
11159 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11160 ICreateTypeInfo2_fnDeleteVarDesc,
11161 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11162 ICreateTypeInfo2_fnDeleteImplType,
11163 ICreateTypeInfo2_fnSetCustData,
11164 ICreateTypeInfo2_fnSetFuncCustData,
11165 ICreateTypeInfo2_fnSetParamCustData,
11166 ICreateTypeInfo2_fnSetVarCustData,
11167 ICreateTypeInfo2_fnSetImplTypeCustData,
11168 ICreateTypeInfo2_fnSetHelpStringContext,
11169 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11170 ICreateTypeInfo2_fnSetVarHelpStringContext,
11171 ICreateTypeInfo2_fnInvalidate,
11172 ICreateTypeInfo2_fnSetName
11175 /******************************************************************************
11176 * ClearCustData (OLEAUT32.171)
11178 * Clear a custom data type's data.
11180 * PARAMS
11181 * lpCust [I] The custom data type instance
11183 * RETURNS
11184 * Nothing.
11186 void WINAPI ClearCustData(CUSTDATA *lpCust)
11188 if (lpCust && lpCust->cCustData)
11190 if (lpCust->prgCustData)
11192 DWORD i;
11194 for (i = 0; i < lpCust->cCustData; i++)
11195 VariantClear(&lpCust->prgCustData[i].varValue);
11197 CoTaskMemFree(lpCust->prgCustData);
11198 lpCust->prgCustData = NULL;
11200 lpCust->cCustData = 0;