include: Move inline assembly definitions to a new wine/asm.h header.
[wine.git] / dlls / oleaut32 / typelib.c
blob1a0bceb7ad23d6daaf07669aad2dbdcb648f61d7
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/asm.h"
77 #include "wine/heap.h"
78 #include "wine/list.h"
80 WINE_DEFAULT_DEBUG_CHANNEL(ole);
81 WINE_DECLARE_DEBUG_CHANNEL(typelib);
83 typedef struct
85 WORD offset;
86 WORD length;
87 WORD flags;
88 WORD id;
89 WORD handle;
90 WORD usage;
91 } NE_NAMEINFO;
93 typedef struct
95 WORD type_id; /* Type identifier */
96 WORD count; /* Number of resources of this type */
97 DWORD resloader; /* SetResourceHandler() */
99 * Name info array.
101 } NE_TYPEINFO;
103 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
104 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
105 static void TLB_FreeVarDesc(VARDESC*);
107 /****************************************************************************
108 * FromLExxx
110 * Takes p_iVal (which is in little endian) and returns it
111 * in the host machine's byte order.
113 #ifdef WORDS_BIGENDIAN
114 static WORD FromLEWord(WORD p_iVal)
116 return (((p_iVal & 0x00FF) << 8) |
117 ((p_iVal & 0xFF00) >> 8));
121 static DWORD FromLEDWord(DWORD p_iVal)
123 return (((p_iVal & 0x000000FF) << 24) |
124 ((p_iVal & 0x0000FF00) << 8) |
125 ((p_iVal & 0x00FF0000) >> 8) |
126 ((p_iVal & 0xFF000000) >> 24));
128 #else
129 #define FromLEWord(X) (X)
130 #define FromLEDWord(X) (X)
131 #endif
133 #define DISPATCH_HREF_OFFSET 0x01000000
134 #define DISPATCH_HREF_MASK 0xff000000
136 /****************************************************************************
137 * FromLExxx
139 * Fix byte order in any structure if necessary
141 #ifdef WORDS_BIGENDIAN
142 static void FromLEWords(void *p_Val, int p_iSize)
144 WORD *Val = p_Val;
146 p_iSize /= sizeof(WORD);
148 while (p_iSize) {
149 *Val = FromLEWord(*Val);
150 Val++;
151 p_iSize--;
156 static void FromLEDWords(void *p_Val, int p_iSize)
158 DWORD *Val = p_Val;
160 p_iSize /= sizeof(DWORD);
162 while (p_iSize) {
163 *Val = FromLEDWord(*Val);
164 Val++;
165 p_iSize--;
168 #else
169 #define FromLEWords(X,Y) /*nothing*/
170 #define FromLEDWords(X,Y) /*nothing*/
171 #endif
174 * Find a typelib key which matches a requested maj.min version.
176 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
178 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
179 WCHAR buffer[60];
180 char key_name[16];
181 DWORD len, i;
182 INT best_maj = -1, best_min = -1;
183 HKEY hkey;
185 memcpy( buffer, typelibW, sizeof(typelibW) );
186 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
188 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
189 return FALSE;
191 len = sizeof(key_name);
192 i = 0;
193 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
195 INT v_maj, v_min;
197 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
199 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
201 if (*wMaj == 0xffff && *wMin == 0xffff)
203 if (v_maj > best_maj) best_maj = v_maj;
204 if (v_min > best_min) best_min = v_min;
206 else if (*wMaj == v_maj)
208 best_maj = v_maj;
210 if (*wMin == v_min)
212 best_min = v_min;
213 break; /* exact match */
215 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
218 len = sizeof(key_name);
220 RegCloseKey( hkey );
222 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
224 if (*wMaj == 0xffff && *wMin == 0xffff)
226 if (best_maj >= 0 && best_min >= 0)
228 *wMaj = best_maj;
229 *wMin = best_min;
230 return TRUE;
234 if (*wMaj == best_maj && best_min >= 0)
236 *wMin = best_min;
237 return TRUE;
239 return FALSE;
242 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
243 /* buffer must be at least 60 characters long */
244 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
246 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
247 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
249 memcpy( buffer, TypelibW, sizeof(TypelibW) );
250 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
251 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
252 return buffer;
255 /* get the path of an interface key, in the form "Interface\\<guid>" */
256 /* buffer must be at least 50 characters long */
257 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
259 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
261 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
262 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
263 return buffer;
266 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
267 /* buffer must be at least 16 characters long */
268 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
270 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
271 static const WCHAR win16W[] = {'w','i','n','1','6',0};
272 static const WCHAR win32W[] = {'w','i','n','3','2',0};
273 static const WCHAR win64W[] = {'w','i','n','6','4',0};
275 sprintfW( buffer, LcidFormatW, lcid );
276 switch(syskind)
278 case SYS_WIN16: strcatW( buffer, win16W ); break;
279 case SYS_WIN32: strcatW( buffer, win32W ); break;
280 case SYS_WIN64: strcatW( buffer, win64W ); break;
281 default:
282 TRACE("Typelib is for unsupported syskind %i\n", syskind);
283 return NULL;
285 return buffer;
288 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
290 struct tlibredirect_data
292 ULONG size;
293 DWORD res;
294 ULONG name_len;
295 ULONG name_offset;
296 LANGID langid;
297 WORD flags;
298 ULONG help_len;
299 ULONG help_offset;
300 WORD major_version;
301 WORD minor_version;
304 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
305 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
306 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
308 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
309 LCID myLCID = lcid;
310 HKEY hkey;
311 WCHAR buffer[60];
312 WCHAR Path[MAX_PATH];
313 LONG res;
315 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
317 if (redir)
319 ACTCTX_SECTION_KEYED_DATA data;
321 data.cbSize = sizeof(data);
322 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
324 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
325 WCHAR *nameW;
326 DWORD len;
328 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
329 return TYPE_E_LIBNOTREGISTERED;
331 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
332 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
333 if (!len) return TYPE_E_LIBNOTREGISTERED;
335 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
336 *path = SysAllocString( Path );
337 return S_OK;
341 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
342 get_typelib_key( guid, wMaj, wMin, buffer );
344 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
345 if (res == ERROR_FILE_NOT_FOUND)
347 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
348 return TYPE_E_LIBNOTREGISTERED;
350 else if (res != ERROR_SUCCESS)
352 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
353 return TYPE_E_REGISTRYACCESS;
356 while (hr != S_OK)
358 LONG dwPathLen = sizeof(Path);
360 get_lcid_subkey( myLCID, syskind, buffer );
362 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
364 if (!lcid)
365 break;
366 else if (myLCID == lcid)
368 /* try with sub-langid */
369 myLCID = SUBLANGID(lcid);
371 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
373 /* try with system langid */
374 myLCID = 0;
376 else
378 break;
381 else
383 *path = SysAllocString( Path );
384 hr = S_OK;
387 RegCloseKey( hkey );
388 TRACE_(typelib)("-- 0x%08x\n", hr);
389 return hr;
392 /****************************************************************************
393 * QueryPathOfRegTypeLib [OLEAUT32.164]
395 * Gets the path to a registered type library.
397 * PARAMS
398 * guid [I] referenced guid
399 * wMaj [I] major version
400 * wMin [I] minor version
401 * lcid [I] locale id
402 * path [O] path of typelib
404 * RETURNS
405 * Success: S_OK.
406 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
407 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
408 * opened.
410 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
412 BOOL redir = TRUE;
413 #ifdef _WIN64
414 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
415 if(SUCCEEDED(hres))
416 return hres;
417 redir = FALSE;
418 #endif
419 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
422 /******************************************************************************
423 * CreateTypeLib [OLEAUT32.160] creates a typelib
425 * RETURNS
426 * Success: S_OK
427 * Failure: Status
429 HRESULT WINAPI CreateTypeLib(
430 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
432 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
433 return E_FAIL;
436 /******************************************************************************
437 * LoadTypeLib [OLEAUT32.161]
439 * Loads a type library
441 * PARAMS
442 * szFile [I] Name of file to load from.
443 * pptLib [O] Pointer that receives ITypeLib object on success.
445 * RETURNS
446 * Success: S_OK
447 * Failure: Status
449 * SEE
450 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
452 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
454 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
455 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
458 /******************************************************************************
459 * LoadTypeLibEx [OLEAUT32.183]
461 * Loads and optionally registers a type library
463 * RETURNS
464 * Success: S_OK
465 * Failure: Status
467 HRESULT WINAPI LoadTypeLibEx(
468 LPCOLESTR szFile, /* [in] Name of file to load from */
469 REGKIND regkind, /* [in] Specify kind of registration */
470 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
472 WCHAR szPath[MAX_PATH+1];
473 HRESULT res;
475 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
477 if (!szFile || !pptLib)
478 return E_INVALIDARG;
480 *pptLib = NULL;
482 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
484 if (SUCCEEDED(res))
485 switch(regkind)
487 case REGKIND_DEFAULT:
488 /* don't register typelibs supplied with full path. Experimentation confirms the following */
489 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
490 (szFile[0] && (szFile[1] == ':'))) break;
491 /* else fall-through */
493 case REGKIND_REGISTER:
494 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
496 ITypeLib_Release(*pptLib);
497 *pptLib = 0;
499 break;
500 case REGKIND_NONE:
501 break;
504 TRACE(" returns %08x\n",res);
505 return res;
508 /******************************************************************************
509 * LoadRegTypeLib [OLEAUT32.162]
511 * Loads a registered type library.
513 * PARAMS
514 * rguid [I] GUID of the registered type library.
515 * wVerMajor [I] major version.
516 * wVerMinor [I] minor version.
517 * lcid [I] locale ID.
518 * ppTLib [O] pointer that receives an ITypeLib object on success.
520 * RETURNS
521 * Success: S_OK.
522 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
523 * LoadTypeLib.
525 HRESULT WINAPI LoadRegTypeLib(
526 REFGUID rguid,
527 WORD wVerMajor,
528 WORD wVerMinor,
529 LCID lcid,
530 ITypeLib **ppTLib)
532 BSTR bstr=NULL;
533 HRESULT res;
535 *ppTLib = NULL;
537 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
539 if(SUCCEEDED(res))
541 res= LoadTypeLib(bstr, ppTLib);
542 SysFreeString(bstr);
544 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
546 TLIBATTR *attr;
548 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
549 if (res == S_OK)
551 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
552 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
554 if (mismatch)
556 ITypeLib_Release(*ppTLib);
557 *ppTLib = NULL;
558 res = TYPE_E_LIBNOTREGISTERED;
564 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
566 return res;
570 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
571 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
572 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
573 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
574 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
575 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
577 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
579 WCHAR keyName[60];
580 HKEY key, subKey;
582 static const WCHAR typelib_proxy_clsid[] = {'{','0','0','0','2','0','4','2','4','-',
583 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
584 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
585 static const WCHAR dispatch_proxy_clsid[] = {'{','0','0','0','2','0','4','2','0','-',
586 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
587 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
589 get_interface_key( &tattr->guid, keyName );
590 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
591 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
593 const WCHAR *proxy_clsid;
595 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
596 proxy_clsid = typelib_proxy_clsid;
597 else
598 proxy_clsid = dispatch_proxy_clsid;
600 if (name)
601 RegSetValueExW(key, NULL, 0, REG_SZ,
602 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
604 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
605 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
606 RegSetValueExW(subKey, NULL, 0, REG_SZ,
607 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
608 RegCloseKey(subKey);
611 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
612 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
613 RegSetValueExW(subKey, NULL, 0, REG_SZ,
614 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
615 RegCloseKey(subKey);
618 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
619 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
621 WCHAR buffer[40];
622 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
623 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
625 StringFromGUID2(&libattr->guid, buffer, 40);
626 RegSetValueExW(subKey, NULL, 0, REG_SZ,
627 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
628 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
629 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
630 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
631 RegCloseKey(subKey);
634 RegCloseKey(key);
638 /******************************************************************************
639 * RegisterTypeLib [OLEAUT32.163]
640 * Adds information about a type library to the System Registry
641 * NOTES
642 * Docs: ITypeLib FAR * ptlib
643 * Docs: OLECHAR FAR* szFullPath
644 * Docs: OLECHAR FAR* szHelpDir
646 * RETURNS
647 * Success: S_OK
648 * Failure: Status
650 HRESULT WINAPI RegisterTypeLib(
651 ITypeLib * ptlib, /* [in] Pointer to the library*/
652 OLECHAR * szFullPath, /* [in] full Path of the library*/
653 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
654 may be NULL*/
656 HRESULT res;
657 TLIBATTR *attr;
658 WCHAR keyName[60];
659 WCHAR tmp[16];
660 HKEY key, subKey;
661 UINT types, tidx;
662 TYPEKIND kind;
663 DWORD disposition;
665 if (ptlib == NULL || szFullPath == NULL)
666 return E_INVALIDARG;
668 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
669 return E_FAIL;
671 #ifndef _WIN64
672 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
673 #endif
675 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
677 res = S_OK;
678 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
679 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
681 LPOLESTR doc;
683 /* Set the human-readable name of the typelib */
684 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
685 res = E_FAIL;
686 else if (doc)
688 if (RegSetValueExW(key, NULL, 0, REG_SZ,
689 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
690 res = E_FAIL;
692 SysFreeString(doc);
695 /* Make up the name of the typelib path subkey */
696 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
698 /* Create the typelib path subkey */
699 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
700 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
702 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
703 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
704 res = E_FAIL;
706 RegCloseKey(subKey);
708 else
709 res = E_FAIL;
711 /* Create the flags subkey */
712 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
715 /* FIXME: is %u correct? */
716 static const WCHAR formatW[] = {'%','u',0};
717 WCHAR buf[20];
718 sprintfW(buf, formatW, attr->wLibFlags);
719 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
721 res = E_FAIL;
723 RegCloseKey(subKey);
725 else
726 res = E_FAIL;
728 /* create the helpdir subkey */
729 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
730 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
732 BOOL freeHelpDir = FALSE;
733 OLECHAR* pIndexStr;
735 /* if we created a new key, and helpDir was null, set the helpdir
736 to the directory which contains the typelib. However,
737 if we just opened an existing key, we leave the helpdir alone */
738 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
739 szHelpDir = SysAllocString(szFullPath);
740 pIndexStr = strrchrW(szHelpDir, '\\');
741 if (pIndexStr) {
742 *pIndexStr = 0;
744 freeHelpDir = TRUE;
747 /* if we have an szHelpDir, set it! */
748 if (szHelpDir != NULL) {
749 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
750 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
751 res = E_FAIL;
755 /* tidy up */
756 if (freeHelpDir) SysFreeString(szHelpDir);
757 RegCloseKey(subKey);
759 } else {
760 res = E_FAIL;
763 RegCloseKey(key);
765 else
766 res = E_FAIL;
768 /* register OLE Automation-compatible interfaces for this typelib */
769 types = ITypeLib_GetTypeInfoCount(ptlib);
770 for (tidx=0; tidx<types; tidx++) {
771 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
772 LPOLESTR name = NULL;
773 ITypeInfo *tinfo = NULL;
775 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
777 switch (kind) {
778 case TKIND_INTERFACE:
779 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
780 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
781 break;
783 case TKIND_DISPATCH:
784 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
785 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
786 break;
788 default:
789 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
790 break;
793 if (tinfo) {
794 TYPEATTR *tattr = NULL;
795 ITypeInfo_GetTypeAttr(tinfo, &tattr);
797 if (tattr) {
798 TRACE_(typelib)("guid=%s, flags=%04x (",
799 debugstr_guid(&tattr->guid),
800 tattr->wTypeFlags);
802 if (TRACE_ON(typelib)) {
803 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
804 XX(FAPPOBJECT);
805 XX(FCANCREATE);
806 XX(FLICENSED);
807 XX(FPREDECLID);
808 XX(FHIDDEN);
809 XX(FCONTROL);
810 XX(FDUAL);
811 XX(FNONEXTENSIBLE);
812 XX(FOLEAUTOMATION);
813 XX(FRESTRICTED);
814 XX(FAGGREGATABLE);
815 XX(FREPLACEABLE);
816 XX(FDISPATCHABLE);
817 XX(FREVERSEBIND);
818 XX(FPROXY);
819 #undef XX
820 MESSAGE("\n");
823 /* Register all dispinterfaces (which includes dual interfaces) and
824 oleautomation interfaces */
825 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
826 kind == TKIND_DISPATCH)
828 BOOL is_wow64;
829 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
831 /* register interface<->typelib coupling */
832 TLB_register_interface(attr, name, tattr, 0);
834 /* register TLBs into the opposite registry view, too */
835 if(opposite == KEY_WOW64_32KEY ||
836 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
837 TLB_register_interface(attr, name, tattr, opposite);
840 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
843 ITypeInfo_Release(tinfo);
846 SysFreeString(name);
850 ITypeLib_ReleaseTLibAttr(ptlib, attr);
852 return res;
855 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
857 WCHAR subKeyName[50];
858 HKEY subKey;
860 /* the path to the type */
861 get_interface_key( guid, subKeyName );
863 /* Delete its bits */
864 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
865 return;
867 RegDeleteKeyW(subKey, ProxyStubClsidW);
868 RegDeleteKeyW(subKey, ProxyStubClsid32W);
869 RegDeleteKeyW(subKey, TypeLibW);
870 RegCloseKey(subKey);
871 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
874 /******************************************************************************
875 * UnRegisterTypeLib [OLEAUT32.186]
876 * Removes information about a type library from the System Registry
877 * NOTES
879 * RETURNS
880 * Success: S_OK
881 * Failure: Status
883 HRESULT WINAPI UnRegisterTypeLib(
884 REFGUID libid, /* [in] Guid of the library */
885 WORD wVerMajor, /* [in] major version */
886 WORD wVerMinor, /* [in] minor version */
887 LCID lcid, /* [in] locale id */
888 SYSKIND syskind)
890 BSTR tlibPath = NULL;
891 DWORD tmpLength;
892 WCHAR keyName[60];
893 WCHAR subKeyName[50];
894 int result = S_OK;
895 DWORD i = 0;
896 BOOL deleteOtherStuff;
897 HKEY key = NULL;
898 TYPEATTR* typeAttr = NULL;
899 TYPEKIND kind;
900 ITypeInfo* typeInfo = NULL;
901 ITypeLib* typeLib = NULL;
902 int numTypes;
904 TRACE("(IID: %s)\n",debugstr_guid(libid));
906 /* Create the path to the key */
907 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
909 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
911 TRACE("Unsupported syskind %i\n", syskind);
912 result = E_INVALIDARG;
913 goto end;
916 /* get the path to the typelib on disk */
917 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
918 result = E_INVALIDARG;
919 goto end;
922 /* Try and open the key to the type library. */
923 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
924 result = E_INVALIDARG;
925 goto end;
928 /* Try and load the type library */
929 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
930 result = TYPE_E_INVALIDSTATE;
931 goto end;
934 /* remove any types registered with this typelib */
935 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
936 for (i=0; i<numTypes; i++) {
937 /* get the kind of type */
938 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
939 goto enddeleteloop;
942 /* skip non-interfaces, and get type info for the type */
943 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
944 goto enddeleteloop;
946 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
947 goto enddeleteloop;
949 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
950 goto enddeleteloop;
953 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
954 kind == TKIND_DISPATCH)
956 BOOL is_wow64;
957 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
959 TLB_unregister_interface(&typeAttr->guid, 0);
961 /* unregister TLBs into the opposite registry view, too */
962 if(opposite == KEY_WOW64_32KEY ||
963 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
964 TLB_unregister_interface(&typeAttr->guid, opposite);
968 enddeleteloop:
969 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
970 typeAttr = NULL;
971 if (typeInfo) ITypeInfo_Release(typeInfo);
972 typeInfo = NULL;
975 /* Now, delete the type library path subkey */
976 get_lcid_subkey( lcid, syskind, subKeyName );
977 RegDeleteKeyW(key, subKeyName);
978 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
979 RegDeleteKeyW(key, subKeyName);
981 /* check if there is anything besides the FLAGS/HELPDIR keys.
982 If there is, we don't delete them */
983 tmpLength = ARRAY_SIZE(subKeyName);
984 deleteOtherStuff = TRUE;
985 i = 0;
986 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
987 tmpLength = ARRAY_SIZE(subKeyName);
989 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
990 if (!strcmpW(subKeyName, FLAGSW)) continue;
991 if (!strcmpW(subKeyName, HELPDIRW)) continue;
992 deleteOtherStuff = FALSE;
993 break;
996 /* only delete the other parts of the key if we're absolutely sure */
997 if (deleteOtherStuff) {
998 RegDeleteKeyW(key, FLAGSW);
999 RegDeleteKeyW(key, HELPDIRW);
1000 RegCloseKey(key);
1001 key = NULL;
1003 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1004 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
1005 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1008 end:
1009 SysFreeString(tlibPath);
1010 if (typeLib) ITypeLib_Release(typeLib);
1011 if (key) RegCloseKey(key);
1012 return result;
1015 /******************************************************************************
1016 * RegisterTypeLibForUser [OLEAUT32.442]
1017 * Adds information about a type library to the user registry
1018 * NOTES
1019 * Docs: ITypeLib FAR * ptlib
1020 * Docs: OLECHAR FAR* szFullPath
1021 * Docs: OLECHAR FAR* szHelpDir
1023 * RETURNS
1024 * Success: S_OK
1025 * Failure: Status
1027 HRESULT WINAPI RegisterTypeLibForUser(
1028 ITypeLib * ptlib, /* [in] Pointer to the library*/
1029 OLECHAR * szFullPath, /* [in] full Path of the library*/
1030 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1031 may be NULL*/
1033 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1034 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1035 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1038 /******************************************************************************
1039 * UnRegisterTypeLibForUser [OLEAUT32.443]
1040 * Removes information about a type library from the user registry
1042 * RETURNS
1043 * Success: S_OK
1044 * Failure: Status
1046 HRESULT WINAPI UnRegisterTypeLibForUser(
1047 REFGUID libid, /* [in] GUID of the library */
1048 WORD wVerMajor, /* [in] major version */
1049 WORD wVerMinor, /* [in] minor version */
1050 LCID lcid, /* [in] locale id */
1051 SYSKIND syskind)
1053 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1054 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1055 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1058 /*======================= ITypeLib implementation =======================*/
1060 typedef struct tagTLBGuid {
1061 GUID guid;
1062 INT hreftype;
1063 UINT offset;
1064 struct list entry;
1065 } TLBGuid;
1067 typedef struct tagTLBCustData
1069 TLBGuid *guid;
1070 VARIANT data;
1071 struct list entry;
1072 } TLBCustData;
1074 /* data structure for import typelibs */
1075 typedef struct tagTLBImpLib
1077 int offset; /* offset in the file (MSFT)
1078 offset in nametable (SLTG)
1079 just used to identify library while reading
1080 data from file */
1081 TLBGuid *guid; /* libid */
1082 BSTR name; /* name */
1084 LCID lcid; /* lcid of imported typelib */
1086 WORD wVersionMajor; /* major version number */
1087 WORD wVersionMinor; /* minor version number */
1089 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1090 NULL if not yet loaded */
1091 struct list entry;
1092 } TLBImpLib;
1094 typedef struct tagTLBString {
1095 BSTR str;
1096 UINT offset;
1097 struct list entry;
1098 } TLBString;
1100 /* internal ITypeLib data */
1101 typedef struct tagITypeLibImpl
1103 ITypeLib2 ITypeLib2_iface;
1104 ITypeComp ITypeComp_iface;
1105 ICreateTypeLib2 ICreateTypeLib2_iface;
1106 LONG ref;
1107 TLBGuid *guid;
1108 LCID lcid;
1109 SYSKIND syskind;
1110 int ptr_size;
1111 WORD ver_major;
1112 WORD ver_minor;
1113 WORD libflags;
1114 LCID set_lcid;
1116 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1117 * exported to the application as a UNICODE string.
1119 struct list string_list;
1120 struct list name_list;
1121 struct list guid_list;
1123 const TLBString *Name;
1124 const TLBString *DocString;
1125 const TLBString *HelpFile;
1126 const TLBString *HelpStringDll;
1127 DWORD dwHelpContext;
1128 int TypeInfoCount; /* nr of typeinfo's in librarry */
1129 struct tagITypeInfoImpl **typeinfos;
1130 struct list custdata_list;
1131 struct list implib_list;
1132 int ctTypeDesc; /* number of items in type desc array */
1133 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1134 library. Only used while reading MSFT
1135 typelibs */
1136 struct list ref_list; /* list of ref types in this typelib */
1137 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1140 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1141 struct list entry;
1142 WCHAR *path;
1143 INT index;
1144 } ITypeLibImpl;
1146 static const ITypeLib2Vtbl tlbvt;
1147 static const ITypeCompVtbl tlbtcvt;
1148 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1150 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1152 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1155 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1157 return impl_from_ITypeLib2((ITypeLib2*)iface);
1160 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1162 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1165 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1167 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1170 /* ITypeLib methods */
1171 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1172 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1174 /*======================= ITypeInfo implementation =======================*/
1176 /* data for referenced types */
1177 typedef struct tagTLBRefType
1179 INT index; /* Type index for internal ref or for external ref
1180 it the format is SLTG. -2 indicates to
1181 use guid */
1183 TYPEKIND tkind;
1184 TLBGuid *guid; /* guid of the referenced type */
1185 /* if index == TLB_REF_USE_GUID */
1187 HREFTYPE reference; /* The href of this ref */
1188 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1189 TLB_REF_INTERNAL for internal refs
1190 TLB_REF_NOT_FOUND for broken refs */
1192 struct list entry;
1193 } TLBRefType;
1195 #define TLB_REF_USE_GUID -2
1197 #define TLB_REF_INTERNAL (void*)-2
1198 #define TLB_REF_NOT_FOUND (void*)-1
1200 /* internal Parameter data */
1201 typedef struct tagTLBParDesc
1203 const TLBString *Name;
1204 struct list custdata_list;
1205 } TLBParDesc;
1207 /* internal Function data */
1208 typedef struct tagTLBFuncDesc
1210 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1211 const TLBString *Name; /* the name of this function */
1212 TLBParDesc *pParamDesc; /* array with param names and custom data */
1213 int helpcontext;
1214 int HelpStringContext;
1215 const TLBString *HelpString;
1216 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1217 struct list custdata_list;
1218 } TLBFuncDesc;
1220 /* internal Variable data */
1221 typedef struct tagTLBVarDesc
1223 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1224 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1225 const TLBString *Name; /* the name of this variable */
1226 int HelpContext;
1227 int HelpStringContext;
1228 const TLBString *HelpString;
1229 struct list custdata_list;
1230 } TLBVarDesc;
1232 /* internal implemented interface data */
1233 typedef struct tagTLBImplType
1235 HREFTYPE hRef; /* hRef of interface */
1236 int implflags; /* IMPLFLAG_*s */
1237 struct list custdata_list;
1238 } TLBImplType;
1240 /* internal TypeInfo data */
1241 typedef struct tagITypeInfoImpl
1243 ITypeInfo2 ITypeInfo2_iface;
1244 ITypeComp ITypeComp_iface;
1245 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1246 LONG ref;
1247 BOOL not_attached_to_typelib;
1248 BOOL needs_layout;
1250 TLBGuid *guid;
1251 TYPEATTR typeattr;
1252 TYPEDESC *tdescAlias;
1254 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1255 int index; /* index in this typelib; */
1256 HREFTYPE hreftype; /* hreftype for app object binding */
1257 /* type libs seem to store the doc strings in ascii
1258 * so why should we do it in unicode?
1260 const TLBString *Name;
1261 const TLBString *DocString;
1262 const TLBString *DllName;
1263 const TLBString *Schema;
1264 DWORD dwHelpContext;
1265 DWORD dwHelpStringContext;
1267 /* functions */
1268 TLBFuncDesc *funcdescs;
1270 /* variables */
1271 TLBVarDesc *vardescs;
1273 /* Implemented Interfaces */
1274 TLBImplType *impltypes;
1276 struct list *pcustdata_list;
1277 struct list custdata_list;
1278 } ITypeInfoImpl;
1280 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1282 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1285 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1287 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1290 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1292 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1295 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1297 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1300 static const ITypeInfo2Vtbl tinfvt;
1301 static const ITypeCompVtbl tcompvt;
1302 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1304 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1305 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1307 typedef struct tagTLBContext
1309 unsigned int oStart; /* start of TLB in file */
1310 unsigned int pos; /* current pos */
1311 unsigned int length; /* total length */
1312 void *mapping; /* memory mapping */
1313 MSFT_SegDir * pTblDir;
1314 ITypeLibImpl* pLibInfo;
1315 } TLBContext;
1318 static inline BSTR TLB_get_bstr(const TLBString *str)
1320 return str != NULL ? str->str : NULL;
1323 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1325 if(!str)
1326 return 1;
1327 return memcmp(left, str->str, len);
1330 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1332 return guid != NULL ? &guid->guid : NULL;
1335 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1337 return guid != NULL ? &guid->guid : &GUID_NULL;
1340 static int get_ptr_size(SYSKIND syskind)
1342 switch(syskind){
1343 case SYS_WIN64:
1344 return 8;
1345 case SYS_WIN32:
1346 case SYS_MAC:
1347 case SYS_WIN16:
1348 return 4;
1350 WARN("Unhandled syskind: 0x%x\n", syskind);
1351 return 4;
1355 debug
1357 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1358 if (pTD->vt & VT_RESERVED)
1359 szVarType += strlen(strcpy(szVarType, "reserved | "));
1360 if (pTD->vt & VT_BYREF)
1361 szVarType += strlen(strcpy(szVarType, "ref to "));
1362 if (pTD->vt & VT_ARRAY)
1363 szVarType += strlen(strcpy(szVarType, "array of "));
1364 if (pTD->vt & VT_VECTOR)
1365 szVarType += strlen(strcpy(szVarType, "vector of "));
1366 switch(pTD->vt & VT_TYPEMASK) {
1367 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1368 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1369 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1370 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1371 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1372 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1373 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1374 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1375 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1376 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1377 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1378 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1379 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1380 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1381 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1382 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1383 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1384 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1385 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1386 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1387 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1388 pTD->u.hreftype); break;
1389 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1390 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1391 case VT_PTR: sprintf(szVarType, "ptr to ");
1392 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1393 break;
1394 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1395 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1396 break;
1397 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1398 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1399 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1400 break;
1402 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1406 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1407 char buf[200];
1408 USHORT flags = edesc->u.paramdesc.wParamFlags;
1409 dump_TypeDesc(&edesc->tdesc,buf);
1410 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1411 MESSAGE("\t\tu.paramdesc.wParamFlags");
1412 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1413 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1414 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1415 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1416 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1417 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1418 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1419 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1420 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1422 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1423 int i;
1424 MESSAGE("memid is %08x\n",funcdesc->memid);
1425 for (i=0;i<funcdesc->cParams;i++) {
1426 MESSAGE("Param %d:\n",i);
1427 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1429 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1430 switch (funcdesc->funckind) {
1431 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1432 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1433 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1434 case FUNC_STATIC: MESSAGE("static");break;
1435 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1436 default: MESSAGE("unknown");break;
1438 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1439 switch (funcdesc->invkind) {
1440 case INVOKE_FUNC: MESSAGE("func");break;
1441 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1442 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1443 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1445 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1446 switch (funcdesc->callconv) {
1447 case CC_CDECL: MESSAGE("cdecl");break;
1448 case CC_PASCAL: MESSAGE("pascal");break;
1449 case CC_STDCALL: MESSAGE("stdcall");break;
1450 case CC_SYSCALL: MESSAGE("syscall");break;
1451 default:break;
1453 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1454 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1455 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1457 MESSAGE("\telemdescFunc (return value type):\n");
1458 dump_ELEMDESC(&funcdesc->elemdescFunc);
1461 static const char * const typekind_desc[] =
1463 "TKIND_ENUM",
1464 "TKIND_RECORD",
1465 "TKIND_MODULE",
1466 "TKIND_INTERFACE",
1467 "TKIND_DISPATCH",
1468 "TKIND_COCLASS",
1469 "TKIND_ALIAS",
1470 "TKIND_UNION",
1471 "TKIND_MAX"
1474 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1476 int i;
1477 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1478 for (i=0;i<pfd->funcdesc.cParams;i++)
1479 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1482 dump_FUNCDESC(&(pfd->funcdesc));
1484 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1485 if(pfd->Entry == NULL)
1486 MESSAGE("\tentry: (null)\n");
1487 else if(pfd->Entry == (void*)-1)
1488 MESSAGE("\tentry: invalid\n");
1489 else if(IS_INTRESOURCE(pfd->Entry))
1490 MESSAGE("\tentry: %p\n", pfd->Entry);
1491 else
1492 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1494 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1496 while (n)
1498 dump_TLBFuncDescOne(pfd);
1499 ++pfd;
1500 --n;
1503 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1505 while (n)
1507 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1508 ++pvd;
1509 --n;
1513 static void dump_TLBImpLib(const TLBImpLib *import)
1515 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1516 debugstr_w(import->name));
1517 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1518 import->wVersionMinor, import->lcid, import->offset);
1521 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1523 TLBRefType *ref;
1525 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1527 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1528 if(ref->index == -1)
1529 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1530 else
1531 TRACE_(typelib)("type no: %d\n", ref->index);
1533 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1535 TRACE_(typelib)("in lib\n");
1536 dump_TLBImpLib(ref->pImpTLInfo);
1541 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1543 if(!impl)
1544 return;
1545 while (n) {
1546 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1547 impl->hRef, impl->implflags);
1548 ++impl;
1549 --n;
1553 static void dump_DispParms(const DISPPARAMS * pdp)
1555 unsigned int index;
1557 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1559 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1561 TRACE("named args:\n");
1562 for (index = 0; index < pdp->cNamedArgs; index++)
1563 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1566 if (pdp->cArgs && pdp->rgvarg)
1568 TRACE("args:\n");
1569 for (index = 0; index < pdp->cArgs; index++)
1570 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1574 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1576 TRACE("%p ref=%u\n", pty, pty->ref);
1577 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1578 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1579 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1580 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1581 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1582 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1583 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1584 if (TRACE_ON(ole))
1585 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1586 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1587 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1590 static void dump_VARDESC(const VARDESC *v)
1592 MESSAGE("memid %d\n",v->memid);
1593 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1594 MESSAGE("oInst %d\n",v->u.oInst);
1595 dump_ELEMDESC(&(v->elemdescVar));
1596 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1597 MESSAGE("varkind %d\n",v->varkind);
1600 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1602 /* VT_LPWSTR is largest type that, may appear in type description */
1603 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1604 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1605 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1606 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1607 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1608 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1609 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1610 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1613 static void TLB_abort(void)
1615 DebugBreak();
1618 /* returns the size required for a deep copy of a typedesc into a
1619 * flat buffer */
1620 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1622 SIZE_T size = 0;
1624 if (alloc_initial_space)
1625 size += sizeof(TYPEDESC);
1627 switch (tdesc->vt)
1629 case VT_PTR:
1630 case VT_SAFEARRAY:
1631 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1632 break;
1633 case VT_CARRAY:
1634 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1635 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1636 break;
1638 return size;
1641 /* deep copy a typedesc into a flat buffer */
1642 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1644 if (!dest)
1646 dest = buffer;
1647 buffer = (char *)buffer + sizeof(TYPEDESC);
1650 *dest = *src;
1652 switch (src->vt)
1654 case VT_PTR:
1655 case VT_SAFEARRAY:
1656 dest->u.lptdesc = buffer;
1657 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1658 break;
1659 case VT_CARRAY:
1660 dest->u.lpadesc = buffer;
1661 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1662 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1663 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1664 break;
1666 return buffer;
1669 /* free custom data allocated by MSFT_CustData */
1670 static inline void TLB_FreeCustData(struct list *custdata_list)
1672 TLBCustData *cd, *cdn;
1673 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1675 list_remove(&cd->entry);
1676 VariantClear(&cd->data);
1677 heap_free(cd);
1681 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1683 DWORD len;
1684 BSTR ret;
1686 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1687 ret = SysAllocStringLen(NULL, len - 1);
1688 if (!ret) return ret;
1689 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1690 return ret;
1693 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1694 UINT n, MEMBERID memid)
1696 while(n){
1697 if(funcdescs->funcdesc.memid == memid)
1698 return funcdescs;
1699 ++funcdescs;
1700 --n;
1702 return NULL;
1705 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1706 UINT n, MEMBERID memid)
1708 while(n){
1709 if(vardescs->vardesc.memid == memid)
1710 return vardescs;
1711 ++vardescs;
1712 --n;
1714 return NULL;
1717 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1718 UINT n, const OLECHAR *name)
1720 while(n){
1721 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1722 return vardescs;
1723 ++vardescs;
1724 --n;
1726 return NULL;
1729 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1731 TLBCustData *cust_data;
1732 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1733 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1734 return cust_data;
1735 return NULL;
1738 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1739 UINT n, const OLECHAR *name)
1741 while(n){
1742 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1743 return *typeinfos;
1744 ++typeinfos;
1745 --n;
1747 return NULL;
1750 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1752 list_init(&var_desc->custdata_list);
1755 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1757 TLBVarDesc *ret;
1759 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1760 if(!ret)
1761 return NULL;
1763 while(n){
1764 TLBVarDesc_Constructor(&ret[n-1]);
1765 --n;
1768 return ret;
1771 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1773 TLBParDesc *ret;
1775 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1776 if(!ret)
1777 return NULL;
1779 while(n){
1780 list_init(&ret[n-1].custdata_list);
1781 --n;
1784 return ret;
1787 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1789 list_init(&func_desc->custdata_list);
1792 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1794 TLBFuncDesc *ret;
1796 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1797 if(!ret)
1798 return NULL;
1800 while(n){
1801 TLBFuncDesc_Constructor(&ret[n-1]);
1802 --n;
1805 return ret;
1808 static void TLBImplType_Constructor(TLBImplType *impl)
1810 list_init(&impl->custdata_list);
1813 static TLBImplType *TLBImplType_Alloc(UINT n)
1815 TLBImplType *ret;
1817 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1818 if(!ret)
1819 return NULL;
1821 while(n){
1822 TLBImplType_Constructor(&ret[n-1]);
1823 --n;
1826 return ret;
1829 static TLBGuid *TLB_append_guid(struct list *guid_list,
1830 const GUID *new_guid, HREFTYPE hreftype)
1832 TLBGuid *guid;
1834 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1835 if (IsEqualGUID(&guid->guid, new_guid))
1836 return guid;
1839 guid = heap_alloc(sizeof(TLBGuid));
1840 if (!guid)
1841 return NULL;
1843 memcpy(&guid->guid, new_guid, sizeof(GUID));
1844 guid->hreftype = hreftype;
1846 list_add_tail(guid_list, &guid->entry);
1848 return guid;
1851 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1853 TLBCustData *cust_data;
1855 switch(V_VT(var)){
1856 case VT_I4:
1857 case VT_R4:
1858 case VT_UI4:
1859 case VT_INT:
1860 case VT_UINT:
1861 case VT_HRESULT:
1862 case VT_BSTR:
1863 break;
1864 default:
1865 return DISP_E_BADVARTYPE;
1868 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1870 if (!cust_data) {
1871 cust_data = heap_alloc(sizeof(TLBCustData));
1872 if (!cust_data)
1873 return E_OUTOFMEMORY;
1875 cust_data->guid = tlbguid;
1876 VariantInit(&cust_data->data);
1878 list_add_tail(custdata_list, &cust_data->entry);
1879 }else
1880 VariantClear(&cust_data->data);
1882 return VariantCopy(&cust_data->data, var);
1885 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1887 TLBString *str;
1889 if(!new_str)
1890 return NULL;
1892 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1893 if (strcmpW(str->str, new_str) == 0)
1894 return str;
1897 str = heap_alloc(sizeof(TLBString));
1898 if (!str)
1899 return NULL;
1901 str->str = SysAllocString(new_str);
1902 if (!str->str) {
1903 heap_free(str);
1904 return NULL;
1907 list_add_tail(string_list, &str->entry);
1909 return str;
1912 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1913 ULONG *size, WORD *align)
1915 ITypeInfo *other;
1916 TYPEATTR *attr;
1917 HRESULT hr;
1919 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1920 if(FAILED(hr))
1921 return hr;
1923 hr = ITypeInfo_GetTypeAttr(other, &attr);
1924 if(FAILED(hr)){
1925 ITypeInfo_Release(other);
1926 return hr;
1929 if(size)
1930 *size = attr->cbSizeInstance;
1931 if(align)
1932 *align = attr->cbAlignment;
1934 ITypeInfo_ReleaseTypeAttr(other, attr);
1935 ITypeInfo_Release(other);
1937 return S_OK;
1940 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1941 TYPEDESC *tdesc, ULONG *size, WORD *align)
1943 ULONG i, sub, ptr_size;
1944 HRESULT hr;
1946 ptr_size = get_ptr_size(sys);
1948 switch(tdesc->vt){
1949 case VT_VOID:
1950 *size = 0;
1951 break;
1952 case VT_I1:
1953 case VT_UI1:
1954 *size = 1;
1955 break;
1956 case VT_I2:
1957 case VT_BOOL:
1958 case VT_UI2:
1959 *size = 2;
1960 break;
1961 case VT_I4:
1962 case VT_R4:
1963 case VT_ERROR:
1964 case VT_UI4:
1965 case VT_INT:
1966 case VT_UINT:
1967 case VT_HRESULT:
1968 *size = 4;
1969 break;
1970 case VT_R8:
1971 case VT_I8:
1972 case VT_UI8:
1973 *size = 8;
1974 break;
1975 case VT_BSTR:
1976 case VT_DISPATCH:
1977 case VT_UNKNOWN:
1978 case VT_PTR:
1979 case VT_SAFEARRAY:
1980 case VT_LPSTR:
1981 case VT_LPWSTR:
1982 *size = ptr_size;
1983 break;
1984 case VT_DATE:
1985 *size = sizeof(DATE);
1986 break;
1987 case VT_VARIANT:
1988 *size = sizeof(VARIANT);
1989 #ifdef _WIN64
1990 if(sys == SYS_WIN32)
1991 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1992 #endif
1993 break;
1994 case VT_DECIMAL:
1995 *size = sizeof(DECIMAL);
1996 break;
1997 case VT_CY:
1998 *size = sizeof(CY);
1999 break;
2000 case VT_CARRAY:
2001 *size = 0;
2002 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2003 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2004 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2005 if(FAILED(hr))
2006 return hr;
2007 *size *= sub;
2008 return S_OK;
2009 case VT_USERDEFINED:
2010 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2011 default:
2012 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2013 return E_FAIL;
2016 if(align){
2017 if(*size < 4)
2018 *align = *size;
2019 else
2020 *align = 4;
2023 return S_OK;
2026 /**********************************************************************
2028 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2031 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2033 if (where != DO_NOT_SEEK)
2035 where += pcx->oStart;
2036 if (where > pcx->length)
2038 /* FIXME */
2039 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2040 TLB_abort();
2042 pcx->pos = where;
2046 /* read function */
2047 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2049 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2050 pcx->pos, count, pcx->oStart, pcx->length, where);
2052 MSFT_Seek(pcx, where);
2053 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2054 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2055 pcx->pos += count;
2056 return count;
2059 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2060 LONG where )
2062 DWORD ret;
2064 ret = MSFT_Read(buffer, count, pcx, where);
2065 FromLEDWords(buffer, ret);
2067 return ret;
2070 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2071 LONG where )
2073 DWORD ret;
2075 ret = MSFT_Read(buffer, count, pcx, where);
2076 FromLEWords(buffer, ret);
2078 return ret;
2081 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2083 TLBGuid *guid;
2084 MSFT_GuidEntry entry;
2085 int offs = 0;
2087 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2088 while (1) {
2089 if (offs >= pcx->pTblDir->pGuidTab.length)
2090 return S_OK;
2092 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2094 guid = heap_alloc(sizeof(TLBGuid));
2096 guid->offset = offs;
2097 guid->guid = entry.guid;
2098 guid->hreftype = entry.hreftype;
2100 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2102 offs += sizeof(MSFT_GuidEntry);
2106 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2108 TLBGuid *ret;
2110 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2111 if(ret->offset == offset){
2112 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2113 return ret;
2117 return NULL;
2120 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2122 MSFT_NameIntro niName;
2124 if (offset < 0)
2126 ERR_(typelib)("bad offset %d\n", offset);
2127 return -1;
2130 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2131 pcx->pTblDir->pNametab.offset+offset);
2133 return niName.hreftype;
2136 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2138 char *string;
2139 MSFT_NameIntro intro;
2140 INT16 len_piece;
2141 int offs = 0, lengthInChars;
2143 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2144 while (1) {
2145 TLBString *tlbstr;
2147 if (offs >= pcx->pTblDir->pNametab.length)
2148 return S_OK;
2150 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2151 intro.namelen &= 0xFF;
2152 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2153 if(len_piece % 4)
2154 len_piece = (len_piece + 4) & ~0x3;
2155 if(len_piece < 8)
2156 len_piece = 8;
2158 string = heap_alloc(len_piece + 1);
2159 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2160 string[intro.namelen] = '\0';
2162 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2163 string, -1, NULL, 0);
2164 if (!lengthInChars) {
2165 heap_free(string);
2166 return E_UNEXPECTED;
2169 tlbstr = heap_alloc(sizeof(TLBString));
2171 tlbstr->offset = offs;
2172 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2173 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2175 heap_free(string);
2177 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2179 offs += len_piece;
2183 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2185 TLBString *tlbstr;
2187 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2188 if (tlbstr->offset == offset) {
2189 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2190 return tlbstr;
2194 return NULL;
2197 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2199 TLBString *tlbstr;
2201 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2202 if (tlbstr->offset == offset) {
2203 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2204 return tlbstr;
2208 return NULL;
2212 * read a value and fill a VARIANT structure
2214 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2216 int size;
2218 TRACE_(typelib)("\n");
2220 if(offset <0) { /* data are packed in here */
2221 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2222 V_I4(pVar) = offset & 0x3ffffff;
2223 return;
2225 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2226 pcx->pTblDir->pCustData.offset + offset );
2227 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2228 switch (V_VT(pVar)){
2229 case VT_EMPTY: /* FIXME: is this right? */
2230 case VT_NULL: /* FIXME: is this right? */
2231 case VT_I2 : /* this should not happen */
2232 case VT_I4 :
2233 case VT_R4 :
2234 case VT_ERROR :
2235 case VT_BOOL :
2236 case VT_I1 :
2237 case VT_UI1 :
2238 case VT_UI2 :
2239 case VT_UI4 :
2240 case VT_INT :
2241 case VT_UINT :
2242 case VT_VOID : /* FIXME: is this right? */
2243 case VT_HRESULT :
2244 size=4; break;
2245 case VT_R8 :
2246 case VT_CY :
2247 case VT_DATE :
2248 case VT_I8 :
2249 case VT_UI8 :
2250 case VT_DECIMAL : /* FIXME: is this right? */
2251 case VT_FILETIME :
2252 size=8;break;
2253 /* pointer types with known behaviour */
2254 case VT_BSTR :{
2255 char * ptr;
2256 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2257 if(size == -1){
2258 V_BSTR(pVar) = NULL;
2259 }else{
2260 ptr = heap_alloc_zero(size);
2261 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2262 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2263 /* FIXME: do we need a AtoW conversion here? */
2264 V_UNION(pVar, bstrVal[size])='\0';
2265 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2266 heap_free(ptr);
2269 size=-4; break;
2270 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2271 case VT_DISPATCH :
2272 case VT_VARIANT :
2273 case VT_UNKNOWN :
2274 case VT_PTR :
2275 case VT_SAFEARRAY :
2276 case VT_CARRAY :
2277 case VT_USERDEFINED :
2278 case VT_LPSTR :
2279 case VT_LPWSTR :
2280 case VT_BLOB :
2281 case VT_STREAM :
2282 case VT_STORAGE :
2283 case VT_STREAMED_OBJECT :
2284 case VT_STORED_OBJECT :
2285 case VT_BLOB_OBJECT :
2286 case VT_CF :
2287 case VT_CLSID :
2288 default:
2289 size=0;
2290 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2291 V_VT(pVar));
2294 if(size>0) /* (big|small) endian correct? */
2295 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2296 return;
2299 * create a linked list with custom data
2301 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2303 MSFT_CDGuid entry;
2304 TLBCustData* pNew;
2305 int count=0;
2307 TRACE_(typelib)("\n");
2309 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2311 while(offset >=0){
2312 count++;
2313 pNew=heap_alloc_zero(sizeof(TLBCustData));
2314 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2315 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2316 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2317 list_add_head(custdata_list, &pNew->entry);
2318 offset = entry.next;
2320 return count;
2323 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2325 if(type <0)
2326 pTd->vt=type & VT_TYPEMASK;
2327 else
2328 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2330 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2333 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2335 return (invkind == INVOKE_PROPERTYGET ||
2336 invkind == INVOKE_PROPERTYPUT ||
2337 invkind == INVOKE_PROPERTYPUTREF);
2340 static void
2341 MSFT_DoFuncs(TLBContext* pcx,
2342 ITypeInfoImpl* pTI,
2343 int cFuncs,
2344 int cVars,
2345 int offset,
2346 TLBFuncDesc** pptfd)
2349 * member information is stored in a data structure at offset
2350 * indicated by the memoffset field of the typeinfo structure
2351 * There are several distinctive parts.
2352 * The first part starts with a field that holds the total length
2353 * of this (first) part excluding this field. Then follow the records,
2354 * for each member there is one record.
2356 * The first entry is always the length of the record (including this
2357 * length word).
2358 * The rest of the record depends on the type of the member. If there is
2359 * a field indicating the member type (function, variable, interface, etc)
2360 * I have not found it yet. At this time we depend on the information
2361 * in the type info and the usual order how things are stored.
2363 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2364 * for each member;
2366 * Third is an equal sized array with file offsets to the name entry
2367 * of each member.
2369 * The fourth and last (?) part is an array with offsets to the records
2370 * in the first part of this file segment.
2373 int infolen, nameoffset, reclength, i;
2374 int recoffset = offset + sizeof(INT);
2376 char *recbuf = heap_alloc(0xffff);
2377 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2378 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2380 TRACE_(typelib)("\n");
2382 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2384 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2385 ptfd = *pptfd;
2386 for ( i = 0; i < cFuncs ; i++ )
2388 int optional;
2390 /* name, eventually add to a hash table */
2391 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2392 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2394 /* read the function information record */
2395 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2397 reclength &= 0xffff;
2399 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2401 /* size without argument data */
2402 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2403 if (pFuncRec->FKCCIC & 0x1000)
2404 optional -= pFuncRec->nrargs * sizeof(INT);
2406 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2407 ptfd->helpcontext = pFuncRec->HelpContext;
2409 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2410 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2412 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2414 if (pFuncRec->FKCCIC & 0x2000 )
2416 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2417 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2418 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2420 else
2421 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2423 else
2424 ptfd->Entry = (TLBString*)-1;
2426 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2427 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2429 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2430 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2432 /* fill the FuncDesc Structure */
2433 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2434 offset + infolen + ( i + 1) * sizeof(INT));
2436 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2437 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2438 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2439 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2440 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2441 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2442 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2444 /* nameoffset is sometimes -1 on the second half of a propget/propput
2445 * pair of functions */
2446 if ((nameoffset == -1) && (i > 0) &&
2447 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2448 TLB_is_propgetput(ptfd->funcdesc.invkind))
2449 ptfd->Name = ptfd_prev->Name;
2450 else
2451 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2453 MSFT_GetTdesc(pcx,
2454 pFuncRec->DataType,
2455 &ptfd->funcdesc.elemdescFunc.tdesc);
2457 /* do the parameters/arguments */
2458 if(pFuncRec->nrargs)
2460 int j = 0;
2461 MSFT_ParameterInfo paraminfo;
2463 ptfd->funcdesc.lprgelemdescParam =
2464 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2466 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2468 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2469 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2471 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2473 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2475 MSFT_GetTdesc(pcx,
2476 paraminfo.DataType,
2477 &elemdesc->tdesc);
2479 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2481 /* name */
2482 if (paraminfo.oName != -1)
2483 ptfd->pParamDesc[j].Name =
2484 MSFT_ReadName( pcx, paraminfo.oName );
2485 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2487 /* default value */
2488 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2489 (pFuncRec->FKCCIC & 0x1000) )
2491 INT* pInt = (INT *)((char *)pFuncRec +
2492 reclength -
2493 (pFuncRec->nrargs * 4) * sizeof(INT) );
2495 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2497 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2498 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2500 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2501 pInt[j], pcx);
2503 else
2504 elemdesc->u.paramdesc.pparamdescex = NULL;
2506 /* custom info */
2507 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2508 j*sizeof(pFuncRec->oArgCustData[0])) &&
2509 pFuncRec->FKCCIC & 0x80 )
2511 MSFT_CustData(pcx,
2512 pFuncRec->oArgCustData[j],
2513 &ptfd->pParamDesc[j].custdata_list);
2516 /* SEEK value = jump to offset,
2517 * from there jump to the end of record,
2518 * go back by (j-1) arguments
2520 MSFT_ReadLEDWords( &paraminfo ,
2521 sizeof(MSFT_ParameterInfo), pcx,
2522 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2523 * sizeof(MSFT_ParameterInfo)));
2527 /* scode is not used: archaic win16 stuff FIXME: right? */
2528 ptfd->funcdesc.cScodes = 0 ;
2529 ptfd->funcdesc.lprgscode = NULL ;
2531 ptfd_prev = ptfd;
2532 ++ptfd;
2533 recoffset += reclength;
2535 heap_free(recbuf);
2538 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2539 int cVars, int offset, TLBVarDesc ** pptvd)
2541 int infolen, nameoffset, reclength;
2542 char recbuf[256];
2543 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2544 TLBVarDesc *ptvd;
2545 int i;
2546 int recoffset;
2548 TRACE_(typelib)("\n");
2550 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2551 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2552 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2553 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2554 recoffset += offset+sizeof(INT);
2555 for(i=0;i<cVars;i++, ++ptvd){
2556 /* name, eventually add to a hash table */
2557 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2558 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2559 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2560 /* read the variable information record */
2561 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2562 reclength &= 0xff;
2563 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2565 /* optional data */
2566 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2567 ptvd->HelpContext = pVarRec->HelpContext;
2569 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2570 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2572 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2573 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2575 /* fill the VarDesc Structure */
2576 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2577 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2578 ptvd->vardesc.varkind = pVarRec->VarKind;
2579 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2580 MSFT_GetTdesc(pcx, pVarRec->DataType,
2581 &ptvd->vardesc.elemdescVar.tdesc);
2582 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2583 if(pVarRec->VarKind == VAR_CONST ){
2584 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2585 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2586 pVarRec->OffsValue, pcx);
2587 } else
2588 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2589 recoffset += reclength;
2593 /* process Implemented Interfaces of a com class */
2594 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2595 int offset)
2597 int i;
2598 MSFT_RefRecord refrec;
2599 TLBImplType *pImpl;
2601 TRACE_(typelib)("\n");
2603 pTI->impltypes = TLBImplType_Alloc(count);
2604 pImpl = pTI->impltypes;
2605 for(i=0;i<count;i++){
2606 if(offset<0) break; /* paranoia */
2607 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2608 pImpl->hRef = refrec.reftype;
2609 pImpl->implflags=refrec.flags;
2610 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2611 offset=refrec.onext;
2612 ++pImpl;
2616 #ifdef _WIN64
2617 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2618 * and some structures, and fix the alignment */
2619 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2621 if(info->typeattr.typekind == TKIND_ALIAS){
2622 switch(info->tdescAlias->vt){
2623 case VT_BSTR:
2624 case VT_DISPATCH:
2625 case VT_UNKNOWN:
2626 case VT_PTR:
2627 case VT_SAFEARRAY:
2628 case VT_LPSTR:
2629 case VT_LPWSTR:
2630 info->typeattr.cbSizeInstance = sizeof(void*);
2631 info->typeattr.cbAlignment = sizeof(void*);
2632 break;
2633 case VT_CARRAY:
2634 case VT_USERDEFINED:
2635 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2636 break;
2637 case VT_VARIANT:
2638 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2639 info->typeattr.cbAlignment = 8;
2640 default:
2641 if(info->typeattr.cbSizeInstance < sizeof(void*))
2642 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2643 else
2644 info->typeattr.cbAlignment = sizeof(void*);
2645 break;
2647 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2648 info->typeattr.typekind == TKIND_DISPATCH ||
2649 info->typeattr.typekind == TKIND_COCLASS){
2650 info->typeattr.cbSizeInstance = sizeof(void*);
2651 info->typeattr.cbAlignment = sizeof(void*);
2654 #endif
2657 * process a typeinfo record
2659 static ITypeInfoImpl * MSFT_DoTypeInfo(
2660 TLBContext *pcx,
2661 int count,
2662 ITypeLibImpl * pLibInfo)
2664 MSFT_TypeInfoBase tiBase;
2665 ITypeInfoImpl *ptiRet;
2667 TRACE_(typelib)("count=%u\n", count);
2669 ptiRet = ITypeInfoImpl_Constructor();
2670 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2671 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2673 /* this is where we are coming from */
2674 ptiRet->pTypeLib = pLibInfo;
2675 ptiRet->index=count;
2677 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2678 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2679 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2680 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2681 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2682 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2683 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2684 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2685 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2686 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2687 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2688 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2689 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2690 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2691 TYPEDESC tmp;
2692 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2693 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2694 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2697 /* FIXME: */
2698 /* IDLDESC idldescType; *//* never saw this one != zero */
2700 /* name, eventually add to a hash table */
2701 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2702 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2703 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2704 /* help info */
2705 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2706 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2707 ptiRet->dwHelpContext=tiBase.helpcontext;
2709 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2710 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2712 /* note: InfoType's Help file and HelpStringDll come from the containing
2713 * library. Further HelpString and Docstring appear to be the same thing :(
2715 /* functions */
2716 if(ptiRet->typeattr.cFuncs >0 )
2717 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2718 ptiRet->typeattr.cVars,
2719 tiBase.memoffset, &ptiRet->funcdescs);
2720 /* variables */
2721 if(ptiRet->typeattr.cVars >0 )
2722 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2723 ptiRet->typeattr.cVars,
2724 tiBase.memoffset, &ptiRet->vardescs);
2725 if(ptiRet->typeattr.cImplTypes >0 ) {
2726 switch(ptiRet->typeattr.typekind)
2728 case TKIND_COCLASS:
2729 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2730 tiBase.datatype1);
2731 break;
2732 case TKIND_DISPATCH:
2733 /* This is not -1 when the interface is a non-base dual interface or
2734 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2735 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2736 not this interface.
2739 if (tiBase.datatype1 != -1)
2741 ptiRet->impltypes = TLBImplType_Alloc(1);
2742 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2744 break;
2745 default:
2746 ptiRet->impltypes = TLBImplType_Alloc(1);
2747 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2748 break;
2751 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2753 TRACE_(typelib)("%s guid: %s kind:%s\n",
2754 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2755 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2756 typekind_desc[ptiRet->typeattr.typekind]);
2757 if (TRACE_ON(typelib))
2758 dump_TypeInfo(ptiRet);
2760 return ptiRet;
2763 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2765 char *string;
2766 INT16 len_str, len_piece;
2767 int offs = 0, lengthInChars;
2769 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2770 while (1) {
2771 TLBString *tlbstr;
2773 if (offs >= pcx->pTblDir->pStringtab.length)
2774 return S_OK;
2776 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2777 len_piece = len_str + sizeof(INT16);
2778 if(len_piece % 4)
2779 len_piece = (len_piece + 4) & ~0x3;
2780 if(len_piece < 8)
2781 len_piece = 8;
2783 string = heap_alloc(len_piece + 1);
2784 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2785 string[len_str] = '\0';
2787 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2788 string, -1, NULL, 0);
2789 if (!lengthInChars) {
2790 heap_free(string);
2791 return E_UNEXPECTED;
2794 tlbstr = heap_alloc(sizeof(TLBString));
2796 tlbstr->offset = offs;
2797 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2798 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2800 heap_free(string);
2802 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2804 offs += len_piece;
2808 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2810 TLBRefType *ref;
2811 int offs = 0;
2813 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2814 while (offs < pcx->pTblDir->pImpInfo.length) {
2815 MSFT_ImpInfo impinfo;
2816 TLBImpLib *pImpLib;
2818 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2820 ref = heap_alloc_zero(sizeof(TLBRefType));
2821 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2823 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2824 if(pImpLib->offset==impinfo.oImpFile)
2825 break;
2827 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2828 ref->reference = offs;
2829 ref->pImpTLInfo = pImpLib;
2830 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2831 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2832 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2833 ref->index = TLB_REF_USE_GUID;
2834 } else
2835 ref->index = impinfo.oGuid;
2836 }else{
2837 ERR("Cannot find a reference\n");
2838 ref->reference = -1;
2839 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2842 offs += sizeof(impinfo);
2845 return S_OK;
2848 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2849 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2850 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2851 * tradeoff here.
2853 static struct list tlb_cache = LIST_INIT(tlb_cache);
2854 static CRITICAL_SECTION cache_section;
2855 static CRITICAL_SECTION_DEBUG cache_section_debug =
2857 0, 0, &cache_section,
2858 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2859 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2861 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2864 typedef struct TLB_PEFile
2866 IUnknown IUnknown_iface;
2867 LONG refs;
2868 HMODULE dll;
2869 HRSRC typelib_resource;
2870 HGLOBAL typelib_global;
2871 LPVOID typelib_base;
2872 } TLB_PEFile;
2874 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2876 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2879 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2881 if (IsEqualIID(riid, &IID_IUnknown))
2883 *ppv = iface;
2884 IUnknown_AddRef(iface);
2885 return S_OK;
2887 *ppv = NULL;
2888 return E_NOINTERFACE;
2891 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2893 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2894 return InterlockedIncrement(&This->refs);
2897 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2899 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2900 ULONG refs = InterlockedDecrement(&This->refs);
2901 if (!refs)
2903 if (This->typelib_global)
2904 FreeResource(This->typelib_global);
2905 if (This->dll)
2906 FreeLibrary(This->dll);
2907 heap_free(This);
2909 return refs;
2912 static const IUnknownVtbl TLB_PEFile_Vtable =
2914 TLB_PEFile_QueryInterface,
2915 TLB_PEFile_AddRef,
2916 TLB_PEFile_Release
2919 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2921 TLB_PEFile *This;
2922 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2924 This = heap_alloc(sizeof(TLB_PEFile));
2925 if (!This)
2926 return E_OUTOFMEMORY;
2928 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2929 This->refs = 1;
2930 This->dll = NULL;
2931 This->typelib_resource = NULL;
2932 This->typelib_global = NULL;
2933 This->typelib_base = NULL;
2935 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2936 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2938 if (This->dll)
2940 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2941 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2942 if (This->typelib_resource)
2944 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2945 if (This->typelib_global)
2947 This->typelib_base = LockResource(This->typelib_global);
2949 if (This->typelib_base)
2951 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2952 *ppBase = This->typelib_base;
2953 *ppFile = &This->IUnknown_iface;
2954 return S_OK;
2959 TRACE("No TYPELIB resource found\n");
2960 hr = E_FAIL;
2963 TLB_PEFile_Release(&This->IUnknown_iface);
2964 return hr;
2967 typedef struct TLB_NEFile
2969 IUnknown IUnknown_iface;
2970 LONG refs;
2971 LPVOID typelib_base;
2972 } TLB_NEFile;
2974 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2976 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2979 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2981 if (IsEqualIID(riid, &IID_IUnknown))
2983 *ppv = iface;
2984 IUnknown_AddRef(iface);
2985 return S_OK;
2987 *ppv = NULL;
2988 return E_NOINTERFACE;
2991 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2993 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2994 return InterlockedIncrement(&This->refs);
2997 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2999 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
3000 ULONG refs = InterlockedDecrement(&This->refs);
3001 if (!refs)
3003 heap_free(This->typelib_base);
3004 heap_free(This);
3006 return refs;
3009 static const IUnknownVtbl TLB_NEFile_Vtable =
3011 TLB_NEFile_QueryInterface,
3012 TLB_NEFile_AddRef,
3013 TLB_NEFile_Release
3016 /***********************************************************************
3017 * read_xx_header [internal]
3019 static int read_xx_header( HFILE lzfd )
3021 IMAGE_DOS_HEADER mzh;
3022 char magic[3];
3024 LZSeek( lzfd, 0, SEEK_SET );
3025 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3026 return 0;
3027 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3028 return 0;
3030 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3031 if ( 2 != LZRead( lzfd, magic, 2 ) )
3032 return 0;
3034 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3036 if ( magic[0] == 'N' && magic[1] == 'E' )
3037 return IMAGE_OS2_SIGNATURE;
3038 if ( magic[0] == 'P' && magic[1] == 'E' )
3039 return IMAGE_NT_SIGNATURE;
3041 magic[2] = '\0';
3042 WARN("Can't handle %s files.\n", magic );
3043 return 0;
3047 /***********************************************************************
3048 * find_ne_resource [internal]
3050 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3051 DWORD *resLen, DWORD *resOff )
3053 IMAGE_OS2_HEADER nehd;
3054 NE_TYPEINFO *typeInfo;
3055 NE_NAMEINFO *nameInfo;
3056 DWORD nehdoffset;
3057 LPBYTE resTab;
3058 DWORD resTabSize;
3059 int count;
3061 /* Read in NE header */
3062 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3063 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3065 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3066 if ( !resTabSize )
3068 TRACE("No resources in NE dll\n" );
3069 return FALSE;
3072 /* Read in resource table */
3073 resTab = heap_alloc( resTabSize );
3074 if ( !resTab ) return FALSE;
3076 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3077 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3079 heap_free( resTab );
3080 return FALSE;
3083 /* Find resource */
3084 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3086 if (!IS_INTRESOURCE(typeid)) /* named type */
3088 BYTE len = strlen( typeid );
3089 while (typeInfo->type_id)
3091 if (!(typeInfo->type_id & 0x8000))
3093 BYTE *p = resTab + typeInfo->type_id;
3094 if ((*p == len) && !_strnicmp( (char*)p+1, typeid, len )) goto found_type;
3096 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3097 typeInfo->count * sizeof(NE_NAMEINFO));
3100 else /* numeric type id */
3102 WORD id = LOWORD(typeid) | 0x8000;
3103 while (typeInfo->type_id)
3105 if (typeInfo->type_id == id) goto found_type;
3106 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3107 typeInfo->count * sizeof(NE_NAMEINFO));
3110 TRACE("No typeid entry found for %p\n", typeid );
3111 heap_free( resTab );
3112 return FALSE;
3114 found_type:
3115 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3117 if (!IS_INTRESOURCE(resid)) /* named resource */
3119 BYTE len = strlen( resid );
3120 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3122 BYTE *p = resTab + nameInfo->id;
3123 if (nameInfo->id & 0x8000) continue;
3124 if ((*p == len) && !_strnicmp( (char*)p+1, resid, len )) goto found_name;
3127 else /* numeric resource id */
3129 WORD id = LOWORD(resid) | 0x8000;
3130 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3131 if (nameInfo->id == id) goto found_name;
3133 TRACE("No resid entry found for %p\n", typeid );
3134 heap_free( resTab );
3135 return FALSE;
3137 found_name:
3138 /* Return resource data */
3139 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3140 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3142 heap_free( resTab );
3143 return TRUE;
3146 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3148 HFILE lzfd = -1;
3149 OFSTRUCT ofs;
3150 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3151 TLB_NEFile *This;
3153 This = heap_alloc(sizeof(TLB_NEFile));
3154 if (!This) return E_OUTOFMEMORY;
3156 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3157 This->refs = 1;
3158 This->typelib_base = NULL;
3160 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3161 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3163 DWORD reslen, offset;
3164 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3166 This->typelib_base = heap_alloc(reslen);
3167 if( !This->typelib_base )
3168 hr = E_OUTOFMEMORY;
3169 else
3171 LZSeek( lzfd, offset, SEEK_SET );
3172 reslen = LZRead( lzfd, This->typelib_base, reslen );
3173 LZClose( lzfd );
3174 *ppBase = This->typelib_base;
3175 *pdwTLBLength = reslen;
3176 *ppFile = &This->IUnknown_iface;
3177 return S_OK;
3182 if( lzfd >= 0) LZClose( lzfd );
3183 TLB_NEFile_Release(&This->IUnknown_iface);
3184 return hr;
3187 typedef struct TLB_Mapping
3189 IUnknown IUnknown_iface;
3190 LONG refs;
3191 HANDLE file;
3192 HANDLE mapping;
3193 LPVOID typelib_base;
3194 } TLB_Mapping;
3196 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3198 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3201 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3203 if (IsEqualIID(riid, &IID_IUnknown))
3205 *ppv = iface;
3206 IUnknown_AddRef(iface);
3207 return S_OK;
3209 *ppv = NULL;
3210 return E_NOINTERFACE;
3213 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3215 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3216 return InterlockedIncrement(&This->refs);
3219 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3221 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3222 ULONG refs = InterlockedDecrement(&This->refs);
3223 if (!refs)
3225 if (This->typelib_base)
3226 UnmapViewOfFile(This->typelib_base);
3227 if (This->mapping)
3228 CloseHandle(This->mapping);
3229 if (This->file != INVALID_HANDLE_VALUE)
3230 CloseHandle(This->file);
3231 heap_free(This);
3233 return refs;
3236 static const IUnknownVtbl TLB_Mapping_Vtable =
3238 TLB_Mapping_QueryInterface,
3239 TLB_Mapping_AddRef,
3240 TLB_Mapping_Release
3243 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3245 TLB_Mapping *This;
3247 This = heap_alloc(sizeof(TLB_Mapping));
3248 if (!This)
3249 return E_OUTOFMEMORY;
3251 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3252 This->refs = 1;
3253 This->file = INVALID_HANDLE_VALUE;
3254 This->mapping = NULL;
3255 This->typelib_base = NULL;
3257 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3258 if (INVALID_HANDLE_VALUE != This->file)
3260 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3261 if (This->mapping)
3263 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3264 if(This->typelib_base)
3266 /* retrieve file size */
3267 *pdwTLBLength = GetFileSize(This->file, NULL);
3268 *ppBase = This->typelib_base;
3269 *ppFile = &This->IUnknown_iface;
3270 return S_OK;
3275 IUnknown_Release(&This->IUnknown_iface);
3276 return TYPE_E_CANTLOADLIBRARY;
3279 /****************************************************************************
3280 * TLB_ReadTypeLib
3282 * find the type of the typelib file and map the typelib resource into
3283 * the memory
3286 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3289 ITypeLibImpl *entry;
3290 HRESULT ret;
3291 INT index = 1;
3292 LPWSTR index_str, file = (LPWSTR)pszFileName;
3293 LPVOID pBase = NULL;
3294 DWORD dwTLBLength = 0;
3295 IUnknown *pFile = NULL;
3296 HANDLE h;
3298 *ppTypeLib = NULL;
3300 index_str = strrchrW(pszFileName, '\\');
3301 if(index_str && *++index_str != '\0')
3303 LPWSTR end_ptr;
3304 LONG idx = strtolW(index_str, &end_ptr, 10);
3305 if(*end_ptr == '\0')
3307 int str_len = index_str - pszFileName - 1;
3308 index = idx;
3309 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3310 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3311 file[str_len] = 0;
3315 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3317 if(strchrW(file, '\\'))
3319 lstrcpyW(pszPath, file);
3321 else
3323 int len = GetSystemDirectoryW(pszPath, cchPath);
3324 pszPath[len] = '\\';
3325 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3329 if(file != pszFileName) heap_free(file);
3331 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3332 if(h != INVALID_HANDLE_VALUE){
3333 FILE_NAME_INFORMATION size_info;
3334 BOOL br;
3336 /* GetFileInformationByHandleEx returns the path of the file without
3337 * WOW64 redirection */
3338 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3339 if(br || GetLastError() == ERROR_MORE_DATA){
3340 FILE_NAME_INFORMATION *info;
3341 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3343 info = HeapAlloc(GetProcessHeap(), 0, size);
3345 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3346 if(br){
3347 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3348 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3351 HeapFree(GetProcessHeap(), 0, info);
3354 CloseHandle(h);
3357 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3359 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3360 EnterCriticalSection(&cache_section);
3361 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3363 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3365 TRACE("cache hit\n");
3366 *ppTypeLib = &entry->ITypeLib2_iface;
3367 ITypeLib2_AddRef(*ppTypeLib);
3368 LeaveCriticalSection(&cache_section);
3369 return S_OK;
3372 LeaveCriticalSection(&cache_section);
3374 /* now actually load and parse the typelib */
3376 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3377 if (ret == TYPE_E_CANTLOADLIBRARY)
3378 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3379 if (ret == TYPE_E_CANTLOADLIBRARY)
3380 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3381 if (SUCCEEDED(ret))
3383 if (dwTLBLength >= 4)
3385 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3386 if (dwSignature == MSFT_SIGNATURE)
3387 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3388 else if (dwSignature == SLTG_SIGNATURE)
3389 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3390 else
3392 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3393 ret = TYPE_E_CANTLOADLIBRARY;
3396 else
3397 ret = TYPE_E_CANTLOADLIBRARY;
3398 IUnknown_Release(pFile);
3401 if(*ppTypeLib) {
3402 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3404 TRACE("adding to cache\n");
3405 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3406 lstrcpyW(impl->path, pszPath);
3407 /* We should really canonicalise the path here. */
3408 impl->index = index;
3410 /* FIXME: check if it has added already in the meantime */
3411 EnterCriticalSection(&cache_section);
3412 list_add_head(&tlb_cache, &impl->entry);
3413 LeaveCriticalSection(&cache_section);
3414 ret = S_OK;
3416 else
3418 if(ret != E_FAIL)
3419 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3421 ret = TYPE_E_CANTLOADLIBRARY;
3425 return ret;
3428 /*================== ITypeLib(2) Methods ===================================*/
3430 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3432 ITypeLibImpl* pTypeLibImpl;
3434 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3435 if (!pTypeLibImpl) return NULL;
3437 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3438 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3439 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3440 pTypeLibImpl->ref = 1;
3442 list_init(&pTypeLibImpl->implib_list);
3443 list_init(&pTypeLibImpl->custdata_list);
3444 list_init(&pTypeLibImpl->name_list);
3445 list_init(&pTypeLibImpl->string_list);
3446 list_init(&pTypeLibImpl->guid_list);
3447 list_init(&pTypeLibImpl->ref_list);
3448 pTypeLibImpl->dispatch_href = -1;
3450 return pTypeLibImpl;
3453 /****************************************************************************
3454 * ITypeLib2_Constructor_MSFT
3456 * loading an MSFT typelib from an in-memory image
3458 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3460 TLBContext cx;
3461 LONG lPSegDir;
3462 MSFT_Header tlbHeader;
3463 MSFT_SegDir tlbSegDir;
3464 ITypeLibImpl * pTypeLibImpl;
3465 int i;
3467 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3469 pTypeLibImpl = TypeLibImpl_Constructor();
3470 if (!pTypeLibImpl) return NULL;
3472 /* get pointer to beginning of typelib data */
3473 cx.pos = 0;
3474 cx.oStart=0;
3475 cx.mapping = pLib;
3476 cx.pLibInfo = pTypeLibImpl;
3477 cx.length = dwTLBLength;
3479 /* read header */
3480 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3481 TRACE_(typelib)("header:\n");
3482 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3483 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3484 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3485 return NULL;
3487 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3489 /* there is a small amount of information here until the next important
3490 * part:
3491 * the segment directory . Try to calculate the amount of data */
3492 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3494 /* now read the segment directory */
3495 TRACE("read segment directory (at %d)\n",lPSegDir);
3496 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3497 cx.pTblDir = &tlbSegDir;
3499 /* just check two entries */
3500 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3502 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3503 heap_free(pTypeLibImpl);
3504 return NULL;
3507 MSFT_ReadAllNames(&cx);
3508 MSFT_ReadAllStrings(&cx);
3509 MSFT_ReadAllGuids(&cx);
3511 /* now fill our internal data */
3512 /* TLIBATTR fields */
3513 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3515 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3516 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3517 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3518 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3519 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3521 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3522 pTypeLibImpl->lcid = tlbHeader.lcid;
3524 /* name, eventually add to a hash table */
3525 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3527 /* help info */
3528 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3529 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3531 if( tlbHeader.varflags & HELPDLLFLAG)
3533 int offset;
3534 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3535 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3538 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3540 /* custom data */
3541 if(tlbHeader.CustomDataOffset >= 0)
3543 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3546 /* fill in type descriptions */
3547 if(tlbSegDir.pTypdescTab.length > 0)
3549 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3550 INT16 td[4];
3551 pTypeLibImpl->ctTypeDesc = cTD;
3552 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3553 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3554 for(i=0; i<cTD; )
3556 /* FIXME: add several sanity checks here */
3557 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3558 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3560 /* FIXME: check safearray */
3561 if(td[3] < 0)
3562 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3563 else
3564 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3566 else if(td[0] == VT_CARRAY)
3568 /* array descr table here */
3569 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3571 else if(td[0] == VT_USERDEFINED)
3573 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3575 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3578 /* second time around to fill the array subscript info */
3579 for(i=0;i<cTD;i++)
3581 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3582 if(tlbSegDir.pArrayDescriptions.offset>0)
3584 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3585 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3587 if(td[1]<0)
3588 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3589 else
3590 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3592 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3594 for(j = 0; j<td[2]; j++)
3596 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3597 sizeof(INT), &cx, DO_NOT_SEEK);
3598 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3599 sizeof(INT), &cx, DO_NOT_SEEK);
3602 else
3604 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3605 ERR("didn't find array description data\n");
3610 /* imported type libs */
3611 if(tlbSegDir.pImpFiles.offset>0)
3613 TLBImpLib *pImpLib;
3614 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3615 UINT16 size;
3617 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3619 char *name;
3621 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3622 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3623 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3625 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3626 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3627 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3628 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3630 size >>= 2;
3631 name = heap_alloc_zero(size+1);
3632 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3633 pImpLib->name = TLB_MultiByteToBSTR(name);
3634 heap_free(name);
3636 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3637 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3639 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3643 MSFT_ReadAllRefs(&cx);
3645 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3647 /* type infos */
3648 if(tlbHeader.nrtypeinfos >= 0 )
3650 ITypeInfoImpl **ppTI;
3652 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3654 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3656 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3658 ++ppTI;
3659 (pTypeLibImpl->TypeInfoCount)++;
3663 #ifdef _WIN64
3664 if(pTypeLibImpl->syskind == SYS_WIN32){
3665 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3666 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3668 #endif
3670 TRACE("(%p)\n", pTypeLibImpl);
3671 return &pTypeLibImpl->ITypeLib2_iface;
3675 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3677 char b[3];
3678 int i;
3679 short s;
3681 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3682 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3683 return FALSE;
3686 guid->Data4[0] = s >> 8;
3687 guid->Data4[1] = s & 0xff;
3689 b[2] = '\0';
3690 for(i = 0; i < 6; i++) {
3691 memcpy(b, str + 24 + 2 * i, 2);
3692 guid->Data4[i + 2] = strtol(b, NULL, 16);
3694 return TRUE;
3697 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3699 WORD bytelen;
3700 DWORD len;
3701 BSTR tmp_str;
3703 *pStr = NULL;
3704 bytelen = *(const WORD*)ptr;
3705 if(bytelen == 0xffff) return 2;
3707 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3708 tmp_str = SysAllocStringLen(NULL, len);
3709 if (tmp_str) {
3710 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3711 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3712 SysFreeString(tmp_str);
3714 return bytelen + 2;
3717 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3719 WORD bytelen;
3721 *str = NULL;
3722 bytelen = *(const WORD*)ptr;
3723 if(bytelen == 0xffff) return 2;
3724 *str = heap_alloc(bytelen + 1);
3725 memcpy(*str, ptr + 2, bytelen);
3726 (*str)[bytelen] = '\0';
3727 return bytelen + 2;
3730 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3732 BSTR tmp_str;
3733 TLBString *tlbstr;
3735 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3736 if (tlbstr->offset == offset)
3737 return tlbstr;
3740 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3741 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3742 SysFreeString(tmp_str);
3744 return tlbstr;
3747 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3749 char *ptr = pLibBlk;
3750 WORD w;
3752 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3753 FIXME("libblk magic = %04x\n", w);
3754 return 0;
3757 ptr += 6;
3758 if((w = *(WORD*)ptr) != 0xffff) {
3759 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3760 ptr += w;
3762 ptr += 2;
3764 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3766 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3768 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3769 ptr += 4;
3771 pTypeLibImpl->syskind = *(WORD*)ptr;
3772 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3773 ptr += 2;
3775 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3776 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3777 else
3778 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3779 ptr += 2;
3781 ptr += 4; /* skip res12 */
3783 pTypeLibImpl->libflags = *(WORD*)ptr;
3784 ptr += 2;
3786 pTypeLibImpl->ver_major = *(WORD*)ptr;
3787 ptr += 2;
3789 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3790 ptr += 2;
3792 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3793 ptr += sizeof(GUID);
3795 return ptr - (char*)pLibBlk;
3798 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3799 typedef struct
3801 unsigned int num;
3802 HREFTYPE refs[1];
3803 } sltg_ref_lookup_t;
3805 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3806 HREFTYPE *typelib_ref)
3808 if(table && typeinfo_ref < table->num)
3810 *typelib_ref = table->refs[typeinfo_ref];
3811 return S_OK;
3814 ERR_(typelib)("Unable to find reference\n");
3815 *typelib_ref = -1;
3816 return E_FAIL;
3819 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3821 BOOL done = FALSE;
3823 while(!done) {
3824 if((*pType & 0xe00) == 0xe00) {
3825 pTD->vt = VT_PTR;
3826 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3827 pTD = pTD->u.lptdesc;
3829 switch(*pType & 0x3f) {
3830 case VT_PTR:
3831 pTD->vt = VT_PTR;
3832 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3833 pTD = pTD->u.lptdesc;
3834 break;
3836 case VT_USERDEFINED:
3837 pTD->vt = VT_USERDEFINED;
3838 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3839 done = TRUE;
3840 break;
3842 case VT_CARRAY:
3844 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3845 array */
3847 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3849 pTD->vt = VT_CARRAY;
3850 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3851 pTD->u.lpadesc->cDims = pSA->cDims;
3852 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3853 pSA->cDims * sizeof(SAFEARRAYBOUND));
3855 pTD = &pTD->u.lpadesc->tdescElem;
3856 break;
3859 case VT_SAFEARRAY:
3861 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3862 useful? */
3864 pType++;
3865 pTD->vt = VT_SAFEARRAY;
3866 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3867 pTD = pTD->u.lptdesc;
3868 break;
3870 default:
3871 pTD->vt = *pType & 0x3f;
3872 done = TRUE;
3873 break;
3875 pType++;
3877 return pType;
3880 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3881 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3883 /* Handle [in/out] first */
3884 if((*pType & 0xc000) == 0xc000)
3885 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3886 else if(*pType & 0x8000)
3887 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3888 else if(*pType & 0x4000)
3889 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3890 else
3891 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3893 if(*pType & 0x2000)
3894 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3896 if(*pType & 0x80)
3897 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3899 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3903 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3904 char *pNameTable)
3906 unsigned int ref;
3907 char *name;
3908 TLBRefType *ref_type;
3909 sltg_ref_lookup_t *table;
3910 HREFTYPE typelib_ref;
3912 if(pRef->magic != SLTG_REF_MAGIC) {
3913 FIXME("Ref magic = %x\n", pRef->magic);
3914 return NULL;
3916 name = ( (char*)pRef->names + pRef->number);
3918 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3919 table->num = pRef->number >> 3;
3921 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3923 /* We don't want the first href to be 0 */
3924 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3926 for(ref = 0; ref < pRef->number >> 3; ref++) {
3927 char *refname;
3928 unsigned int lib_offs, type_num;
3930 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3932 name += SLTG_ReadStringA(name, &refname);
3933 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3934 FIXME_(typelib)("Can't sscanf ref\n");
3935 if(lib_offs != 0xffff) {
3936 TLBImpLib *import;
3938 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3939 if(import->offset == lib_offs)
3940 break;
3942 if(&import->entry == &pTL->implib_list) {
3943 char fname[MAX_PATH+1];
3944 int len;
3945 GUID tmpguid;
3947 import = heap_alloc_zero(sizeof(*import));
3948 import->offset = lib_offs;
3949 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3950 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3951 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3952 &import->wVersionMajor,
3953 &import->wVersionMinor,
3954 &import->lcid, fname) != 4) {
3955 FIXME_(typelib)("can't sscanf ref %s\n",
3956 pNameTable + lib_offs + 40);
3958 len = strlen(fname);
3959 if(fname[len-1] != '#')
3960 FIXME("fname = %s\n", fname);
3961 fname[len-1] = '\0';
3962 import->name = TLB_MultiByteToBSTR(fname);
3963 list_add_tail(&pTL->implib_list, &import->entry);
3965 ref_type->pImpTLInfo = import;
3967 /* Store a reference to IDispatch */
3968 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3969 pTL->dispatch_href = typelib_ref;
3971 } else { /* internal ref */
3972 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3974 ref_type->reference = typelib_ref;
3975 ref_type->index = type_num;
3977 heap_free(refname);
3978 list_add_tail(&pTL->ref_list, &ref_type->entry);
3980 table->refs[ref] = typelib_ref;
3981 typelib_ref += 4;
3983 if((BYTE)*name != SLTG_REF_MAGIC)
3984 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3985 dump_TLBRefType(pTL);
3986 return table;
3989 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3990 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3992 SLTG_ImplInfo *info;
3993 TLBImplType *pImplType;
3994 /* I don't really get this structure, usually it's 0x16 bytes
3995 long, but iuser.tlb contains some that are 0x18 bytes long.
3996 That's ok because we can use the next ptr to jump to the next
3997 one. But how do we know the length of the last one? The WORD
3998 at offs 0x8 might be the clue. For now I'm just assuming that
3999 the last one is the regular 0x16 bytes. */
4001 info = (SLTG_ImplInfo*)pBlk;
4002 while(1){
4003 pTI->typeattr.cImplTypes++;
4004 if(info->next == 0xffff)
4005 break;
4006 info = (SLTG_ImplInfo*)(pBlk + info->next);
4009 info = (SLTG_ImplInfo*)pBlk;
4010 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4011 pImplType = pTI->impltypes;
4012 while(1) {
4013 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4014 pImplType->implflags = info->impltypeflags;
4015 ++pImplType;
4017 if(info->next == 0xffff)
4018 break;
4019 if(OneOnly)
4020 FIXME_(typelib)("Interface inheriting more than one interface\n");
4021 info = (SLTG_ImplInfo*)(pBlk + info->next);
4023 info++; /* see comment at top of function */
4024 return (char*)info;
4027 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4028 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4030 TLBVarDesc *pVarDesc;
4031 const TLBString *prevName = NULL;
4032 SLTG_Variable *pItem;
4033 unsigned short i;
4034 WORD *pType;
4036 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4038 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4039 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4041 pVarDesc->vardesc.memid = pItem->memid;
4043 if (pItem->magic != SLTG_VAR_MAGIC &&
4044 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4045 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4046 return;
4049 if (pItem->name == 0xfffe)
4050 pVarDesc->Name = prevName;
4051 else
4052 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4054 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4055 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4056 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4058 if(pItem->flags & 0x02)
4059 pType = &pItem->type;
4060 else
4061 pType = (WORD*)(pBlk + pItem->type);
4063 if (pItem->flags & ~0xda)
4064 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4066 SLTG_DoElem(pType, pBlk,
4067 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4069 if (TRACE_ON(typelib)) {
4070 char buf[300];
4071 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4072 TRACE_(typelib)("elemdescVar: %s\n", buf);
4075 if (pItem->flags & 0x40) {
4076 TRACE_(typelib)("VAR_DISPATCH\n");
4077 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4079 else if (pItem->flags & 0x10) {
4080 TRACE_(typelib)("VAR_CONST\n");
4081 pVarDesc->vardesc.varkind = VAR_CONST;
4082 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4083 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4084 if (pItem->flags & 0x08)
4085 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4086 else {
4087 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4089 case VT_LPSTR:
4090 case VT_LPWSTR:
4091 case VT_BSTR:
4093 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4094 BSTR str;
4095 TRACE_(typelib)("len = %u\n", len);
4096 if (len == 0xffff) {
4097 str = NULL;
4098 } else {
4099 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4100 str = SysAllocStringLen(NULL, alloc_len);
4101 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4103 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4104 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4105 break;
4107 case VT_I2:
4108 case VT_UI2:
4109 case VT_I4:
4110 case VT_UI4:
4111 case VT_INT:
4112 case VT_UINT:
4113 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4114 *(INT*)(pBlk + pItem->byte_offs);
4115 break;
4116 default:
4117 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4121 else {
4122 TRACE_(typelib)("VAR_PERINSTANCE\n");
4123 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4124 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4127 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4128 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4130 if (pItem->flags & 0x80)
4131 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4133 prevName = pVarDesc->Name;
4135 pTI->typeattr.cVars = cVars;
4138 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4139 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4141 SLTG_Function *pFunc;
4142 unsigned short i;
4143 TLBFuncDesc *pFuncDesc;
4145 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4147 pFuncDesc = pTI->funcdescs;
4148 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4149 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4151 int param;
4152 WORD *pType, *pArg;
4154 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4155 case SLTG_FUNCTION_MAGIC:
4156 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4157 break;
4158 case SLTG_DISPATCH_FUNCTION_MAGIC:
4159 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4160 break;
4161 case SLTG_STATIC_FUNCTION_MAGIC:
4162 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4163 break;
4164 default:
4165 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4166 continue;
4168 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4170 pFuncDesc->funcdesc.memid = pFunc->dispid;
4171 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4172 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4173 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4174 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4175 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4177 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4178 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4180 if(pFunc->retnextopt & 0x80)
4181 pType = &pFunc->rettype;
4182 else
4183 pType = (WORD*)(pBlk + pFunc->rettype);
4185 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4187 pFuncDesc->funcdesc.lprgelemdescParam =
4188 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4189 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4191 pArg = (WORD*)(pBlk + pFunc->arg_off);
4193 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4194 char *paramName = pNameTable + *pArg;
4195 BOOL HaveOffs;
4196 /* If arg type follows then paramName points to the 2nd
4197 letter of the name, else the next WORD is an offset to
4198 the arg type and paramName points to the first letter.
4199 So let's take one char off paramName and see if we're
4200 pointing at an alpha-numeric char. However if *pArg is
4201 0xffff or 0xfffe then the param has no name, the former
4202 meaning that the next WORD is the type, the latter
4203 meaning that the next WORD is an offset to the type. */
4205 HaveOffs = FALSE;
4206 if(*pArg == 0xffff)
4207 paramName = NULL;
4208 else if(*pArg == 0xfffe) {
4209 paramName = NULL;
4210 HaveOffs = TRUE;
4212 else if(paramName[-1] && !isalnum(paramName[-1]))
4213 HaveOffs = TRUE;
4215 pArg++;
4217 if(HaveOffs) { /* the next word is an offset to type */
4218 pType = (WORD*)(pBlk + *pArg);
4219 SLTG_DoElem(pType, pBlk,
4220 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4221 pArg++;
4222 } else {
4223 if(paramName)
4224 paramName--;
4225 pArg = SLTG_DoElem(pArg, pBlk,
4226 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4229 /* Are we an optional param ? */
4230 if(pFuncDesc->funcdesc.cParams - param <=
4231 pFuncDesc->funcdesc.cParamsOpt)
4232 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4234 if(paramName) {
4235 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4236 paramName - pNameTable, pTI->pTypeLib);
4237 } else {
4238 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4242 pTI->typeattr.cFuncs = cFuncs;
4245 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4246 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4247 SLTG_TypeInfoTail *pTITail)
4249 char *pFirstItem;
4250 sltg_ref_lookup_t *ref_lookup = NULL;
4252 if(pTIHeader->href_table != 0xffffffff) {
4253 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4254 pNameTable);
4257 pFirstItem = pBlk;
4259 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4260 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4262 heap_free(ref_lookup);
4266 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4267 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4268 const SLTG_TypeInfoTail *pTITail)
4270 char *pFirstItem;
4271 sltg_ref_lookup_t *ref_lookup = NULL;
4273 if(pTIHeader->href_table != 0xffffffff) {
4274 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4275 pNameTable);
4278 pFirstItem = pBlk;
4280 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4281 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4284 if (pTITail->funcs_off != 0xffff)
4285 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4287 heap_free(ref_lookup);
4289 if (TRACE_ON(typelib))
4290 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4293 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4294 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4295 const SLTG_TypeInfoTail *pTITail)
4297 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4300 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4301 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4302 const SLTG_TypeInfoTail *pTITail)
4304 WORD *pType;
4305 sltg_ref_lookup_t *ref_lookup = NULL;
4307 if (pTITail->simple_alias) {
4308 /* if simple alias, no more processing required */
4309 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4310 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4311 return;
4314 if(pTIHeader->href_table != 0xffffffff) {
4315 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4316 pNameTable);
4319 /* otherwise it is an offset to a type */
4320 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4322 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4323 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4325 heap_free(ref_lookup);
4328 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4329 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4330 const SLTG_TypeInfoTail *pTITail)
4332 sltg_ref_lookup_t *ref_lookup = NULL;
4333 if (pTIHeader->href_table != 0xffffffff)
4334 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4335 pNameTable);
4337 if (pTITail->vars_off != 0xffff)
4338 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4340 if (pTITail->funcs_off != 0xffff)
4341 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4343 if (pTITail->impls_off != 0xffff)
4344 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4346 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4347 * of dispinterface functions including the IDispatch ones, so
4348 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4349 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4351 heap_free(ref_lookup);
4352 if (TRACE_ON(typelib))
4353 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4356 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4357 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4358 const SLTG_TypeInfoTail *pTITail)
4360 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4363 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4364 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4365 const SLTG_TypeInfoTail *pTITail)
4367 sltg_ref_lookup_t *ref_lookup = NULL;
4368 if (pTIHeader->href_table != 0xffffffff)
4369 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4370 pNameTable);
4372 if (pTITail->vars_off != 0xffff)
4373 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4375 if (pTITail->funcs_off != 0xffff)
4376 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4377 heap_free(ref_lookup);
4378 if (TRACE_ON(typelib))
4379 dump_TypeInfo(pTI);
4382 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4383 manageable copy of it into this */
4384 typedef struct {
4385 WORD small_no;
4386 char *index_name;
4387 char *other_name;
4388 WORD res1a;
4389 WORD name_offs;
4390 WORD more_bytes;
4391 char *extra;
4392 WORD res20;
4393 DWORD helpcontext;
4394 WORD res26;
4395 GUID uuid;
4396 } SLTG_InternalOtherTypeInfo;
4398 /****************************************************************************
4399 * ITypeLib2_Constructor_SLTG
4401 * loading a SLTG typelib from an in-memory image
4403 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4405 ITypeLibImpl *pTypeLibImpl;
4406 SLTG_Header *pHeader;
4407 SLTG_BlkEntry *pBlkEntry;
4408 SLTG_Magic *pMagic;
4409 SLTG_Index *pIndex;
4410 SLTG_Pad9 *pPad9;
4411 LPVOID pBlk, pFirstBlk;
4412 SLTG_LibBlk *pLibBlk;
4413 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4414 char *pAfterOTIBlks = NULL;
4415 char *pNameTable, *ptr;
4416 int i;
4417 DWORD len, order;
4418 ITypeInfoImpl **ppTypeInfoImpl;
4420 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4423 pTypeLibImpl = TypeLibImpl_Constructor();
4424 if (!pTypeLibImpl) return NULL;
4426 pHeader = pLib;
4428 TRACE_(typelib)("header:\n");
4429 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4430 pHeader->nrOfFileBlks );
4431 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4432 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4433 pHeader->SLTG_magic);
4434 return NULL;
4437 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4438 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4440 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4441 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4443 /* Next we have a magic block */
4444 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4446 /* Let's see if we're still in sync */
4447 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4448 sizeof(SLTG_COMPOBJ_MAGIC))) {
4449 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4450 return NULL;
4452 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4453 sizeof(SLTG_DIR_MAGIC))) {
4454 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4455 return NULL;
4458 pIndex = (SLTG_Index*)(pMagic+1);
4460 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4462 pFirstBlk = pPad9 + 1;
4464 /* We'll set up a ptr to the main library block, which is the last one. */
4466 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4467 pBlkEntry[order].next != 0;
4468 order = pBlkEntry[order].next - 1) {
4469 pBlk = (char*)pBlk + pBlkEntry[order].len;
4471 pLibBlk = pBlk;
4473 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4475 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4476 interspersed */
4478 len += 0x40;
4480 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4482 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4485 ptr = (char*)pLibBlk + len;
4487 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4488 WORD w, extra;
4489 len = 0;
4491 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4493 w = *(WORD*)(ptr + 2);
4494 if(w != 0xffff) {
4495 len += w;
4496 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4497 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4498 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4500 w = *(WORD*)(ptr + 4 + len);
4501 if(w != 0xffff) {
4502 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4503 len += w;
4504 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4505 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4506 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4508 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4509 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4510 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4511 if(extra) {
4512 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4513 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4514 len += extra;
4516 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4517 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4518 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4519 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4520 len += sizeof(SLTG_OtherTypeInfo);
4521 ptr += len;
4524 pAfterOTIBlks = ptr;
4526 /* Skip this WORD and get the next DWORD */
4527 len = *(DWORD*)(pAfterOTIBlks + 2);
4529 /* Now add this to pLibBLk look at what we're pointing at and
4530 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4531 dust and we should be pointing at the beginning of the name
4532 table */
4534 pNameTable = (char*)pLibBlk + len;
4536 switch(*(WORD*)pNameTable) {
4537 case 0xffff:
4538 break;
4539 case 0x0200:
4540 pNameTable += 0x20;
4541 break;
4542 default:
4543 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4544 break;
4547 pNameTable += 0x216;
4549 pNameTable += 2;
4551 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4553 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4556 /* Hopefully we now have enough ptrs set up to actually read in
4557 some TypeInfos. It's not clear which order to do them in, so
4558 I'll just follow the links along the BlkEntry chain and read
4559 them in the order in which they are in the file */
4561 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4562 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4564 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4565 pBlkEntry[order].next != 0;
4566 order = pBlkEntry[order].next - 1, i++) {
4568 SLTG_TypeInfoHeader *pTIHeader;
4569 SLTG_TypeInfoTail *pTITail;
4570 SLTG_MemberHeader *pMemHeader;
4572 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4573 FIXME_(typelib)("Index strings don't match\n");
4574 heap_free(pOtherTypeInfoBlks);
4575 return NULL;
4578 pTIHeader = pBlk;
4579 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4580 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4581 heap_free(pOtherTypeInfoBlks);
4582 return NULL;
4584 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4585 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4586 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4588 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4589 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4590 (*ppTypeInfoImpl)->index = i;
4591 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4592 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4593 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4594 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4595 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4596 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4597 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4598 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4600 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4601 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4603 if((pTIHeader->typeflags1 & 7) != 2)
4604 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4605 if(pTIHeader->typeflags3 != 2)
4606 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4608 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4609 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4610 typekind_desc[pTIHeader->typekind],
4611 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4612 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4614 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4616 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4618 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4619 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4620 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4622 switch(pTIHeader->typekind) {
4623 case TKIND_ENUM:
4624 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4625 pTIHeader, pTITail);
4626 break;
4628 case TKIND_RECORD:
4629 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4630 pTIHeader, pTITail);
4631 break;
4633 case TKIND_INTERFACE:
4634 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4635 pTIHeader, pTITail);
4636 break;
4638 case TKIND_COCLASS:
4639 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4640 pTIHeader, pTITail);
4641 break;
4643 case TKIND_ALIAS:
4644 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4645 pTIHeader, pTITail);
4646 break;
4648 case TKIND_DISPATCH:
4649 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4650 pTIHeader, pTITail);
4651 break;
4653 case TKIND_MODULE:
4654 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4655 pTIHeader, pTITail);
4656 break;
4658 default:
4659 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4660 break;
4664 /* could get cFuncs, cVars and cImplTypes from here
4665 but we've already set those */
4666 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4667 X(06);
4668 X(16);
4669 X(18);
4670 X(1a);
4671 X(1e);
4672 X(24);
4673 X(26);
4674 X(2a);
4675 X(2c);
4676 X(2e);
4677 X(30);
4678 X(32);
4679 X(34);
4680 #undef X
4681 ++ppTypeInfoImpl;
4682 pBlk = (char*)pBlk + pBlkEntry[order].len;
4685 if(i != pTypeLibImpl->TypeInfoCount) {
4686 FIXME("Somehow processed %d TypeInfos\n", i);
4687 heap_free(pOtherTypeInfoBlks);
4688 return NULL;
4691 heap_free(pOtherTypeInfoBlks);
4692 return &pTypeLibImpl->ITypeLib2_iface;
4695 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4697 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4699 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4701 if(IsEqualIID(riid, &IID_IUnknown) ||
4702 IsEqualIID(riid,&IID_ITypeLib)||
4703 IsEqualIID(riid,&IID_ITypeLib2))
4705 *ppv = &This->ITypeLib2_iface;
4707 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4708 IsEqualIID(riid, &IID_ICreateTypeLib2))
4710 *ppv = &This->ICreateTypeLib2_iface;
4712 else
4714 *ppv = NULL;
4715 TRACE("-- Interface: E_NOINTERFACE\n");
4716 return E_NOINTERFACE;
4719 IUnknown_AddRef((IUnknown*)*ppv);
4720 return S_OK;
4723 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4725 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4726 ULONG ref = InterlockedIncrement(&This->ref);
4728 TRACE("(%p) ref=%u\n", This, ref);
4730 return ref;
4733 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4735 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4736 ULONG ref = InterlockedDecrement(&This->ref);
4738 TRACE("(%p) ref=%u\n",This, ref);
4740 if (!ref)
4742 TLBImpLib *pImpLib, *pImpLibNext;
4743 TLBRefType *ref_type, *ref_type_next;
4744 TLBString *tlbstr, *tlbstr_next;
4745 TLBGuid *tlbguid, *tlbguid_next;
4746 int i;
4748 /* remove cache entry */
4749 if(This->path)
4751 TRACE("removing from cache list\n");
4752 EnterCriticalSection(&cache_section);
4753 if(This->entry.next)
4754 list_remove(&This->entry);
4755 LeaveCriticalSection(&cache_section);
4756 heap_free(This->path);
4758 TRACE(" destroying ITypeLib(%p)\n",This);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4761 list_remove(&tlbstr->entry);
4762 SysFreeString(tlbstr->str);
4763 heap_free(tlbstr);
4766 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4767 list_remove(&tlbstr->entry);
4768 SysFreeString(tlbstr->str);
4769 heap_free(tlbstr);
4772 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4773 list_remove(&tlbguid->entry);
4774 heap_free(tlbguid);
4777 TLB_FreeCustData(&This->custdata_list);
4779 for (i = 0; i < This->ctTypeDesc; i++)
4780 if (This->pTypeDesc[i].vt == VT_CARRAY)
4781 heap_free(This->pTypeDesc[i].u.lpadesc);
4783 heap_free(This->pTypeDesc);
4785 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4787 if (pImpLib->pImpTypeLib)
4788 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4789 SysFreeString(pImpLib->name);
4791 list_remove(&pImpLib->entry);
4792 heap_free(pImpLib);
4795 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4797 list_remove(&ref_type->entry);
4798 heap_free(ref_type);
4801 for (i = 0; i < This->TypeInfoCount; ++i){
4802 heap_free(This->typeinfos[i]->tdescAlias);
4803 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4805 heap_free(This->typeinfos);
4806 heap_free(This);
4807 return 0;
4810 return ref;
4813 /* ITypeLib::GetTypeInfoCount
4815 * Returns the number of type descriptions in the type library
4817 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4819 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4820 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4821 return This->TypeInfoCount;
4824 /* ITypeLib::GetTypeInfo
4826 * retrieves the specified type description in the library.
4828 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4829 ITypeLib2 *iface,
4830 UINT index,
4831 ITypeInfo **ppTInfo)
4833 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4835 TRACE("%p %u %p\n", This, index, ppTInfo);
4837 if(!ppTInfo)
4838 return E_INVALIDARG;
4840 if(index >= This->TypeInfoCount)
4841 return TYPE_E_ELEMENTNOTFOUND;
4843 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4844 ITypeInfo_AddRef(*ppTInfo);
4846 return S_OK;
4850 /* ITypeLibs::GetTypeInfoType
4852 * Retrieves the type of a type description.
4854 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4855 ITypeLib2 *iface,
4856 UINT index,
4857 TYPEKIND *pTKind)
4859 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4861 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4863 if(!pTKind)
4864 return E_INVALIDARG;
4866 if(index >= This->TypeInfoCount)
4867 return TYPE_E_ELEMENTNOTFOUND;
4869 *pTKind = This->typeinfos[index]->typeattr.typekind;
4871 return S_OK;
4874 /* ITypeLib::GetTypeInfoOfGuid
4876 * Retrieves the type description that corresponds to the specified GUID.
4879 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4880 ITypeLib2 *iface,
4881 REFGUID guid,
4882 ITypeInfo **ppTInfo)
4884 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4885 int i;
4887 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4889 for(i = 0; i < This->TypeInfoCount; ++i){
4890 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4891 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4892 ITypeInfo_AddRef(*ppTInfo);
4893 return S_OK;
4897 return TYPE_E_ELEMENTNOTFOUND;
4900 /* ITypeLib::GetLibAttr
4902 * Retrieves the structure that contains the library's attributes.
4905 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4906 ITypeLib2 *iface,
4907 LPTLIBATTR *attr)
4909 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4911 TRACE("(%p, %p)\n", This, attr);
4913 if (!attr) return E_INVALIDARG;
4915 *attr = heap_alloc(sizeof(**attr));
4916 if (!*attr) return E_OUTOFMEMORY;
4918 (*attr)->guid = *TLB_get_guid_null(This->guid);
4919 (*attr)->lcid = This->set_lcid;
4920 (*attr)->syskind = This->syskind;
4921 (*attr)->wMajorVerNum = This->ver_major;
4922 (*attr)->wMinorVerNum = This->ver_minor;
4923 (*attr)->wLibFlags = This->libflags;
4925 return S_OK;
4928 /* ITypeLib::GetTypeComp
4930 * Enables a client compiler to bind to a library's types, variables,
4931 * constants, and global functions.
4934 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4935 ITypeLib2 *iface,
4936 ITypeComp **ppTComp)
4938 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4940 TRACE("(%p)->(%p)\n",This,ppTComp);
4941 *ppTComp = &This->ITypeComp_iface;
4942 ITypeComp_AddRef(*ppTComp);
4944 return S_OK;
4947 /* ITypeLib::GetDocumentation
4949 * Retrieves the library's documentation string, the complete Help file name
4950 * and path, and the context identifier for the library Help topic in the Help
4951 * file.
4953 * On a successful return all non-null BSTR pointers will have been set,
4954 * possibly to NULL.
4956 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4957 ITypeLib2 *iface,
4958 INT index,
4959 BSTR *pBstrName,
4960 BSTR *pBstrDocString,
4961 DWORD *pdwHelpContext,
4962 BSTR *pBstrHelpFile)
4964 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4965 HRESULT result = E_INVALIDARG;
4966 ITypeInfo *pTInfo;
4968 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4969 This, index,
4970 pBstrName, pBstrDocString,
4971 pdwHelpContext, pBstrHelpFile);
4973 if(index<0)
4975 /* documentation for the typelib */
4976 if(pBstrName)
4978 if (This->Name)
4980 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4981 goto memerr1;
4983 else
4984 *pBstrName = NULL;
4986 if(pBstrDocString)
4988 if (This->DocString)
4990 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4991 goto memerr2;
4993 else
4994 *pBstrDocString = NULL;
4996 if(pdwHelpContext)
4998 *pdwHelpContext = This->dwHelpContext;
5000 if(pBstrHelpFile)
5002 if (This->HelpFile)
5004 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5005 goto memerr3;
5007 else
5008 *pBstrHelpFile = NULL;
5011 result = S_OK;
5013 else
5015 /* for a typeinfo */
5016 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5018 if(SUCCEEDED(result))
5020 result = ITypeInfo_GetDocumentation(pTInfo,
5021 MEMBERID_NIL,
5022 pBstrName,
5023 pBstrDocString,
5024 pdwHelpContext, pBstrHelpFile);
5026 ITypeInfo_Release(pTInfo);
5029 return result;
5030 memerr3:
5031 if (pBstrDocString) SysFreeString (*pBstrDocString);
5032 memerr2:
5033 if (pBstrName) SysFreeString (*pBstrName);
5034 memerr1:
5035 return STG_E_INSUFFICIENTMEMORY;
5038 /* ITypeLib::IsName
5040 * Indicates whether a passed-in string contains the name of a type or member
5041 * described in the library.
5044 static HRESULT WINAPI ITypeLib2_fnIsName(
5045 ITypeLib2 *iface,
5046 LPOLESTR szNameBuf,
5047 ULONG lHashVal,
5048 BOOL *pfName)
5050 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5051 int tic;
5052 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5054 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5055 pfName);
5057 *pfName=TRUE;
5058 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5059 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5060 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5061 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5062 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5063 int pc;
5064 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5065 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5066 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5067 goto ITypeLib2_fnIsName_exit;
5070 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5071 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5072 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5076 *pfName=FALSE;
5078 ITypeLib2_fnIsName_exit:
5079 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5080 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5082 return S_OK;
5085 /* ITypeLib::FindName
5087 * Finds occurrences of a type description in a type library. This may be used
5088 * to quickly verify that a name exists in a type library.
5091 static HRESULT WINAPI ITypeLib2_fnFindName(
5092 ITypeLib2 *iface,
5093 LPOLESTR name,
5094 ULONG hash,
5095 ITypeInfo **ppTInfo,
5096 MEMBERID *memid,
5097 UINT16 *found)
5099 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5100 int tic;
5101 UINT count = 0;
5102 UINT len;
5104 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5106 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5107 return E_INVALIDARG;
5109 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5110 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5111 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5112 TLBVarDesc *var;
5113 UINT fdc;
5115 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5116 memid[count] = MEMBERID_NIL;
5117 goto ITypeLib2_fnFindName_exit;
5120 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5121 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5123 if(!TLB_str_memcmp(name, func->Name, len)) {
5124 memid[count] = func->funcdesc.memid;
5125 goto ITypeLib2_fnFindName_exit;
5129 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5130 if (var) {
5131 memid[count] = var->vardesc.memid;
5132 goto ITypeLib2_fnFindName_exit;
5135 continue;
5136 ITypeLib2_fnFindName_exit:
5137 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5138 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5139 count++;
5141 TRACE("found %d typeinfos\n", count);
5143 *found = count;
5145 return S_OK;
5148 /* ITypeLib::ReleaseTLibAttr
5150 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5153 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5154 ITypeLib2 *iface,
5155 TLIBATTR *pTLibAttr)
5157 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5158 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5159 heap_free(pTLibAttr);
5162 /* ITypeLib2::GetCustData
5164 * gets the custom data
5166 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5167 ITypeLib2 * iface,
5168 REFGUID guid,
5169 VARIANT *pVarVal)
5171 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5172 TLBCustData *pCData;
5174 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5176 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5177 if(!pCData)
5178 return TYPE_E_ELEMENTNOTFOUND;
5180 VariantInit(pVarVal);
5181 VariantCopy(pVarVal, &pCData->data);
5183 return S_OK;
5186 /* ITypeLib2::GetLibStatistics
5188 * Returns statistics about a type library that are required for efficient
5189 * sizing of hash tables.
5192 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5193 ITypeLib2 * iface,
5194 ULONG *pcUniqueNames,
5195 ULONG *pcchUniqueNames)
5197 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5199 FIXME("(%p): stub!\n", This);
5201 if(pcUniqueNames) *pcUniqueNames=1;
5202 if(pcchUniqueNames) *pcchUniqueNames=1;
5203 return S_OK;
5206 /* ITypeLib2::GetDocumentation2
5208 * Retrieves the library's documentation string, the complete Help file name
5209 * and path, the localization context to use, and the context ID for the
5210 * library Help topic in the Help file.
5213 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5214 ITypeLib2 * iface,
5215 INT index,
5216 LCID lcid,
5217 BSTR *pbstrHelpString,
5218 DWORD *pdwHelpStringContext,
5219 BSTR *pbstrHelpStringDll)
5221 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5222 HRESULT result;
5223 ITypeInfo *pTInfo;
5225 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5227 /* the help string should be obtained from the helpstringdll,
5228 * using the _DLLGetDocumentation function, based on the supplied
5229 * lcid. Nice to do sometime...
5231 if(index<0)
5233 /* documentation for the typelib */
5234 if(pbstrHelpString)
5235 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5236 if(pdwHelpStringContext)
5237 *pdwHelpStringContext=This->dwHelpContext;
5238 if(pbstrHelpStringDll)
5239 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5241 result = S_OK;
5243 else
5245 /* for a typeinfo */
5246 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5248 if(SUCCEEDED(result))
5250 ITypeInfo2 * pTInfo2;
5251 result = ITypeInfo_QueryInterface(pTInfo,
5252 &IID_ITypeInfo2,
5253 (LPVOID*) &pTInfo2);
5255 if(SUCCEEDED(result))
5257 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5258 MEMBERID_NIL,
5259 lcid,
5260 pbstrHelpString,
5261 pdwHelpStringContext,
5262 pbstrHelpStringDll);
5264 ITypeInfo2_Release(pTInfo2);
5267 ITypeInfo_Release(pTInfo);
5270 return result;
5273 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5275 TLBCustData *pCData;
5276 unsigned int ct;
5277 CUSTDATAITEM *cdi;
5279 ct = list_count(custdata_list);
5281 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5282 if(!pCustData->prgCustData)
5283 return E_OUTOFMEMORY;
5285 pCustData->cCustData = ct;
5287 cdi = pCustData->prgCustData;
5288 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5289 cdi->guid = *TLB_get_guid_null(pCData->guid);
5290 VariantCopy(&cdi->varValue, &pCData->data);
5291 ++cdi;
5294 return S_OK;
5298 /* ITypeLib2::GetAllCustData
5300 * Gets all custom data items for the library.
5303 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5304 ITypeLib2 * iface,
5305 CUSTDATA *pCustData)
5307 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5308 TRACE("(%p)->(%p)\n", This, pCustData);
5309 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5312 static const ITypeLib2Vtbl tlbvt = {
5313 ITypeLib2_fnQueryInterface,
5314 ITypeLib2_fnAddRef,
5315 ITypeLib2_fnRelease,
5316 ITypeLib2_fnGetTypeInfoCount,
5317 ITypeLib2_fnGetTypeInfo,
5318 ITypeLib2_fnGetTypeInfoType,
5319 ITypeLib2_fnGetTypeInfoOfGuid,
5320 ITypeLib2_fnGetLibAttr,
5321 ITypeLib2_fnGetTypeComp,
5322 ITypeLib2_fnGetDocumentation,
5323 ITypeLib2_fnIsName,
5324 ITypeLib2_fnFindName,
5325 ITypeLib2_fnReleaseTLibAttr,
5327 ITypeLib2_fnGetCustData,
5328 ITypeLib2_fnGetLibStatistics,
5329 ITypeLib2_fnGetDocumentation2,
5330 ITypeLib2_fnGetAllCustData
5334 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5336 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5338 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5341 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5343 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5345 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5348 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5350 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5352 return ITypeLib2_Release(&This->ITypeLib2_iface);
5355 static HRESULT WINAPI ITypeLibComp_fnBind(
5356 ITypeComp * iface,
5357 OLECHAR * szName,
5358 ULONG lHash,
5359 WORD wFlags,
5360 ITypeInfo ** ppTInfo,
5361 DESCKIND * pDescKind,
5362 BINDPTR * pBindPtr)
5364 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5365 BOOL typemismatch = FALSE;
5366 int i;
5368 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5370 *pDescKind = DESCKIND_NONE;
5371 pBindPtr->lptcomp = NULL;
5372 *ppTInfo = NULL;
5374 for(i = 0; i < This->TypeInfoCount; ++i){
5375 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5376 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5378 /* FIXME: check wFlags here? */
5379 /* FIXME: we should use a hash table to look this info up using lHash
5380 * instead of an O(n) search */
5381 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5382 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5384 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5386 *pDescKind = DESCKIND_TYPECOMP;
5387 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5388 ITypeComp_AddRef(pBindPtr->lptcomp);
5389 TRACE("module or enum: %s\n", debugstr_w(szName));
5390 return S_OK;
5394 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5395 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5397 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5398 HRESULT hr;
5400 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5401 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5403 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5404 return S_OK;
5406 else if (hr == TYPE_E_TYPEMISMATCH)
5407 typemismatch = TRUE;
5410 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5411 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5413 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5414 HRESULT hr;
5415 ITypeInfo *subtypeinfo;
5416 BINDPTR subbindptr;
5417 DESCKIND subdesckind;
5419 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5420 &subtypeinfo, &subdesckind, &subbindptr);
5421 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5423 TYPEDESC tdesc_appobject;
5424 const VARDESC vardesc_appobject =
5426 -2, /* memid */
5427 NULL, /* lpstrSchema */
5429 0 /* oInst */
5432 /* ELEMDESC */
5434 /* TYPEDESC */
5436 &tdesc_appobject
5438 VT_PTR
5441 0, /* wVarFlags */
5442 VAR_STATIC /* varkind */
5445 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5446 tdesc_appobject.vt = VT_USERDEFINED;
5448 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5450 /* cleanup things filled in by Bind call so we can put our
5451 * application object data in there instead */
5452 switch (subdesckind)
5454 case DESCKIND_FUNCDESC:
5455 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5456 break;
5457 case DESCKIND_VARDESC:
5458 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5459 break;
5460 default:
5461 break;
5463 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5465 if (pTypeInfo->hreftype == -1)
5466 FIXME("no hreftype for interface %p\n", pTypeInfo);
5468 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5469 if (FAILED(hr))
5470 return hr;
5472 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5473 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5474 ITypeInfo_AddRef(*ppTInfo);
5475 return S_OK;
5477 else if (hr == TYPE_E_TYPEMISMATCH)
5478 typemismatch = TRUE;
5482 if (typemismatch)
5484 TRACE("type mismatch %s\n", debugstr_w(szName));
5485 return TYPE_E_TYPEMISMATCH;
5487 else
5489 TRACE("name not found %s\n", debugstr_w(szName));
5490 return S_OK;
5494 static HRESULT WINAPI ITypeLibComp_fnBindType(
5495 ITypeComp * iface,
5496 OLECHAR * szName,
5497 ULONG lHash,
5498 ITypeInfo ** ppTInfo,
5499 ITypeComp ** ppTComp)
5501 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5502 ITypeInfoImpl *info;
5504 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5506 if(!szName || !ppTInfo || !ppTComp)
5507 return E_INVALIDARG;
5509 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5510 if(!info){
5511 *ppTInfo = NULL;
5512 *ppTComp = NULL;
5513 return S_OK;
5516 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5517 ITypeInfo_AddRef(*ppTInfo);
5518 *ppTComp = &info->ITypeComp_iface;
5519 ITypeComp_AddRef(*ppTComp);
5521 return S_OK;
5524 static const ITypeCompVtbl tlbtcvt =
5527 ITypeLibComp_fnQueryInterface,
5528 ITypeLibComp_fnAddRef,
5529 ITypeLibComp_fnRelease,
5531 ITypeLibComp_fnBind,
5532 ITypeLibComp_fnBindType
5535 /*================== ITypeInfo(2) Methods ===================================*/
5536 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5538 ITypeInfoImpl *pTypeInfoImpl;
5540 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5541 if (pTypeInfoImpl)
5543 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5544 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5545 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5546 pTypeInfoImpl->ref = 0;
5547 pTypeInfoImpl->hreftype = -1;
5548 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5549 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5550 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5551 list_init(pTypeInfoImpl->pcustdata_list);
5553 TRACE("(%p)\n", pTypeInfoImpl);
5554 return pTypeInfoImpl;
5557 /* ITypeInfo::QueryInterface
5559 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5560 ITypeInfo2 *iface,
5561 REFIID riid,
5562 VOID **ppvObject)
5564 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5566 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5568 *ppvObject=NULL;
5569 if(IsEqualIID(riid, &IID_IUnknown) ||
5570 IsEqualIID(riid,&IID_ITypeInfo)||
5571 IsEqualIID(riid,&IID_ITypeInfo2))
5572 *ppvObject = &This->ITypeInfo2_iface;
5573 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5574 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5575 *ppvObject = &This->ICreateTypeInfo2_iface;
5576 else if(IsEqualIID(riid, &IID_ITypeComp))
5577 *ppvObject = &This->ITypeComp_iface;
5579 if(*ppvObject){
5580 IUnknown_AddRef((IUnknown*)*ppvObject);
5581 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5582 return S_OK;
5584 TRACE("-- Interface: E_NOINTERFACE\n");
5585 return E_NOINTERFACE;
5588 /* ITypeInfo::AddRef
5590 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5592 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5593 ULONG ref = InterlockedIncrement(&This->ref);
5595 TRACE("(%p)->ref is %u\n",This, ref);
5597 if (ref == 1 /* incremented from 0 */)
5598 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5600 return ref;
5603 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5605 UINT i;
5607 TRACE("destroying ITypeInfo(%p)\n",This);
5609 for (i = 0; i < This->typeattr.cFuncs; ++i)
5611 int j;
5612 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5613 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5615 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5616 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5617 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5618 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5620 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5621 heap_free(pFInfo->pParamDesc);
5622 TLB_FreeCustData(&pFInfo->custdata_list);
5624 heap_free(This->funcdescs);
5626 for(i = 0; i < This->typeattr.cVars; ++i)
5628 TLBVarDesc *pVInfo = &This->vardescs[i];
5629 if (pVInfo->vardesc_create) {
5630 TLB_FreeVarDesc(pVInfo->vardesc_create);
5631 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5632 VariantClear(pVInfo->vardesc.u.lpvarValue);
5633 heap_free(pVInfo->vardesc.u.lpvarValue);
5635 TLB_FreeCustData(&pVInfo->custdata_list);
5637 heap_free(This->vardescs);
5639 if(This->impltypes){
5640 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5641 TLBImplType *pImpl = &This->impltypes[i];
5642 TLB_FreeCustData(&pImpl->custdata_list);
5644 heap_free(This->impltypes);
5647 TLB_FreeCustData(&This->custdata_list);
5649 heap_free(This);
5652 /* ITypeInfo::Release
5654 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5656 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5657 ULONG ref = InterlockedDecrement(&This->ref);
5659 TRACE("(%p)->(%u)\n",This, ref);
5661 if (!ref)
5663 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5664 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5665 if (not_attached_to_typelib)
5666 heap_free(This);
5667 /* otherwise This will be freed when typelib is freed */
5670 return ref;
5673 /* ITypeInfo::GetTypeAttr
5675 * Retrieves a TYPEATTR structure that contains the attributes of the type
5676 * description.
5679 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5680 LPTYPEATTR *ppTypeAttr)
5682 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5683 SIZE_T size;
5685 TRACE("(%p)\n",This);
5687 size = sizeof(**ppTypeAttr);
5688 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5689 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5691 *ppTypeAttr = heap_alloc(size);
5692 if (!*ppTypeAttr)
5693 return E_OUTOFMEMORY;
5695 **ppTypeAttr = This->typeattr;
5696 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5698 if (This->tdescAlias)
5699 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5701 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5702 /* This should include all the inherited funcs */
5703 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5704 /* This is always the size of IDispatch's vtbl */
5705 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5706 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5708 return S_OK;
5711 /* ITypeInfo::GetTypeComp
5713 * Retrieves the ITypeComp interface for the type description, which enables a
5714 * client compiler to bind to the type description's members.
5717 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5718 ITypeComp * *ppTComp)
5720 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5722 TRACE("(%p)->(%p)\n", This, ppTComp);
5724 *ppTComp = &This->ITypeComp_iface;
5725 ITypeComp_AddRef(*ppTComp);
5726 return S_OK;
5729 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5731 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5732 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5733 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5734 return size;
5737 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5739 *dest = *src;
5740 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5741 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5743 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5744 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5745 *buffer += sizeof(PARAMDESCEX);
5746 *pparamdescex_dest = *pparamdescex_src;
5747 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5748 VariantInit(&pparamdescex_dest->varDefaultValue);
5749 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5750 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5752 else
5753 dest->u.paramdesc.pparamdescex = NULL;
5754 return S_OK;
5757 static HRESULT TLB_SanitizeBSTR(BSTR str)
5759 UINT len = SysStringLen(str), i;
5760 for (i = 0; i < len; ++i)
5761 if (str[i] > 0x7f)
5762 str[i] = '?';
5763 return S_OK;
5766 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5768 if (V_VT(var) == VT_INT)
5769 return VariantChangeType(var, var, 0, VT_I4);
5770 else if (V_VT(var) == VT_UINT)
5771 return VariantChangeType(var, var, 0, VT_UI4);
5772 else if (V_VT(var) == VT_BSTR)
5773 return TLB_SanitizeBSTR(V_BSTR(var));
5775 return S_OK;
5778 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5780 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5781 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5784 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5786 FUNCDESC *dest;
5787 char *buffer;
5788 SIZE_T size = sizeof(*src);
5789 SHORT i;
5790 HRESULT hr;
5792 size += sizeof(*src->lprgscode) * src->cScodes;
5793 size += TLB_SizeElemDesc(&src->elemdescFunc);
5794 for (i = 0; i < src->cParams; i++)
5796 size += sizeof(ELEMDESC);
5797 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5800 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5801 if (!dest) return E_OUTOFMEMORY;
5803 *dest = *src;
5804 if (dispinterface) /* overwrite funckind */
5805 dest->funckind = FUNC_DISPATCH;
5806 buffer = (char *)(dest + 1);
5808 dest->oVft = dest->oVft & 0xFFFC;
5810 if (dest->cScodes) {
5811 dest->lprgscode = (SCODE *)buffer;
5812 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5813 buffer += sizeof(*src->lprgscode) * src->cScodes;
5814 } else
5815 dest->lprgscode = NULL;
5817 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5818 if (FAILED(hr))
5820 SysFreeString((BSTR)dest);
5821 return hr;
5824 if (dest->cParams) {
5825 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5826 buffer += sizeof(ELEMDESC) * src->cParams;
5827 for (i = 0; i < src->cParams; i++)
5829 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5830 if (FAILED(hr))
5831 break;
5833 if (FAILED(hr))
5835 /* undo the above actions */
5836 for (i = i - 1; i >= 0; i--)
5837 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5838 TLB_FreeElemDesc(&dest->elemdescFunc);
5839 SysFreeString((BSTR)dest);
5840 return hr;
5842 } else
5843 dest->lprgelemdescParam = NULL;
5845 /* special treatment for dispinterfaces: this makes functions appear
5846 * to return their [retval] value when it is really returning an
5847 * HRESULT */
5848 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5850 if (dest->cParams &&
5851 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5853 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5854 if (elemdesc->tdesc.vt != VT_PTR)
5856 ERR("elemdesc should have started with VT_PTR instead of:\n");
5857 if (ERR_ON(ole))
5858 dump_ELEMDESC(elemdesc);
5859 return E_UNEXPECTED;
5862 /* copy last parameter to the return value. we are using a flat
5863 * buffer so there is no danger of leaking memory in
5864 * elemdescFunc */
5865 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5867 /* remove the last parameter */
5868 dest->cParams--;
5870 else
5871 /* otherwise this function is made to appear to have no return
5872 * value */
5873 dest->elemdescFunc.tdesc.vt = VT_VOID;
5877 *dest_ptr = dest;
5878 return S_OK;
5881 static void TLB_FreeVarDesc(VARDESC *var_desc)
5883 TLB_FreeElemDesc(&var_desc->elemdescVar);
5884 if (var_desc->varkind == VAR_CONST)
5885 VariantClear(var_desc->u.lpvarValue);
5886 SysFreeString((BSTR)var_desc);
5889 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5891 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5893 if (index >= This->typeattr.cFuncs)
5894 return TYPE_E_ELEMENTNOTFOUND;
5896 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5897 return S_OK;
5900 /* internal function to make the inherited interfaces' methods appear
5901 * part of the interface */
5902 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5903 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5905 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5906 HRESULT hr;
5907 UINT implemented_funcs = 0;
5909 if (funcs)
5910 *funcs = 0;
5911 else
5912 *hrefoffset = DISPATCH_HREF_OFFSET;
5914 if(This->impltypes)
5916 ITypeInfo *pSubTypeInfo;
5917 UINT sub_funcs;
5919 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5920 if (FAILED(hr))
5921 return hr;
5923 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5924 index,
5925 ppFuncDesc,
5926 &sub_funcs, hrefoffset);
5927 implemented_funcs += sub_funcs;
5928 ITypeInfo_Release(pSubTypeInfo);
5929 if (SUCCEEDED(hr))
5930 return hr;
5931 *hrefoffset += DISPATCH_HREF_OFFSET;
5934 if (funcs)
5935 *funcs = implemented_funcs + This->typeattr.cFuncs;
5936 else
5937 *hrefoffset = 0;
5939 if (index < implemented_funcs)
5940 return E_INVALIDARG;
5941 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5942 ppFuncDesc);
5945 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5947 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5948 while (TRUE)
5950 switch (pTypeDesc->vt)
5952 case VT_USERDEFINED:
5953 pTypeDesc->u.hreftype += hrefoffset;
5954 return;
5955 case VT_PTR:
5956 case VT_SAFEARRAY:
5957 pTypeDesc = pTypeDesc->u.lptdesc;
5958 break;
5959 case VT_CARRAY:
5960 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5961 break;
5962 default:
5963 return;
5968 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5970 SHORT i;
5971 for (i = 0; i < pFuncDesc->cParams; i++)
5972 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5973 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5976 /* ITypeInfo::GetFuncDesc
5978 * Retrieves the FUNCDESC structure that contains information about a
5979 * specified function.
5982 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5983 LPFUNCDESC *ppFuncDesc)
5985 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5986 const FUNCDESC *internal_funcdesc;
5987 HRESULT hr;
5988 UINT hrefoffset = 0;
5990 TRACE("(%p) index %d\n", This, index);
5992 if (!ppFuncDesc)
5993 return E_INVALIDARG;
5995 if (This->needs_layout)
5996 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5998 if (This->typeattr.typekind == TKIND_DISPATCH)
5999 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
6000 &internal_funcdesc, NULL,
6001 &hrefoffset);
6002 else
6003 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6004 &internal_funcdesc);
6005 if (FAILED(hr))
6007 WARN("description for function %d not found\n", index);
6008 return hr;
6011 hr = TLB_AllocAndInitFuncDesc(
6012 internal_funcdesc,
6013 ppFuncDesc,
6014 This->typeattr.typekind == TKIND_DISPATCH);
6016 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6017 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6019 TRACE("-- 0x%08x\n", hr);
6020 return hr;
6023 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6025 VARDESC *dest;
6026 char *buffer;
6027 SIZE_T size = sizeof(*src);
6028 HRESULT hr;
6030 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6031 if (src->varkind == VAR_CONST)
6032 size += sizeof(VARIANT);
6033 size += TLB_SizeElemDesc(&src->elemdescVar);
6035 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6036 if (!dest) return E_OUTOFMEMORY;
6038 *dest = *src;
6039 buffer = (char *)(dest + 1);
6040 if (src->lpstrSchema)
6042 int len;
6043 dest->lpstrSchema = (LPOLESTR)buffer;
6044 len = strlenW(src->lpstrSchema);
6045 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6046 buffer += (len + 1) * sizeof(WCHAR);
6049 if (src->varkind == VAR_CONST)
6051 HRESULT hr;
6053 dest->u.lpvarValue = (VARIANT *)buffer;
6054 *dest->u.lpvarValue = *src->u.lpvarValue;
6055 buffer += sizeof(VARIANT);
6056 VariantInit(dest->u.lpvarValue);
6057 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6058 if (FAILED(hr))
6060 SysFreeString((BSTR)dest);
6061 return hr;
6064 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6065 if (FAILED(hr))
6067 if (src->varkind == VAR_CONST)
6068 VariantClear(dest->u.lpvarValue);
6069 SysFreeString((BSTR)dest);
6070 return hr;
6072 *dest_ptr = dest;
6073 return S_OK;
6076 /* ITypeInfo::GetVarDesc
6078 * Retrieves a VARDESC structure that describes the specified variable.
6081 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6082 LPVARDESC *ppVarDesc)
6084 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6085 const TLBVarDesc *pVDesc = &This->vardescs[index];
6087 TRACE("(%p) index %d\n", This, index);
6089 if(index >= This->typeattr.cVars)
6090 return TYPE_E_ELEMENTNOTFOUND;
6092 if (This->needs_layout)
6093 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6095 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6098 /* ITypeInfo_GetNames
6100 * Retrieves the variable with the specified member ID (or the name of the
6101 * property or method and its parameters) that correspond to the specified
6102 * function ID.
6104 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6105 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6107 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6108 const TLBFuncDesc *pFDesc;
6109 const TLBVarDesc *pVDesc;
6110 int i;
6111 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6113 if(!rgBstrNames)
6114 return E_INVALIDARG;
6116 *pcNames = 0;
6118 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6119 if(pFDesc)
6121 if(!cMaxNames || !pFDesc->Name)
6122 return S_OK;
6124 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6125 ++(*pcNames);
6127 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6128 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6129 return S_OK;
6130 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6131 ++(*pcNames);
6133 return S_OK;
6136 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6137 if(pVDesc)
6139 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6140 *pcNames=1;
6142 else
6144 if(This->impltypes &&
6145 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6146 /* recursive search */
6147 ITypeInfo *pTInfo;
6148 HRESULT result;
6149 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6150 if(SUCCEEDED(result))
6152 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6153 ITypeInfo_Release(pTInfo);
6154 return result;
6156 WARN("Could not search inherited interface!\n");
6158 else
6160 WARN("no names found\n");
6162 *pcNames=0;
6163 return TYPE_E_ELEMENTNOTFOUND;
6165 return S_OK;
6169 /* ITypeInfo::GetRefTypeOfImplType
6171 * If a type description describes a COM class, it retrieves the type
6172 * description of the implemented interface types. For an interface,
6173 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6174 * if any exist.
6177 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6178 ITypeInfo2 *iface,
6179 UINT index,
6180 HREFTYPE *pRefType)
6182 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6183 HRESULT hr = S_OK;
6185 TRACE("(%p) index %d\n", This, index);
6186 if (TRACE_ON(ole)) dump_TypeInfo(This);
6188 if(index==(UINT)-1)
6190 /* only valid on dual interfaces;
6191 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6194 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6196 *pRefType = -2;
6198 else
6200 hr = TYPE_E_ELEMENTNOTFOUND;
6203 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6205 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6206 *pRefType = This->pTypeLib->dispatch_href;
6208 else
6210 if(index >= This->typeattr.cImplTypes)
6211 hr = TYPE_E_ELEMENTNOTFOUND;
6212 else{
6213 *pRefType = This->impltypes[index].hRef;
6214 if (This->typeattr.typekind == TKIND_INTERFACE)
6215 *pRefType |= 0x2;
6219 if(TRACE_ON(ole))
6221 if(SUCCEEDED(hr))
6222 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6223 else
6224 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6227 return hr;
6230 /* ITypeInfo::GetImplTypeFlags
6232 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6233 * or base interface in a type description.
6235 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6236 UINT index, INT *pImplTypeFlags)
6238 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6240 TRACE("(%p) index %d\n", This, index);
6242 if(!pImplTypeFlags)
6243 return E_INVALIDARG;
6245 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6246 *pImplTypeFlags = 0;
6247 return S_OK;
6250 if(index >= This->typeattr.cImplTypes)
6251 return TYPE_E_ELEMENTNOTFOUND;
6253 *pImplTypeFlags = This->impltypes[index].implflags;
6255 return S_OK;
6258 /* GetIDsOfNames
6259 * Maps between member names and member IDs, and parameter names and
6260 * parameter IDs.
6262 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6263 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6265 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6266 const TLBVarDesc *pVDesc;
6267 HRESULT ret=S_OK;
6268 UINT i, fdc;
6270 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6271 cNames);
6273 /* init out parameters in case of failure */
6274 for (i = 0; i < cNames; i++)
6275 pMemId[i] = MEMBERID_NIL;
6277 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6278 int j;
6279 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6280 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6281 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6282 for(i=1; i < cNames; i++){
6283 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6284 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6285 break;
6286 if( j<pFDesc->funcdesc.cParams)
6287 pMemId[i]=j;
6288 else
6289 ret=DISP_E_UNKNOWNNAME;
6291 TRACE("-- 0x%08x\n", ret);
6292 return ret;
6295 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6296 if(pVDesc){
6297 if(cNames)
6298 *pMemId = pVDesc->vardesc.memid;
6299 return ret;
6301 /* not found, see if it can be found in an inherited interface */
6302 if(This->impltypes) {
6303 /* recursive search */
6304 ITypeInfo *pTInfo;
6305 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6306 if(SUCCEEDED(ret)){
6307 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6308 ITypeInfo_Release(pTInfo);
6309 return ret;
6311 WARN("Could not search inherited interface!\n");
6312 } else
6313 WARN("no names found\n");
6314 return DISP_E_UNKNOWNNAME;
6318 #ifdef __i386__
6320 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6321 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6322 __ASM_GLOBAL_FUNC( call_method,
6323 "pushl %ebp\n\t"
6324 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6325 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6326 "movl %esp,%ebp\n\t"
6327 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6328 "pushl %esi\n\t"
6329 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6330 "pushl %edi\n\t"
6331 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6332 "movl 12(%ebp),%edx\n\t"
6333 "movl %esp,%edi\n\t"
6334 "shll $2,%edx\n\t"
6335 "jz 1f\n\t"
6336 "subl %edx,%edi\n\t"
6337 "andl $~15,%edi\n\t"
6338 "movl %edi,%esp\n\t"
6339 "movl 12(%ebp),%ecx\n\t"
6340 "movl 16(%ebp),%esi\n\t"
6341 "cld\n\t"
6342 "rep; movsl\n"
6343 "1:\tcall *8(%ebp)\n\t"
6344 "subl %esp,%edi\n\t"
6345 "movl 20(%ebp),%ecx\n\t"
6346 "movl %edi,(%ecx)\n\t"
6347 "leal -8(%ebp),%esp\n\t"
6348 "popl %edi\n\t"
6349 __ASM_CFI(".cfi_same_value %edi\n\t")
6350 "popl %esi\n\t"
6351 __ASM_CFI(".cfi_same_value %esi\n\t")
6352 "popl %ebp\n\t"
6353 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6354 __ASM_CFI(".cfi_same_value %ebp\n\t")
6355 "ret" )
6356 __ASM_GLOBAL_FUNC( call_double_method,
6357 "jmp " __ASM_NAME("call_method") )
6359 #elif defined(__x86_64__)
6361 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6362 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6363 __ASM_GLOBAL_FUNC( call_method,
6364 "pushq %rbp\n\t"
6365 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6366 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6367 "movq %rsp,%rbp\n\t"
6368 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6369 "pushq %rsi\n\t"
6370 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6371 "pushq %rdi\n\t"
6372 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6373 "movq %rcx,%rax\n\t"
6374 "movq $4,%rcx\n\t"
6375 "cmp %rcx,%rdx\n\t"
6376 "cmovgq %rdx,%rcx\n\t"
6377 "leaq 0(,%rcx,8),%rdx\n\t"
6378 "subq %rdx,%rsp\n\t"
6379 "andq $~15,%rsp\n\t"
6380 "movq %rsp,%rdi\n\t"
6381 "movq %r8,%rsi\n\t"
6382 "rep; movsq\n\t"
6383 "movq 0(%rsp),%rcx\n\t"
6384 "movq 8(%rsp),%rdx\n\t"
6385 "movq 16(%rsp),%r8\n\t"
6386 "movq 24(%rsp),%r9\n\t"
6387 "movq 0(%rsp),%xmm0\n\t"
6388 "movq 8(%rsp),%xmm1\n\t"
6389 "movq 16(%rsp),%xmm2\n\t"
6390 "movq 24(%rsp),%xmm3\n\t"
6391 "callq *%rax\n\t"
6392 "leaq -16(%rbp),%rsp\n\t"
6393 "popq %rdi\n\t"
6394 __ASM_CFI(".cfi_same_value %rdi\n\t")
6395 "popq %rsi\n\t"
6396 __ASM_CFI(".cfi_same_value %rsi\n\t")
6397 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6398 "popq %rbp\n\t"
6399 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6400 __ASM_CFI(".cfi_same_value %rbp\n\t")
6401 "ret")
6402 __ASM_GLOBAL_FUNC( call_double_method,
6403 "jmp " __ASM_NAME("call_method") )
6405 #elif defined(__arm__)
6407 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6408 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6409 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6410 __ASM_GLOBAL_FUNC( call_method,
6411 /* r0 = *func
6412 * r1 = nb_stk_args
6413 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6414 * r3 = *reg_args (pointer to 8, 64-bit d0-d7 (double) values OR as 16, 32-bit s0-s15 (float) values, followed by 4, 32-bit (DWORD) r0-r3 values)
6417 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6418 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6420 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6421 "beq 1f\n\t" /* Skip allocation if no stack args */
6422 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6423 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6424 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6425 "subs r1, r1, #4\n\t" /* Decrement count */
6426 "bgt 2b\n\t" /* Loop till done */
6428 "1:\n\t"
6429 #ifndef __SOFTFP__
6430 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6431 #endif
6432 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6433 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6435 "blx ip\n\t" /* Call the target function */
6437 "mov sp, fp\n\t" /* Clean the stack using fp */
6438 "pop {fp, pc}\n\t" /* Restore fp and return */
6440 __ASM_GLOBAL_FUNC( call_float_method,
6441 "b " __ASM_NAME("call_method") )
6442 __ASM_GLOBAL_FUNC( call_double_method,
6443 "b " __ASM_NAME("call_method") )
6445 #endif /* __arm__ */
6447 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6449 HRESULT hr = S_OK;
6450 ITypeInfo *tinfo2 = NULL;
6451 TYPEATTR *tattr = NULL;
6453 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6454 if (hr)
6456 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6457 "hr = 0x%08x\n",
6458 tdesc->u.hreftype, hr);
6459 return hr;
6461 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6462 if (hr)
6464 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6465 ITypeInfo_Release(tinfo2);
6466 return hr;
6469 switch (tattr->typekind)
6471 case TKIND_ENUM:
6472 *vt |= VT_I4;
6473 break;
6475 case TKIND_ALIAS:
6476 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6477 break;
6479 case TKIND_INTERFACE:
6480 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6481 *vt |= VT_DISPATCH;
6482 else
6483 *vt |= VT_UNKNOWN;
6484 break;
6486 case TKIND_DISPATCH:
6487 *vt |= VT_DISPATCH;
6488 break;
6490 case TKIND_COCLASS:
6491 *vt |= VT_DISPATCH;
6492 break;
6494 case TKIND_RECORD:
6495 FIXME("TKIND_RECORD unhandled.\n");
6496 hr = E_NOTIMPL;
6497 break;
6499 case TKIND_UNION:
6500 FIXME("TKIND_UNION unhandled.\n");
6501 hr = E_NOTIMPL;
6502 break;
6504 default:
6505 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6506 hr = E_NOTIMPL;
6507 break;
6509 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6510 ITypeInfo_Release(tinfo2);
6511 return hr;
6514 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6516 HRESULT hr = S_OK;
6518 /* enforce only one level of pointer indirection */
6519 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6521 tdesc = tdesc->u.lptdesc;
6523 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6524 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6525 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6526 if ((tdesc->vt == VT_USERDEFINED) ||
6527 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6529 VARTYPE vt_userdefined = 0;
6530 const TYPEDESC *tdesc_userdefined = tdesc;
6531 if (tdesc->vt == VT_PTR)
6533 vt_userdefined = VT_BYREF;
6534 tdesc_userdefined = tdesc->u.lptdesc;
6536 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6537 if ((hr == S_OK) &&
6538 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6539 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6541 *vt |= vt_userdefined;
6542 return S_OK;
6545 *vt = VT_BYREF;
6548 switch (tdesc->vt)
6550 case VT_HRESULT:
6551 *vt |= VT_ERROR;
6552 break;
6553 case VT_USERDEFINED:
6554 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6555 break;
6556 case VT_VOID:
6557 case VT_CARRAY:
6558 case VT_PTR:
6559 case VT_LPSTR:
6560 case VT_LPWSTR:
6561 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6562 hr = DISP_E_BADVARTYPE;
6563 break;
6564 case VT_SAFEARRAY:
6565 *vt |= VT_ARRAY;
6566 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6567 break;
6568 case VT_INT:
6569 *vt |= VT_I4;
6570 break;
6571 case VT_UINT:
6572 *vt |= VT_UI4;
6573 break;
6574 default:
6575 *vt |= tdesc->vt;
6576 break;
6578 return hr;
6581 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
6583 ITypeInfo *tinfo2;
6584 TYPEATTR *tattr;
6585 HRESULT hres;
6586 int flags, i;
6588 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
6589 if(FAILED(hres))
6590 return hres;
6592 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6593 if(FAILED(hres)) {
6594 ITypeInfo_Release(tinfo2);
6595 return hres;
6598 switch(tattr->typekind) {
6599 case TKIND_ALIAS:
6600 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
6601 break;
6603 case TKIND_INTERFACE:
6604 case TKIND_DISPATCH:
6605 *guid = tattr->guid;
6606 break;
6608 case TKIND_COCLASS:
6609 for (i = 0; i < tattr->cImplTypes; i++)
6611 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
6612 if (flags & IMPLTYPEFLAG_FDEFAULT)
6613 break;
6616 if (i == tattr->cImplTypes)
6617 i = 0;
6619 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
6620 if (SUCCEEDED(hres))
6621 hres = get_iface_guid(tinfo2, href, guid);
6622 break;
6624 default:
6625 ERR("Unexpected typekind %d\n", tattr->typekind);
6626 hres = E_UNEXPECTED;
6629 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6630 ITypeInfo_Release(tinfo2);
6631 return hres;
6634 /***********************************************************************
6635 * DispCallFunc (OLEAUT32.@)
6637 * Invokes a function of the specified calling convention, passing the
6638 * specified arguments and returns the result.
6640 * PARAMS
6641 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6642 * oVft [I] The offset in the vtable. See notes.
6643 * cc [I] Calling convention of the function to call.
6644 * vtReturn [I] The return type of the function.
6645 * cActuals [I] Number of parameters.
6646 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6647 * prgpvarg [I] The arguments to pass.
6648 * pvargResult [O] The return value of the function. Can be NULL.
6650 * RETURNS
6651 * Success: S_OK.
6652 * Failure: HRESULT code.
6654 * NOTES
6655 * The HRESULT return value of this function is not affected by the return
6656 * value of the user supplied function, which is returned in pvargResult.
6658 * If pvInstance is NULL then a non-object function is to be called and oVft
6659 * is the address of the function to call.
6661 * The cc parameter can be one of the following values:
6662 *|CC_FASTCALL
6663 *|CC_CDECL
6664 *|CC_PASCAL
6665 *|CC_STDCALL
6666 *|CC_FPFASTCALL
6667 *|CC_SYSCALL
6668 *|CC_MPWCDECL
6669 *|CC_MPWPASCAL
6672 HRESULT WINAPI
6673 DispCallFunc(
6674 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6675 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6677 #ifdef __i386__
6678 int argspos = 0, stack_offset;
6679 void *func;
6680 UINT i;
6681 DWORD *args;
6683 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6684 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6685 pvargResult, V_VT(pvargResult));
6687 if (cc != CC_STDCALL && cc != CC_CDECL)
6689 FIXME("unsupported calling convention %d\n",cc);
6690 return E_INVALIDARG;
6693 /* maximum size for an argument is sizeof(VARIANT) */
6694 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6696 if (pvInstance)
6698 const FARPROC *vtable = *(FARPROC **)pvInstance;
6699 func = vtable[oVft/sizeof(void *)];
6700 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6702 else func = (void *)oVft;
6704 switch (vtReturn)
6706 case VT_DECIMAL:
6707 case VT_VARIANT:
6708 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6709 break;
6710 case VT_HRESULT:
6711 WARN("invalid return type %u\n", vtReturn);
6712 heap_free( args );
6713 return E_INVALIDARG;
6714 default:
6715 break;
6718 for (i = 0; i < cActuals; i++)
6720 VARIANT *arg = prgpvarg[i];
6722 switch (prgvt[i])
6724 case VT_EMPTY:
6725 break;
6726 case VT_I8:
6727 case VT_UI8:
6728 case VT_R8:
6729 case VT_DATE:
6730 case VT_CY:
6731 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6732 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6733 break;
6734 case VT_DECIMAL:
6735 case VT_VARIANT:
6736 memcpy( &args[argspos], arg, sizeof(*arg) );
6737 argspos += sizeof(*arg) / sizeof(DWORD);
6738 break;
6739 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6740 args[argspos++] = V_BOOL(arg);
6741 break;
6742 default:
6743 args[argspos++] = V_UI4(arg);
6744 break;
6746 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6749 switch (vtReturn)
6751 case VT_EMPTY:
6752 case VT_DECIMAL:
6753 case VT_VARIANT:
6754 call_method( func, argspos, args, &stack_offset );
6755 break;
6756 case VT_R4:
6757 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6758 break;
6759 case VT_R8:
6760 case VT_DATE:
6761 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6762 break;
6763 case VT_I8:
6764 case VT_UI8:
6765 case VT_CY:
6766 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6767 break;
6768 default:
6769 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6770 break;
6772 heap_free( args );
6773 if (stack_offset && cc == CC_STDCALL)
6775 WARN( "stack pointer off by %d\n", stack_offset );
6776 return DISP_E_BADCALLEE;
6778 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6779 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6780 return S_OK;
6782 #elif defined(__x86_64__)
6783 int argspos = 0;
6784 UINT i;
6785 DWORD_PTR *args;
6786 void *func;
6788 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6789 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6790 pvargResult, V_VT(pvargResult));
6792 if (cc != CC_STDCALL && cc != CC_CDECL)
6794 FIXME("unsupported calling convention %d\n",cc);
6795 return E_INVALIDARG;
6798 /* maximum size for an argument is sizeof(DWORD_PTR) */
6799 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6801 if (pvInstance)
6803 const FARPROC *vtable = *(FARPROC **)pvInstance;
6804 func = vtable[oVft/sizeof(void *)];
6805 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6807 else func = (void *)oVft;
6809 switch (vtReturn)
6811 case VT_DECIMAL:
6812 case VT_VARIANT:
6813 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6814 break;
6815 case VT_HRESULT:
6816 WARN("invalid return type %u\n", vtReturn);
6817 heap_free( args );
6818 return E_INVALIDARG;
6819 default:
6820 break;
6823 for (i = 0; i < cActuals; i++)
6825 VARIANT *arg = prgpvarg[i];
6827 switch (prgvt[i])
6829 case VT_DECIMAL:
6830 case VT_VARIANT:
6831 args[argspos++] = (ULONG_PTR)arg;
6832 break;
6833 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6834 args[argspos++] = V_BOOL(arg);
6835 break;
6836 default:
6837 args[argspos++] = V_UI8(arg);
6838 break;
6840 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6843 switch (vtReturn)
6845 case VT_R4:
6846 V_R4(pvargResult) = call_double_method( func, argspos, args );
6847 break;
6848 case VT_R8:
6849 case VT_DATE:
6850 V_R8(pvargResult) = call_double_method( func, argspos, args );
6851 break;
6852 case VT_DECIMAL:
6853 case VT_VARIANT:
6854 call_method( func, argspos, args );
6855 break;
6856 default:
6857 V_UI8(pvargResult) = call_method( func, argspos, args );
6858 break;
6860 heap_free( args );
6861 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6862 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6863 return S_OK;
6865 #elif defined(__arm__)
6866 int argspos;
6867 void *func;
6868 UINT i;
6869 DWORD *args;
6870 struct {
6871 #ifndef __SOFTFP__
6872 union {
6873 float s[16];
6874 double d[8];
6875 } sd;
6876 #endif
6877 DWORD r[4];
6878 } regs;
6879 int rcount; /* 32-bit register index count */
6880 #ifndef __SOFTFP__
6881 int scount = 0; /* single-precision float register index count */
6882 int dcount = 0; /* double-precision float register index count */
6883 #endif
6885 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6886 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6888 if (cc != CC_STDCALL && cc != CC_CDECL)
6890 FIXME("unsupported calling convention %d\n",cc);
6891 return E_INVALIDARG;
6894 argspos = 0;
6895 rcount = 0;
6897 if (pvInstance)
6899 const FARPROC *vtable = *(FARPROC **)pvInstance;
6900 func = vtable[oVft/sizeof(void *)];
6901 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6903 else func = (void *)oVft;
6905 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6906 /* first as it will need to be in the 'r' registers: */
6907 switch (vtReturn)
6909 case VT_DECIMAL:
6910 case VT_VARIANT:
6911 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6912 break;
6913 case VT_HRESULT:
6914 WARN("invalid return type %u\n", vtReturn);
6915 return E_INVALIDARG;
6916 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6917 break;
6920 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6921 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6923 for (i = 0; i < cActuals; i++)
6925 VARIANT *arg = prgpvarg[i];
6926 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6927 int ntemp; /* Used for counting words split between registers and stack */
6929 switch (prgvt[i])
6931 case VT_EMPTY:
6932 break;
6933 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6934 case VT_DATE:
6935 #ifndef __SOFTFP__
6936 dcount = max( (scount + 1) / 2, dcount );
6937 if (dcount < 8)
6939 regs.sd.d[dcount++] = V_R8(arg);
6941 else
6943 argspos += (argspos % 2); /* align argspos to 8-bytes */
6944 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6945 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6947 break;
6948 #endif
6949 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6950 case VT_UI8:
6951 case VT_CY:
6952 if (rcount < 3)
6954 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6955 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6956 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6958 else
6960 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6961 argspos += (argspos % 2); /* align argspos to 8-bytes */
6962 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6963 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6965 break;
6966 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6967 case VT_VARIANT:
6968 /* 8-byte align 'r' and/or stack: */
6969 if (rcount < 3)
6970 rcount += (rcount % 2);
6971 else
6973 rcount = 4;
6974 argspos += (argspos % 2);
6976 ntemp = sizeof(*arg) / sizeof(DWORD);
6977 while (ntemp > 0)
6979 if (rcount < 4)
6980 regs.r[rcount++] = *pdwarg++;
6981 else
6982 args[argspos++] = *pdwarg++;
6983 --ntemp;
6985 break;
6986 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6987 if (rcount < 4)
6988 regs.r[rcount++] = V_BOOL(arg);
6989 else
6990 args[argspos++] = V_BOOL(arg);
6991 break;
6992 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6993 #ifndef __SOFTFP__
6994 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6995 if (scount < 16)
6996 regs.sd.s[scount++] = V_R4(arg);
6997 else
6998 args[argspos++] = V_UI4(arg);
6999 break;
7000 #endif
7001 default:
7002 if (rcount < 4)
7003 regs.r[rcount++] = V_UI4(arg);
7004 else
7005 args[argspos++] = V_UI4(arg);
7006 break;
7008 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
7011 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
7013 switch (vtReturn)
7015 case VT_EMPTY: /* EMPTY = no return value */
7016 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7017 case VT_VARIANT:
7018 call_method( func, argspos, args, (DWORD*)&regs );
7019 break;
7020 case VT_R4:
7021 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
7022 break;
7023 case VT_R8:
7024 case VT_DATE:
7025 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
7026 break;
7027 case VT_I8:
7028 case VT_UI8:
7029 case VT_CY:
7030 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7031 break;
7032 default:
7033 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7034 break;
7036 heap_free( args );
7037 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
7038 TRACE("retval: %s\n", debugstr_variant(pvargResult));
7039 return S_OK;
7041 #else
7042 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7043 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
7044 return E_NOTIMPL;
7045 #endif
7048 static inline BOOL func_restricted( const FUNCDESC *desc )
7050 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7053 #define INVBUF_ELEMENT_SIZE \
7054 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7055 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7056 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7057 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7058 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7059 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7060 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7061 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7063 static HRESULT WINAPI ITypeInfo_fnInvoke(
7064 ITypeInfo2 *iface,
7065 VOID *pIUnk,
7066 MEMBERID memid,
7067 UINT16 wFlags,
7068 DISPPARAMS *pDispParams,
7069 VARIANT *pVarResult,
7070 EXCEPINFO *pExcepInfo,
7071 UINT *pArgErr)
7073 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7074 int i;
7075 unsigned int var_index;
7076 TYPEKIND type_kind;
7077 HRESULT hres;
7078 const TLBFuncDesc *pFuncInfo;
7079 UINT fdc;
7081 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7082 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7085 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7086 return DISP_E_MEMBERNOTFOUND;
7088 if (!pDispParams)
7090 ERR("NULL pDispParams not allowed\n");
7091 return E_INVALIDARG;
7094 dump_DispParms(pDispParams);
7096 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7098 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7099 pDispParams->cNamedArgs, pDispParams->cArgs);
7100 return E_INVALIDARG;
7103 /* we do this instead of using GetFuncDesc since it will return a fake
7104 * FUNCDESC for dispinterfaces and we want the real function description */
7105 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7106 pFuncInfo = &This->funcdescs[fdc];
7107 if ((memid == pFuncInfo->funcdesc.memid) &&
7108 (wFlags & pFuncInfo->funcdesc.invkind) &&
7109 !func_restricted( &pFuncInfo->funcdesc ))
7110 break;
7113 if (fdc < This->typeattr.cFuncs) {
7114 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7116 if (TRACE_ON(ole))
7118 TRACE("invoking:\n");
7119 dump_TLBFuncDescOne(pFuncInfo);
7122 switch (func_desc->funckind) {
7123 case FUNC_PUREVIRTUAL:
7124 case FUNC_VIRTUAL: {
7125 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7126 VARIANT varresult;
7127 VARIANT retval; /* pointer for storing byref retvals in */
7128 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7129 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7130 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7131 UINT cNamedArgs = pDispParams->cNamedArgs;
7132 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7133 UINT vargs_converted=0;
7135 hres = S_OK;
7137 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7139 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7141 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7142 hres = DISP_E_PARAMNOTFOUND;
7143 goto func_fail;
7147 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7149 ERR("functions with the vararg attribute do not support named arguments\n");
7150 hres = DISP_E_NONAMEDARGS;
7151 goto func_fail;
7154 for (i = 0; i < func_desc->cParams; i++)
7156 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7157 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7158 if (FAILED(hres))
7159 goto func_fail;
7162 TRACE("changing args\n");
7163 for (i = 0; i < func_desc->cParams; i++)
7165 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7166 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7167 VARIANTARG *src_arg;
7169 if (wParamFlags & PARAMFLAG_FLCID)
7171 VARIANTARG *arg;
7172 arg = prgpvarg[i] = &rgvarg[i];
7173 V_VT(arg) = VT_I4;
7174 V_I4(arg) = This->pTypeLib->lcid;
7175 continue;
7178 src_arg = NULL;
7180 if (cNamedArgs)
7182 USHORT j;
7183 for (j = 0; j < cNamedArgs; j++)
7184 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7186 src_arg = &pDispParams->rgvarg[j];
7187 break;
7191 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7193 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7194 vargs_converted++;
7197 if (wParamFlags & PARAMFLAG_FRETVAL)
7199 /* under most conditions the caller is not allowed to
7200 * pass in a dispparam arg in the index of what would be
7201 * the retval parameter. however, there is an exception
7202 * where the extra parameter is used in an extra
7203 * IDispatch::Invoke below */
7204 if ((i < pDispParams->cArgs) &&
7205 ((func_desc->cParams != 1) || !pVarResult ||
7206 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7208 hres = DISP_E_BADPARAMCOUNT;
7209 break;
7212 /* note: this check is placed so that if the caller passes
7213 * in a VARIANTARG for the retval we just ignore it, like
7214 * native does */
7215 if (i == func_desc->cParams - 1)
7217 VARIANTARG *arg;
7218 arg = prgpvarg[i] = &rgvarg[i];
7219 memset(arg, 0, sizeof(*arg));
7220 V_VT(arg) = rgvt[i];
7221 memset(&retval, 0, sizeof(retval));
7222 V_BYREF(arg) = &retval;
7224 else
7226 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7227 hres = E_UNEXPECTED;
7228 break;
7231 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7232 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7234 TRACE("%s\n", debugstr_variant(src_arg));
7236 if(rgvt[i]!=V_VT(src_arg))
7238 if (rgvt[i] == VT_VARIANT)
7239 hres = VariantCopy(&rgvarg[i], src_arg);
7240 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7242 if (rgvt[i] == V_VT(src_arg))
7243 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7244 else
7246 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7247 if (wParamFlags & PARAMFLAG_FIN)
7248 hres = VariantCopy(&missing_arg[i], src_arg);
7249 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7251 V_VT(&rgvarg[i]) = rgvt[i];
7253 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7255 SAFEARRAY *a;
7256 SAFEARRAYBOUND bound;
7257 VARIANT *v;
7258 LONG j;
7259 bound.lLbound = 0;
7260 bound.cElements = pDispParams->cArgs-i;
7261 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7263 ERR("SafeArrayCreate failed\n");
7264 break;
7266 hres = SafeArrayAccessData(a, (LPVOID)&v);
7267 if (hres != S_OK)
7269 ERR("SafeArrayAccessData failed with %x\n", hres);
7270 SafeArrayDestroy(a);
7271 break;
7273 for (j = 0; j < bound.cElements; j++)
7274 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7275 hres = SafeArrayUnaccessData(a);
7276 if (hres != S_OK)
7278 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7279 SafeArrayDestroy(a);
7280 break;
7282 if (rgvt[i] & VT_BYREF)
7283 V_BYREF(&rgvarg[i]) = &a;
7284 else
7285 V_ARRAY(&rgvarg[i]) = a;
7286 V_VT(&rgvarg[i]) = rgvt[i];
7288 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7290 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7291 if (wParamFlags & PARAMFLAG_FIN)
7292 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7293 else
7294 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7295 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7296 V_VT(&rgvarg[i]) = rgvt[i];
7298 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7300 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7301 V_VT(&rgvarg[i]) = rgvt[i];
7303 else
7305 /* FIXME: this doesn't work for VT_BYREF arguments if
7306 * they are not the same type as in the paramdesc */
7307 V_VT(&rgvarg[i]) = V_VT(src_arg);
7308 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7309 V_VT(&rgvarg[i]) = rgvt[i];
7312 if (FAILED(hres))
7314 ERR("failed to convert param %d to %s from %s\n", i,
7315 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7316 break;
7318 prgpvarg[i] = &rgvarg[i];
7320 else
7322 prgpvarg[i] = src_arg;
7325 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7326 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7327 && V_UNKNOWN(prgpvarg[i])) {
7328 IUnknown *userdefined_iface;
7329 GUID guid;
7331 if (tdesc->vt == VT_PTR)
7332 tdesc = tdesc->u.lptdesc;
7334 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7335 if(FAILED(hres))
7336 break;
7338 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7339 if(FAILED(hres)) {
7340 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7341 break;
7344 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7345 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7348 else if (wParamFlags & PARAMFLAG_FOPT)
7350 VARIANTARG *arg;
7351 arg = prgpvarg[i] = &rgvarg[i];
7352 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7354 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7355 if (FAILED(hres))
7356 break;
7358 else
7360 VARIANTARG *missing_arg;
7361 /* if the function wants a pointer to a variant then
7362 * set that up, otherwise just pass the VT_ERROR in
7363 * the argument by value */
7364 if (rgvt[i] & VT_BYREF)
7366 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7367 V_VT(arg) = VT_VARIANT | VT_BYREF;
7368 V_VARIANTREF(arg) = missing_arg;
7370 else
7371 missing_arg = arg;
7372 V_VT(missing_arg) = VT_ERROR;
7373 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7376 else
7378 hres = DISP_E_BADPARAMCOUNT;
7379 break;
7382 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7384 /* VT_VOID is a special case for return types, so it is not
7385 * handled in the general function */
7386 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7387 V_VT(&varresult) = VT_EMPTY;
7388 else
7390 V_VT(&varresult) = 0;
7391 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7392 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7395 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7396 V_VT(&varresult), func_desc->cParams, rgvt,
7397 prgpvarg, &varresult);
7399 vargs_converted = 0;
7401 for (i = 0; i < func_desc->cParams; i++)
7403 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7404 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7406 if (wParamFlags & PARAMFLAG_FLCID)
7407 continue;
7408 else if (wParamFlags & PARAMFLAG_FRETVAL)
7410 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7412 if (pVarResult)
7414 VariantInit(pVarResult);
7415 /* deref return value */
7416 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7419 VARIANT_ClearInd(prgpvarg[i]);
7421 else if (vargs_converted < pDispParams->cArgs)
7423 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7424 if (wParamFlags & PARAMFLAG_FOUT)
7426 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7428 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7430 if (FAILED(hres))
7432 ERR("failed to convert param %d to vt %d\n", i,
7433 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7434 break;
7438 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7439 func_desc->cParamsOpt < 0 &&
7440 i == func_desc->cParams-1)
7442 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7443 LONG j, ubound;
7444 VARIANT *v;
7445 hres = SafeArrayGetUBound(a, 1, &ubound);
7446 if (hres != S_OK)
7448 ERR("SafeArrayGetUBound failed with %x\n", hres);
7449 break;
7451 hres = SafeArrayAccessData(a, (LPVOID)&v);
7452 if (hres != S_OK)
7454 ERR("SafeArrayAccessData failed with %x\n", hres);
7455 break;
7457 for (j = 0; j <= ubound; j++)
7458 VariantClear(&v[j]);
7459 hres = SafeArrayUnaccessData(a);
7460 if (hres != S_OK)
7462 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7463 break;
7466 VariantClear(&rgvarg[i]);
7467 vargs_converted++;
7469 else if (wParamFlags & PARAMFLAG_FOPT)
7471 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7472 VariantClear(&rgvarg[i]);
7475 VariantClear(&missing_arg[i]);
7478 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7480 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7481 hres = DISP_E_EXCEPTION;
7482 if (pExcepInfo)
7484 IErrorInfo *pErrorInfo;
7485 pExcepInfo->scode = V_ERROR(&varresult);
7486 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7488 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7489 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7490 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7491 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7493 IErrorInfo_Release(pErrorInfo);
7497 if (V_VT(&varresult) != VT_ERROR)
7499 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7501 if (pVarResult)
7503 VariantClear(pVarResult);
7504 *pVarResult = varresult;
7506 else
7507 VariantClear(&varresult);
7510 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7511 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7512 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7513 (pDispParams->cArgs != 0))
7515 if (V_VT(pVarResult) == VT_DISPATCH)
7517 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7518 /* Note: not VariantClear; we still need the dispatch
7519 * pointer to be valid */
7520 VariantInit(pVarResult);
7521 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7522 GetSystemDefaultLCID(), wFlags,
7523 pDispParams, pVarResult, pExcepInfo, pArgErr);
7524 IDispatch_Release(pDispatch);
7526 else
7528 VariantClear(pVarResult);
7529 hres = DISP_E_NOTACOLLECTION;
7533 func_fail:
7534 heap_free(buffer);
7535 break;
7537 case FUNC_DISPATCH: {
7538 IDispatch *disp;
7540 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7541 if (SUCCEEDED(hres)) {
7542 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7543 hres = IDispatch_Invoke(
7544 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7545 pVarResult,pExcepInfo,pArgErr
7547 if (FAILED(hres))
7548 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7549 IDispatch_Release(disp);
7550 } else
7551 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7552 break;
7554 default:
7555 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7556 hres = E_FAIL;
7557 break;
7560 TRACE("-- 0x%08x\n", hres);
7561 return hres;
7563 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7564 VARDESC *var_desc;
7566 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7567 if(FAILED(hres)) return hres;
7569 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7570 dump_VARDESC(var_desc);
7571 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7572 return E_NOTIMPL;
7575 /* not found, look for it in inherited interfaces */
7576 ITypeInfo2_GetTypeKind(iface, &type_kind);
7577 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7578 if(This->impltypes) {
7579 /* recursive search */
7580 ITypeInfo *pTInfo;
7581 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7582 if(SUCCEEDED(hres)){
7583 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7584 ITypeInfo_Release(pTInfo);
7585 return hres;
7587 WARN("Could not search inherited interface!\n");
7590 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7591 return DISP_E_MEMBERNOTFOUND;
7594 /* ITypeInfo::GetDocumentation
7596 * Retrieves the documentation string, the complete Help file name and path,
7597 * and the context ID for the Help topic for a specified type description.
7599 * (Can be tested by the Visual Basic Editor in Word for instance.)
7601 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7602 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7603 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7605 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7606 const TLBFuncDesc *pFDesc;
7607 const TLBVarDesc *pVDesc;
7608 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7609 " HelpContext(%p) HelpFile(%p)\n",
7610 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7611 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7612 if(pBstrName)
7613 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7614 if(pBstrDocString)
7615 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7616 if(pdwHelpContext)
7617 *pdwHelpContext=This->dwHelpContext;
7618 if(pBstrHelpFile)
7619 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7620 return S_OK;
7621 }else {/* for a member */
7622 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7623 if(pFDesc){
7624 if(pBstrName)
7625 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7626 if(pBstrDocString)
7627 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7628 if(pdwHelpContext)
7629 *pdwHelpContext=pFDesc->helpcontext;
7630 if(pBstrHelpFile)
7631 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7632 return S_OK;
7634 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7635 if(pVDesc){
7636 if(pBstrName)
7637 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7638 if(pBstrDocString)
7639 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7640 if(pdwHelpContext)
7641 *pdwHelpContext=pVDesc->HelpContext;
7642 if(pBstrHelpFile)
7643 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7644 return S_OK;
7648 if(This->impltypes &&
7649 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7650 /* recursive search */
7651 ITypeInfo *pTInfo;
7652 HRESULT result;
7653 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7654 if(SUCCEEDED(result)) {
7655 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7656 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7657 ITypeInfo_Release(pTInfo);
7658 return result;
7660 WARN("Could not search inherited interface!\n");
7663 WARN("member %d not found\n", memid);
7664 return TYPE_E_ELEMENTNOTFOUND;
7667 /* ITypeInfo::GetDllEntry
7669 * Retrieves a description or specification of an entry point for a function
7670 * in a DLL.
7672 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7673 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7674 WORD *pwOrdinal)
7676 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7677 const TLBFuncDesc *pFDesc;
7679 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7681 if (pBstrDllName) *pBstrDllName = NULL;
7682 if (pBstrName) *pBstrName = NULL;
7683 if (pwOrdinal) *pwOrdinal = 0;
7685 if (This->typeattr.typekind != TKIND_MODULE)
7686 return TYPE_E_BADMODULEKIND;
7688 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7689 if(pFDesc){
7690 dump_TypeInfo(This);
7691 if (TRACE_ON(ole))
7692 dump_TLBFuncDescOne(pFDesc);
7694 if (pBstrDllName)
7695 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7697 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7698 if (pBstrName)
7699 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7700 if (pwOrdinal)
7701 *pwOrdinal = -1;
7702 return S_OK;
7704 if (pBstrName)
7705 *pBstrName = NULL;
7706 if (pwOrdinal)
7707 *pwOrdinal = LOWORD(pFDesc->Entry);
7708 return S_OK;
7710 return TYPE_E_ELEMENTNOTFOUND;
7713 /* internal function to make the inherited interfaces' methods appear
7714 * part of the interface */
7715 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7716 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7718 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7719 HRESULT hr;
7721 TRACE("%p, 0x%x\n", iface, *hRefType);
7723 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7725 ITypeInfo *pSubTypeInfo;
7727 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7728 if (FAILED(hr))
7729 return hr;
7731 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7732 hRefType, ppTInfo);
7733 ITypeInfo_Release(pSubTypeInfo);
7734 if (SUCCEEDED(hr))
7735 return hr;
7737 *hRefType -= DISPATCH_HREF_OFFSET;
7739 if (!(*hRefType & DISPATCH_HREF_MASK))
7740 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7741 else
7742 return E_FAIL;
7745 struct search_res_tlb_params
7747 const GUID *guid;
7748 ITypeLib *pTLib;
7751 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7753 struct search_res_tlb_params *params = (LPVOID)lParam;
7754 static const WCHAR formatW[] = {'\\','%','d',0};
7755 WCHAR szPath[MAX_PATH+1];
7756 ITypeLib *pTLib = NULL;
7757 HRESULT ret;
7758 DWORD len;
7760 if (IS_INTRESOURCE(lpszName) == FALSE)
7761 return TRUE;
7763 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7764 return TRUE;
7766 if (snprintfW(szPath + len, ARRAY_SIZE(szPath) - len, formatW, LOWORD(lpszName)) < 0)
7767 return TRUE;
7769 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7770 if (SUCCEEDED(ret))
7772 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7773 if (IsEqualGUID(params->guid, impl->guid))
7775 params->pTLib = pTLib;
7776 return FALSE; /* stop enumeration */
7778 ITypeLib_Release(pTLib);
7781 return TRUE;
7784 /* ITypeInfo::GetRefTypeInfo
7786 * If a type description references other type descriptions, it retrieves
7787 * the referenced type descriptions.
7789 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7790 ITypeInfo2 *iface,
7791 HREFTYPE hRefType,
7792 ITypeInfo **ppTInfo)
7794 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7795 HRESULT result = E_FAIL;
7797 if(!ppTInfo)
7798 return E_INVALIDARG;
7800 if ((INT)hRefType < 0) {
7801 ITypeInfoImpl *pTypeInfoImpl;
7803 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7804 !(This->typeattr.typekind == TKIND_INTERFACE ||
7805 This->typeattr.typekind == TKIND_DISPATCH))
7806 return TYPE_E_ELEMENTNOTFOUND;
7808 /* when we meet a DUAL typeinfo, we must create the alternate
7809 * version of it.
7811 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7813 *pTypeInfoImpl = *This;
7814 pTypeInfoImpl->ref = 0;
7815 list_init(&pTypeInfoImpl->custdata_list);
7817 if (This->typeattr.typekind == TKIND_INTERFACE)
7818 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7819 else
7820 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7822 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7823 /* the AddRef implicitly adds a reference to the parent typelib, which
7824 * stops the copied data from being destroyed until the new typeinfo's
7825 * refcount goes to zero, but we need to signal to the new instance to
7826 * not free its data structures when it is destroyed */
7827 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7829 ITypeInfo_AddRef(*ppTInfo);
7831 result = S_OK;
7832 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7833 (This->typeattr.typekind == TKIND_DISPATCH))
7835 HREFTYPE href_dispatch = hRefType;
7836 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7837 } else {
7838 TLBRefType *ref_type;
7839 ITypeLib *pTLib = NULL;
7840 UINT i;
7842 if(!(hRefType & 0x1)){
7843 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7845 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7847 result = S_OK;
7848 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7849 ITypeInfo_AddRef(*ppTInfo);
7850 goto end;
7855 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7857 if(ref_type->reference == (hRefType & (~0x3)))
7858 break;
7860 if(&ref_type->entry == &This->pTypeLib->ref_list)
7862 FIXME("Can't find pRefType for ref %x\n", hRefType);
7863 goto end;
7866 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7867 UINT Index;
7868 TRACE("internal reference\n");
7869 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7870 } else {
7871 if(ref_type->pImpTLInfo->pImpTypeLib) {
7872 TRACE("typeinfo in imported typelib that is already loaded\n");
7873 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7874 ITypeLib_AddRef(pTLib);
7875 result = S_OK;
7876 } else {
7877 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7878 struct search_res_tlb_params params;
7879 BSTR libnam;
7881 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7883 /* Search in resource table */
7884 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7885 params.pTLib = NULL;
7886 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7887 pTLib = params.pTLib;
7888 result = S_OK;
7890 if (!pTLib)
7892 /* Search on disk */
7893 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7894 ref_type->pImpTLInfo->wVersionMajor,
7895 ref_type->pImpTLInfo->wVersionMinor,
7896 This->pTypeLib->syskind,
7897 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7898 if (FAILED(result))
7899 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7901 result = LoadTypeLib(libnam, &pTLib);
7902 SysFreeString(libnam);
7905 if(SUCCEEDED(result)) {
7906 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7907 ITypeLib_AddRef(pTLib);
7911 if(SUCCEEDED(result)) {
7912 if(ref_type->index == TLB_REF_USE_GUID)
7913 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7914 else
7915 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7917 if (pTLib != NULL)
7918 ITypeLib_Release(pTLib);
7921 end:
7922 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7923 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7924 return result;
7927 /* ITypeInfo::AddressOfMember
7929 * Retrieves the addresses of static functions or variables, such as those
7930 * defined in a DLL.
7932 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7933 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7935 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7936 HRESULT hr;
7937 BSTR dll, entry;
7938 WORD ordinal;
7939 HMODULE module;
7941 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7943 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7944 if (FAILED(hr))
7945 return hr;
7947 module = LoadLibraryW(dll);
7948 if (!module)
7950 ERR("couldn't load %s\n", debugstr_w(dll));
7951 SysFreeString(dll);
7952 SysFreeString(entry);
7953 return STG_E_FILENOTFOUND;
7955 /* FIXME: store library somewhere where we can free it */
7957 if (entry)
7959 LPSTR entryA;
7960 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7961 entryA = heap_alloc(len);
7962 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7964 *ppv = GetProcAddress(module, entryA);
7965 if (!*ppv)
7966 ERR("function not found %s\n", debugstr_a(entryA));
7968 heap_free(entryA);
7970 else
7972 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7973 if (!*ppv)
7974 ERR("function not found %d\n", ordinal);
7977 SysFreeString(dll);
7978 SysFreeString(entry);
7980 if (!*ppv)
7981 return TYPE_E_DLLFUNCTIONNOTFOUND;
7983 return S_OK;
7986 /* ITypeInfo::CreateInstance
7988 * Creates a new instance of a type that describes a component object class
7989 * (coclass).
7991 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7992 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7994 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7995 HRESULT hr;
7996 TYPEATTR *pTA;
7998 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
8000 *ppvObj = NULL;
8002 if(pOuterUnk)
8004 WARN("Not able to aggregate\n");
8005 return CLASS_E_NOAGGREGATION;
8008 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8009 if(FAILED(hr)) return hr;
8011 if(pTA->typekind != TKIND_COCLASS)
8013 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8014 hr = E_INVALIDARG;
8015 goto end;
8018 hr = S_FALSE;
8019 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8021 IUnknown *pUnk;
8022 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8023 TRACE("GetActiveObject rets %08x\n", hr);
8024 if(hr == S_OK)
8026 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8027 IUnknown_Release(pUnk);
8031 if(hr != S_OK)
8032 hr = CoCreateInstance(&pTA->guid, NULL,
8033 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8034 riid, ppvObj);
8036 end:
8037 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8038 return hr;
8041 /* ITypeInfo::GetMops
8043 * Retrieves marshalling information.
8045 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8046 BSTR *pBstrMops)
8048 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8049 FIXME("(%p %d) stub!\n", This, memid);
8050 *pBstrMops = NULL;
8051 return S_OK;
8054 /* ITypeInfo::GetContainingTypeLib
8056 * Retrieves the containing type library and the index of the type description
8057 * within that type library.
8059 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8060 ITypeLib * *ppTLib, UINT *pIndex)
8062 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8064 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8065 if (pIndex) {
8066 *pIndex=This->index;
8067 TRACE("returning pIndex=%d\n", *pIndex);
8070 if (ppTLib) {
8071 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8072 ITypeLib_AddRef(*ppTLib);
8073 TRACE("returning ppTLib=%p\n", *ppTLib);
8076 return S_OK;
8079 /* ITypeInfo::ReleaseTypeAttr
8081 * Releases a TYPEATTR previously returned by Get
8084 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8085 TYPEATTR* pTypeAttr)
8087 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8088 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8089 heap_free(pTypeAttr);
8092 /* ITypeInfo::ReleaseFuncDesc
8094 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8096 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8097 ITypeInfo2 *iface,
8098 FUNCDESC *pFuncDesc)
8100 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8101 SHORT i;
8103 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8105 for (i = 0; i < pFuncDesc->cParams; i++)
8106 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8107 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8109 SysFreeString((BSTR)pFuncDesc);
8112 /* ITypeInfo::ReleaseVarDesc
8114 * Releases a VARDESC previously returned by GetVarDesc.
8116 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8117 VARDESC *pVarDesc)
8119 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8120 TRACE("(%p)->(%p)\n", This, pVarDesc);
8122 TLB_FreeVarDesc(pVarDesc);
8125 /* ITypeInfo2::GetTypeKind
8127 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8130 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8131 TYPEKIND *pTypeKind)
8133 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8134 *pTypeKind = This->typeattr.typekind;
8135 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8136 return S_OK;
8139 /* ITypeInfo2::GetTypeFlags
8141 * Returns the type flags without any allocations. This returns a DWORD type
8142 * flag, which expands the type flags without growing the TYPEATTR (type
8143 * attribute).
8146 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8148 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8149 *pTypeFlags=This->typeattr.wTypeFlags;
8150 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8151 return S_OK;
8154 /* ITypeInfo2::GetFuncIndexOfMemId
8155 * Binds to a specific member based on a known DISPID, where the member name
8156 * is not known (for example, when binding to a default member).
8159 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8160 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8162 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8163 UINT fdc;
8164 HRESULT result;
8166 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8167 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8168 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8169 break;
8171 if(fdc < This->typeattr.cFuncs) {
8172 *pFuncIndex = fdc;
8173 result = S_OK;
8174 } else
8175 result = TYPE_E_ELEMENTNOTFOUND;
8177 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8178 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8179 return result;
8182 /* TypeInfo2::GetVarIndexOfMemId
8184 * Binds to a specific member based on a known DISPID, where the member name
8185 * is not known (for example, when binding to a default member).
8188 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8189 MEMBERID memid, UINT *pVarIndex)
8191 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8192 TLBVarDesc *pVarInfo;
8194 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8196 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8197 if(!pVarInfo)
8198 return TYPE_E_ELEMENTNOTFOUND;
8200 *pVarIndex = (pVarInfo - This->vardescs);
8202 return S_OK;
8205 /* ITypeInfo2::GetCustData
8207 * Gets the custom data
8209 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8210 ITypeInfo2 * iface,
8211 REFGUID guid,
8212 VARIANT *pVarVal)
8214 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8215 TLBCustData *pCData;
8217 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8219 if(!guid || !pVarVal)
8220 return E_INVALIDARG;
8222 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8224 VariantInit( pVarVal);
8225 if (pCData)
8226 VariantCopy( pVarVal, &pCData->data);
8227 else
8228 VariantClear( pVarVal );
8229 return S_OK;
8232 /* ITypeInfo2::GetFuncCustData
8234 * Gets the custom data
8236 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8237 ITypeInfo2 * iface,
8238 UINT index,
8239 REFGUID guid,
8240 VARIANT *pVarVal)
8242 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8243 TLBCustData *pCData;
8244 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8246 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8248 if(index >= This->typeattr.cFuncs)
8249 return TYPE_E_ELEMENTNOTFOUND;
8251 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8252 if(!pCData)
8253 return TYPE_E_ELEMENTNOTFOUND;
8255 VariantInit(pVarVal);
8256 VariantCopy(pVarVal, &pCData->data);
8258 return S_OK;
8261 /* ITypeInfo2::GetParamCustData
8263 * Gets the custom data
8265 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8266 ITypeInfo2 * iface,
8267 UINT indexFunc,
8268 UINT indexParam,
8269 REFGUID guid,
8270 VARIANT *pVarVal)
8272 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8273 TLBCustData *pCData;
8274 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8276 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8277 debugstr_guid(guid), pVarVal);
8279 if(indexFunc >= This->typeattr.cFuncs)
8280 return TYPE_E_ELEMENTNOTFOUND;
8282 if(indexParam >= pFDesc->funcdesc.cParams)
8283 return TYPE_E_ELEMENTNOTFOUND;
8285 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8286 if(!pCData)
8287 return TYPE_E_ELEMENTNOTFOUND;
8289 VariantInit(pVarVal);
8290 VariantCopy(pVarVal, &pCData->data);
8292 return S_OK;
8295 /* ITypeInfo2::GetVarCustData
8297 * Gets the custom data
8299 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8300 ITypeInfo2 * iface,
8301 UINT index,
8302 REFGUID guid,
8303 VARIANT *pVarVal)
8305 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8306 TLBCustData *pCData;
8307 TLBVarDesc *pVDesc = &This->vardescs[index];
8309 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8311 if(index >= This->typeattr.cVars)
8312 return TYPE_E_ELEMENTNOTFOUND;
8314 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8315 if(!pCData)
8316 return TYPE_E_ELEMENTNOTFOUND;
8318 VariantInit(pVarVal);
8319 VariantCopy(pVarVal, &pCData->data);
8321 return S_OK;
8324 /* ITypeInfo2::GetImplCustData
8326 * Gets the custom data
8328 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8329 ITypeInfo2 * iface,
8330 UINT index,
8331 REFGUID guid,
8332 VARIANT *pVarVal)
8334 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8335 TLBCustData *pCData;
8336 TLBImplType *pRDesc = &This->impltypes[index];
8338 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8340 if(index >= This->typeattr.cImplTypes)
8341 return TYPE_E_ELEMENTNOTFOUND;
8343 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8344 if(!pCData)
8345 return TYPE_E_ELEMENTNOTFOUND;
8347 VariantInit(pVarVal);
8348 VariantCopy(pVarVal, &pCData->data);
8350 return S_OK;
8353 /* ITypeInfo2::GetDocumentation2
8355 * Retrieves the documentation string, the complete Help file name and path,
8356 * the localization context to use, and the context ID for the library Help
8357 * topic in the Help file.
8360 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8361 ITypeInfo2 * iface,
8362 MEMBERID memid,
8363 LCID lcid,
8364 BSTR *pbstrHelpString,
8365 DWORD *pdwHelpStringContext,
8366 BSTR *pbstrHelpStringDll)
8368 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8369 const TLBFuncDesc *pFDesc;
8370 const TLBVarDesc *pVDesc;
8371 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8372 "HelpStringContext(%p) HelpStringDll(%p)\n",
8373 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8374 pbstrHelpStringDll );
8375 /* the help string should be obtained from the helpstringdll,
8376 * using the _DLLGetDocumentation function, based on the supplied
8377 * lcid. Nice to do sometime...
8379 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8380 if(pbstrHelpString)
8381 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8382 if(pdwHelpStringContext)
8383 *pdwHelpStringContext=This->dwHelpStringContext;
8384 if(pbstrHelpStringDll)
8385 *pbstrHelpStringDll=
8386 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8387 return S_OK;
8388 }else {/* for a member */
8389 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8390 if(pFDesc){
8391 if(pbstrHelpString)
8392 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8393 if(pdwHelpStringContext)
8394 *pdwHelpStringContext=pFDesc->HelpStringContext;
8395 if(pbstrHelpStringDll)
8396 *pbstrHelpStringDll=
8397 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8398 return S_OK;
8400 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8401 if(pVDesc){
8402 if(pbstrHelpString)
8403 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8404 if(pdwHelpStringContext)
8405 *pdwHelpStringContext=pVDesc->HelpStringContext;
8406 if(pbstrHelpStringDll)
8407 *pbstrHelpStringDll=
8408 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8409 return S_OK;
8412 return TYPE_E_ELEMENTNOTFOUND;
8415 /* ITypeInfo2::GetAllCustData
8417 * Gets all custom data items for the Type info.
8420 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8421 ITypeInfo2 * iface,
8422 CUSTDATA *pCustData)
8424 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8426 TRACE("%p %p\n", This, pCustData);
8428 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8431 /* ITypeInfo2::GetAllFuncCustData
8433 * Gets all custom data items for the specified Function
8436 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8437 ITypeInfo2 * iface,
8438 UINT index,
8439 CUSTDATA *pCustData)
8441 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8442 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8444 TRACE("%p %u %p\n", This, index, pCustData);
8446 if(index >= This->typeattr.cFuncs)
8447 return TYPE_E_ELEMENTNOTFOUND;
8449 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8452 /* ITypeInfo2::GetAllParamCustData
8454 * Gets all custom data items for the Functions
8457 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8458 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8460 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8461 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8463 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8465 if(indexFunc >= This->typeattr.cFuncs)
8466 return TYPE_E_ELEMENTNOTFOUND;
8468 if(indexParam >= pFDesc->funcdesc.cParams)
8469 return TYPE_E_ELEMENTNOTFOUND;
8471 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8474 /* ITypeInfo2::GetAllVarCustData
8476 * Gets all custom data items for the specified Variable
8479 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8480 UINT index, CUSTDATA *pCustData)
8482 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8483 TLBVarDesc * pVDesc = &This->vardescs[index];
8485 TRACE("%p %u %p\n", This, index, pCustData);
8487 if(index >= This->typeattr.cVars)
8488 return TYPE_E_ELEMENTNOTFOUND;
8490 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8493 /* ITypeInfo2::GetAllImplCustData
8495 * Gets all custom data items for the specified implementation type
8498 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8499 ITypeInfo2 * iface,
8500 UINT index,
8501 CUSTDATA *pCustData)
8503 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8504 TLBImplType *pRDesc = &This->impltypes[index];
8506 TRACE("%p %u %p\n", This, index, pCustData);
8508 if(index >= This->typeattr.cImplTypes)
8509 return TYPE_E_ELEMENTNOTFOUND;
8511 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8514 static const ITypeInfo2Vtbl tinfvt =
8517 ITypeInfo_fnQueryInterface,
8518 ITypeInfo_fnAddRef,
8519 ITypeInfo_fnRelease,
8521 ITypeInfo_fnGetTypeAttr,
8522 ITypeInfo_fnGetTypeComp,
8523 ITypeInfo_fnGetFuncDesc,
8524 ITypeInfo_fnGetVarDesc,
8525 ITypeInfo_fnGetNames,
8526 ITypeInfo_fnGetRefTypeOfImplType,
8527 ITypeInfo_fnGetImplTypeFlags,
8528 ITypeInfo_fnGetIDsOfNames,
8529 ITypeInfo_fnInvoke,
8530 ITypeInfo_fnGetDocumentation,
8531 ITypeInfo_fnGetDllEntry,
8532 ITypeInfo_fnGetRefTypeInfo,
8533 ITypeInfo_fnAddressOfMember,
8534 ITypeInfo_fnCreateInstance,
8535 ITypeInfo_fnGetMops,
8536 ITypeInfo_fnGetContainingTypeLib,
8537 ITypeInfo_fnReleaseTypeAttr,
8538 ITypeInfo_fnReleaseFuncDesc,
8539 ITypeInfo_fnReleaseVarDesc,
8541 ITypeInfo2_fnGetTypeKind,
8542 ITypeInfo2_fnGetTypeFlags,
8543 ITypeInfo2_fnGetFuncIndexOfMemId,
8544 ITypeInfo2_fnGetVarIndexOfMemId,
8545 ITypeInfo2_fnGetCustData,
8546 ITypeInfo2_fnGetFuncCustData,
8547 ITypeInfo2_fnGetParamCustData,
8548 ITypeInfo2_fnGetVarCustData,
8549 ITypeInfo2_fnGetImplTypeCustData,
8550 ITypeInfo2_fnGetDocumentation2,
8551 ITypeInfo2_fnGetAllCustData,
8552 ITypeInfo2_fnGetAllFuncCustData,
8553 ITypeInfo2_fnGetAllParamCustData,
8554 ITypeInfo2_fnGetAllVarCustData,
8555 ITypeInfo2_fnGetAllImplTypeCustData,
8558 /******************************************************************************
8559 * CreateDispTypeInfo [OLEAUT32.31]
8561 * Build type information for an object so it can be called through an
8562 * IDispatch interface.
8564 * RETURNS
8565 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8566 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8568 * NOTES
8569 * This call allows an objects methods to be accessed through IDispatch, by
8570 * building an ITypeInfo object that IDispatch can use to call through.
8572 HRESULT WINAPI CreateDispTypeInfo(
8573 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8574 LCID lcid, /* [I] Locale Id */
8575 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8577 ITypeInfoImpl *pTIClass, *pTIIface;
8578 ITypeLibImpl *pTypeLibImpl;
8579 unsigned int param, func;
8580 TLBFuncDesc *pFuncDesc;
8581 TLBRefType *ref;
8583 TRACE("\n");
8584 pTypeLibImpl = TypeLibImpl_Constructor();
8585 if (!pTypeLibImpl) return E_FAIL;
8587 pTypeLibImpl->TypeInfoCount = 2;
8588 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8590 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8591 pTIIface->pTypeLib = pTypeLibImpl;
8592 pTIIface->index = 0;
8593 pTIIface->Name = NULL;
8594 pTIIface->dwHelpContext = -1;
8595 pTIIface->guid = NULL;
8596 pTIIface->typeattr.lcid = lcid;
8597 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8598 pTIIface->typeattr.wMajorVerNum = 0;
8599 pTIIface->typeattr.wMinorVerNum = 0;
8600 pTIIface->typeattr.cbAlignment = 2;
8601 pTIIface->typeattr.cbSizeInstance = -1;
8602 pTIIface->typeattr.cbSizeVft = -1;
8603 pTIIface->typeattr.cFuncs = 0;
8604 pTIIface->typeattr.cImplTypes = 0;
8605 pTIIface->typeattr.cVars = 0;
8606 pTIIface->typeattr.wTypeFlags = 0;
8607 pTIIface->hreftype = 0;
8609 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8610 pFuncDesc = pTIIface->funcdescs;
8611 for(func = 0; func < pidata->cMembers; func++) {
8612 METHODDATA *md = pidata->pmethdata + func;
8613 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8614 pFuncDesc->funcdesc.memid = md->dispid;
8615 pFuncDesc->funcdesc.lprgscode = NULL;
8616 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8617 pFuncDesc->funcdesc.invkind = md->wFlags;
8618 pFuncDesc->funcdesc.callconv = md->cc;
8619 pFuncDesc->funcdesc.cParams = md->cArgs;
8620 pFuncDesc->funcdesc.cParamsOpt = 0;
8621 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8622 pFuncDesc->funcdesc.cScodes = 0;
8623 pFuncDesc->funcdesc.wFuncFlags = 0;
8624 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8625 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8626 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8627 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8628 md->cArgs * sizeof(ELEMDESC));
8629 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8630 for(param = 0; param < md->cArgs; param++) {
8631 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8632 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8634 pFuncDesc->helpcontext = 0;
8635 pFuncDesc->HelpStringContext = 0;
8636 pFuncDesc->HelpString = NULL;
8637 pFuncDesc->Entry = NULL;
8638 list_init(&pFuncDesc->custdata_list);
8639 pTIIface->typeattr.cFuncs++;
8640 ++pFuncDesc;
8643 dump_TypeInfo(pTIIface);
8645 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8646 pTIClass->pTypeLib = pTypeLibImpl;
8647 pTIClass->index = 1;
8648 pTIClass->Name = NULL;
8649 pTIClass->dwHelpContext = -1;
8650 pTIClass->guid = NULL;
8651 pTIClass->typeattr.lcid = lcid;
8652 pTIClass->typeattr.typekind = TKIND_COCLASS;
8653 pTIClass->typeattr.wMajorVerNum = 0;
8654 pTIClass->typeattr.wMinorVerNum = 0;
8655 pTIClass->typeattr.cbAlignment = 2;
8656 pTIClass->typeattr.cbSizeInstance = -1;
8657 pTIClass->typeattr.cbSizeVft = -1;
8658 pTIClass->typeattr.cFuncs = 0;
8659 pTIClass->typeattr.cImplTypes = 1;
8660 pTIClass->typeattr.cVars = 0;
8661 pTIClass->typeattr.wTypeFlags = 0;
8662 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8664 pTIClass->impltypes = TLBImplType_Alloc(1);
8666 ref = heap_alloc_zero(sizeof(*ref));
8667 ref->pImpTLInfo = TLB_REF_INTERNAL;
8668 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8670 dump_TypeInfo(pTIClass);
8672 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8674 ITypeInfo_AddRef(*pptinfo);
8675 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8677 return S_OK;
8681 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8683 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8685 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8688 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8690 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8692 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8695 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8697 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8699 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8702 static HRESULT WINAPI ITypeComp_fnBind(
8703 ITypeComp * iface,
8704 OLECHAR * szName,
8705 ULONG lHash,
8706 WORD wFlags,
8707 ITypeInfo ** ppTInfo,
8708 DESCKIND * pDescKind,
8709 BINDPTR * pBindPtr)
8711 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8712 const TLBFuncDesc *pFDesc;
8713 const TLBVarDesc *pVDesc;
8714 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8715 UINT fdc;
8717 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8719 *pDescKind = DESCKIND_NONE;
8720 pBindPtr->lpfuncdesc = NULL;
8721 *ppTInfo = NULL;
8723 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8724 pFDesc = &This->funcdescs[fdc];
8725 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8726 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8727 break;
8728 else
8729 /* name found, but wrong flags */
8730 hr = TYPE_E_TYPEMISMATCH;
8734 if (fdc < This->typeattr.cFuncs)
8736 HRESULT hr = TLB_AllocAndInitFuncDesc(
8737 &pFDesc->funcdesc,
8738 &pBindPtr->lpfuncdesc,
8739 This->typeattr.typekind == TKIND_DISPATCH);
8740 if (FAILED(hr))
8741 return hr;
8742 *pDescKind = DESCKIND_FUNCDESC;
8743 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8744 ITypeInfo_AddRef(*ppTInfo);
8745 return S_OK;
8746 } else {
8747 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8748 if(pVDesc){
8749 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8750 if (FAILED(hr))
8751 return hr;
8752 *pDescKind = DESCKIND_VARDESC;
8753 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8754 ITypeInfo_AddRef(*ppTInfo);
8755 return S_OK;
8759 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8760 /* recursive search */
8761 ITypeInfo *pTInfo;
8762 ITypeComp *pTComp;
8763 HRESULT hr;
8764 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8765 if (SUCCEEDED(hr))
8767 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8768 ITypeInfo_Release(pTInfo);
8770 if (SUCCEEDED(hr))
8772 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8773 ITypeComp_Release(pTComp);
8774 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8775 This->typeattr.typekind == TKIND_DISPATCH)
8777 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8778 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8779 SysFreeString((BSTR)tmp);
8781 return hr;
8783 WARN("Could not search inherited interface!\n");
8785 if (hr == DISP_E_MEMBERNOTFOUND)
8786 hr = S_OK;
8787 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8788 return hr;
8791 static HRESULT WINAPI ITypeComp_fnBindType(
8792 ITypeComp * iface,
8793 OLECHAR * szName,
8794 ULONG lHash,
8795 ITypeInfo ** ppTInfo,
8796 ITypeComp ** ppTComp)
8798 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8800 /* strange behaviour (does nothing) but like the
8801 * original */
8803 if (!ppTInfo || !ppTComp)
8804 return E_POINTER;
8806 *ppTInfo = NULL;
8807 *ppTComp = NULL;
8809 return S_OK;
8812 static const ITypeCompVtbl tcompvt =
8815 ITypeComp_fnQueryInterface,
8816 ITypeComp_fnAddRef,
8817 ITypeComp_fnRelease,
8819 ITypeComp_fnBind,
8820 ITypeComp_fnBindType
8823 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8824 ICreateTypeLib2** ppctlib)
8826 ITypeLibImpl *This;
8827 HRESULT hres;
8829 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8831 if (!szFile) return E_INVALIDARG;
8833 This = TypeLibImpl_Constructor();
8834 if (!This)
8835 return E_OUTOFMEMORY;
8837 This->lcid = GetSystemDefaultLCID();
8838 This->syskind = syskind;
8839 This->ptr_size = get_ptr_size(syskind);
8841 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8842 if (!This->path) {
8843 ITypeLib2_Release(&This->ITypeLib2_iface);
8844 return E_OUTOFMEMORY;
8846 lstrcpyW(This->path, szFile);
8848 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8849 ITypeLib2_Release(&This->ITypeLib2_iface);
8850 return hres;
8853 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8854 REFIID riid, void **object)
8856 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8858 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8861 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8863 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8865 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8868 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8870 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8872 return ITypeLib2_Release(&This->ITypeLib2_iface);
8875 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8876 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8878 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8879 ITypeInfoImpl *info;
8880 HRESULT hres;
8882 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8884 if (!ctinfo || !name)
8885 return E_INVALIDARG;
8887 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8888 if (info)
8889 return TYPE_E_NAMECONFLICT;
8891 if (This->typeinfos)
8892 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8893 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8894 else
8895 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8897 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8899 info->pTypeLib = This;
8900 info->Name = TLB_append_str(&This->name_list, name);
8901 info->index = This->TypeInfoCount;
8902 info->typeattr.typekind = kind;
8903 info->typeattr.cbAlignment = 4;
8905 switch (info->typeattr.typekind) {
8906 case TKIND_ENUM:
8907 case TKIND_INTERFACE:
8908 case TKIND_DISPATCH:
8909 case TKIND_COCLASS:
8910 info->typeattr.cbSizeInstance = This->ptr_size;
8911 break;
8912 case TKIND_RECORD:
8913 case TKIND_UNION:
8914 info->typeattr.cbSizeInstance = 0;
8915 break;
8916 case TKIND_MODULE:
8917 info->typeattr.cbSizeInstance = 2;
8918 break;
8919 case TKIND_ALIAS:
8920 info->typeattr.cbSizeInstance = -0x75;
8921 break;
8922 default:
8923 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8924 info->typeattr.cbSizeInstance = 0xdeadbeef;
8925 break;
8928 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8929 &IID_ICreateTypeInfo, (void **)ctinfo);
8930 if (FAILED(hres)) {
8931 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8932 return hres;
8935 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8937 ++This->TypeInfoCount;
8939 return S_OK;
8942 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8943 LPOLESTR name)
8945 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8947 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8949 if (!name)
8950 return E_INVALIDARG;
8952 This->Name = TLB_append_str(&This->name_list, name);
8954 return S_OK;
8957 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8958 WORD majorVerNum, WORD minorVerNum)
8960 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8962 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8964 This->ver_major = majorVerNum;
8965 This->ver_minor = minorVerNum;
8967 return S_OK;
8970 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8971 REFGUID guid)
8973 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8975 TRACE("%p %s\n", This, debugstr_guid(guid));
8977 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8979 return S_OK;
8982 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8983 LPOLESTR doc)
8985 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8987 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8989 if (!doc)
8990 return E_INVALIDARG;
8992 This->DocString = TLB_append_str(&This->string_list, doc);
8994 return S_OK;
8997 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8998 LPOLESTR helpFileName)
9000 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9002 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9004 if (!helpFileName)
9005 return E_INVALIDARG;
9007 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9009 return S_OK;
9012 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9013 DWORD helpContext)
9015 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9017 TRACE("%p %d\n", This, helpContext);
9019 This->dwHelpContext = helpContext;
9021 return S_OK;
9024 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9025 LCID lcid)
9027 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9029 TRACE("%p %x\n", This, lcid);
9031 This->set_lcid = lcid;
9033 return S_OK;
9036 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9037 UINT libFlags)
9039 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9041 TRACE("%p %x\n", This, libFlags);
9043 This->libflags = libFlags;
9045 return S_OK;
9048 typedef struct tagWMSFT_SegContents {
9049 DWORD len;
9050 void *data;
9051 } WMSFT_SegContents;
9053 typedef struct tagWMSFT_TLBFile {
9054 MSFT_Header header;
9055 WMSFT_SegContents typeinfo_seg;
9056 WMSFT_SegContents impfile_seg;
9057 WMSFT_SegContents impinfo_seg;
9058 WMSFT_SegContents ref_seg;
9059 WMSFT_SegContents guidhash_seg;
9060 WMSFT_SegContents guid_seg;
9061 WMSFT_SegContents namehash_seg;
9062 WMSFT_SegContents name_seg;
9063 WMSFT_SegContents string_seg;
9064 WMSFT_SegContents typdesc_seg;
9065 WMSFT_SegContents arraydesc_seg;
9066 WMSFT_SegContents custdata_seg;
9067 WMSFT_SegContents cdguids_seg;
9068 MSFT_SegDir segdir;
9069 WMSFT_SegContents aux_seg;
9070 } WMSFT_TLBFile;
9072 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9073 WMSFT_TLBFile *file)
9075 TLBString *str;
9076 UINT last_offs;
9077 char *data;
9079 file->string_seg.len = 0;
9080 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9081 int size;
9083 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
9084 if (size == 0)
9085 return E_UNEXPECTED;
9087 size += sizeof(INT16);
9088 if (size % 4)
9089 size = (size + 4) & ~0x3;
9090 if (size < 8)
9091 size = 8;
9093 file->string_seg.len += size;
9095 /* temporarily use str->offset to store the length of the aligned,
9096 * converted string */
9097 str->offset = size;
9100 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9102 last_offs = 0;
9103 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9104 int size;
9106 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9107 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9108 if (size == 0) {
9109 heap_free(file->string_seg.data);
9110 return E_UNEXPECTED;
9113 *((INT16*)data) = size;
9115 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9117 size = str->offset;
9118 data += size;
9119 str->offset = last_offs;
9120 last_offs += size;
9123 return S_OK;
9126 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9127 WMSFT_TLBFile *file)
9129 TLBString *str;
9130 UINT last_offs;
9131 char *data;
9132 MSFT_NameIntro *last_intro = NULL;
9134 file->header.nametablecount = 0;
9135 file->header.nametablechars = 0;
9137 file->name_seg.len = 0;
9138 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9139 int size;
9141 size = strlenW(str->str);
9142 file->header.nametablechars += size;
9143 file->header.nametablecount++;
9145 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9146 if (size == 0)
9147 return E_UNEXPECTED;
9149 size += sizeof(MSFT_NameIntro);
9150 if (size % 4)
9151 size = (size + 4) & ~0x3;
9152 if (size < 8)
9153 size = 8;
9155 file->name_seg.len += size;
9157 /* temporarily use str->offset to store the length of the aligned,
9158 * converted string */
9159 str->offset = size;
9162 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9163 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9165 last_offs = 0;
9166 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9167 int size, hash;
9168 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9170 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9171 data + sizeof(MSFT_NameIntro),
9172 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9173 if (size == 0) {
9174 heap_free(file->name_seg.data);
9175 return E_UNEXPECTED;
9177 data[sizeof(MSFT_NameIntro) + size] = '\0';
9179 intro->hreftype = -1; /* TODO? */
9180 intro->namelen = size & 0xFF;
9181 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9182 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9183 intro->namelen |= hash << 16;
9184 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9185 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9187 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9188 str->offset - size - sizeof(MSFT_NameIntro));
9190 /* update str->offset to actual value to use in other
9191 * compilation functions that require positions within
9192 * the string table */
9193 last_intro = intro;
9194 size = str->offset;
9195 data += size;
9196 str->offset = last_offs;
9197 last_offs += size;
9200 if(last_intro)
9201 last_intro->hreftype = 0; /* last one is 0? */
9203 return S_OK;
9206 static inline int hash_guid(GUID *guid)
9208 int i, hash = 0;
9210 for (i = 0; i < 8; i ++)
9211 hash ^= ((const short *)guid)[i];
9213 return hash & 0x1f;
9216 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9218 TLBGuid *guid;
9219 MSFT_GuidEntry *entry;
9220 DWORD offs;
9221 int hash_key, *guidhashtab;
9223 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9224 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9226 entry = file->guid_seg.data;
9227 offs = 0;
9228 guidhashtab = file->guidhash_seg.data;
9229 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9230 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9231 entry->hreftype = guid->hreftype;
9233 hash_key = hash_guid(&guid->guid);
9234 entry->next_hash = guidhashtab[hash_key];
9235 guidhashtab[hash_key] = offs;
9237 guid->offset = offs;
9238 offs += sizeof(MSFT_GuidEntry);
9239 ++entry;
9242 return S_OK;
9245 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9247 VARIANT v = *value;
9248 VARTYPE arg_type = V_VT(value);
9249 int mask = 0;
9250 HRESULT hres;
9251 DWORD ret = file->custdata_seg.len;
9253 if(arg_type == VT_INT)
9254 arg_type = VT_I4;
9255 if(arg_type == VT_UINT)
9256 arg_type = VT_UI4;
9258 v = *value;
9259 if(V_VT(value) != arg_type) {
9260 hres = VariantChangeType(&v, value, 0, arg_type);
9261 if(FAILED(hres)){
9262 ERR("VariantChangeType failed: %08x\n", hres);
9263 return -1;
9267 /* Check if default value can be stored in-place */
9268 switch(arg_type){
9269 case VT_I4:
9270 case VT_UI4:
9271 mask = 0x3ffffff;
9272 if(V_UI4(&v) > 0x3ffffff)
9273 break;
9274 /* fall through */
9275 case VT_I1:
9276 case VT_UI1:
9277 case VT_BOOL:
9278 if(!mask)
9279 mask = 0xff;
9280 /* fall through */
9281 case VT_I2:
9282 case VT_UI2:
9283 if(!mask)
9284 mask = 0xffff;
9285 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9288 /* have to allocate space in custdata_seg */
9289 switch(arg_type) {
9290 case VT_I4:
9291 case VT_R4:
9292 case VT_UI4:
9293 case VT_INT:
9294 case VT_UINT:
9295 case VT_HRESULT:
9296 case VT_PTR: {
9297 /* Construct the data to be allocated */
9298 int *data;
9300 if(file->custdata_seg.data){
9301 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9302 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9303 file->custdata_seg.len += sizeof(int) * 2;
9304 }else{
9305 file->custdata_seg.len = sizeof(int) * 2;
9306 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9309 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9310 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9312 /* TODO: Check if the encoded data is already present in custdata_seg */
9314 return ret;
9317 case VT_BSTR: {
9318 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9319 char *data;
9321 if(file->custdata_seg.data){
9322 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9323 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9324 file->custdata_seg.len += len;
9325 }else{
9326 file->custdata_seg.len = len;
9327 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9330 *((unsigned short *)data) = V_VT(value);
9331 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9332 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9333 if(V_BSTR(&v)[i] <= 0x7f)
9334 data[i+6] = V_BSTR(&v)[i];
9335 else
9336 data[i+6] = '?';
9338 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9339 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9340 data[i] = 0x57;
9342 /* TODO: Check if the encoded data is already present in custdata_seg */
9344 return ret;
9346 default:
9347 FIXME("Argument type not yet handled\n");
9348 return -1;
9352 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9354 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9356 DWORD offs = file->arraydesc_seg.len;
9357 DWORD *encoded;
9358 USHORT i;
9360 /* TODO: we should check for duplicates, but that's harder because each
9361 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9362 * at the library-level) */
9364 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9365 if(!file->arraydesc_seg.data)
9366 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9367 else
9368 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9369 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9371 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9372 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9373 for(i = 0; i < desc->cDims; ++i){
9374 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9375 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9378 return offs;
9381 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9383 DWORD junk;
9384 INT16 junk2;
9385 DWORD offs = 0;
9386 DWORD encoded[2];
9387 VARTYPE vt, subtype;
9388 char *data;
9390 if(!desc)
9391 return -1;
9393 if(!out_mix)
9394 out_mix = &junk;
9395 if(!out_size)
9396 out_size = &junk2;
9398 vt = desc->vt & VT_TYPEMASK;
9400 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9401 DWORD mix;
9402 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9403 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9404 *out_mix = 0x7FFF;
9405 *out_size += 2 * sizeof(DWORD);
9406 }else if(vt == VT_CARRAY){
9407 encoded[0] = desc->vt | (0x7FFE << 16);
9408 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9409 *out_mix = 0x7FFE;
9410 }else if(vt == VT_USERDEFINED){
9411 encoded[0] = desc->vt | (0x7FFF << 16);
9412 encoded[1] = desc->u.hreftype;
9413 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9414 }else{
9415 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9417 switch(vt){
9418 case VT_INT:
9419 subtype = VT_I4;
9420 break;
9421 case VT_UINT:
9422 subtype = VT_UI4;
9423 break;
9424 case VT_VOID:
9425 subtype = VT_EMPTY;
9426 break;
9427 default:
9428 subtype = vt;
9429 break;
9432 *out_mix = subtype;
9433 return 0x80000000 | (subtype << 16) | desc->vt;
9436 data = file->typdesc_seg.data;
9437 while(offs < file->typdesc_seg.len){
9438 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9439 return offs;
9440 offs += sizeof(encoded);
9443 file->typdesc_seg.len += sizeof(encoded);
9444 if(!file->typdesc_seg.data)
9445 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9446 else
9447 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9449 memcpy(&data[offs], encoded, sizeof(encoded));
9451 return offs;
9454 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9456 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9457 DWORD ret = cdguids_seg->len, offs;
9458 MSFT_CDGuid *cdguid;
9459 TLBCustData *cd;
9461 if(list_empty(custdata_list))
9462 return -1;
9464 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9465 if(!cdguids_seg->data){
9466 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9467 }else {
9468 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9469 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9472 offs = ret + sizeof(MSFT_CDGuid);
9473 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9474 cdguid->GuidOffset = cd->guid->offset;
9475 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9476 cdguid->next = offs;
9477 offs += sizeof(MSFT_CDGuid);
9478 ++cdguid;
9481 --cdguid;
9482 cdguid->next = -1;
9484 return ret;
9487 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9488 WMSFT_TLBFile *file)
9490 WMSFT_SegContents *aux_seg = &file->aux_seg;
9491 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9492 MSFT_VarRecord *varrecord;
9493 MSFT_FuncRecord *funcrecord;
9494 MEMBERID *memid;
9495 DWORD *name, *offsets, offs;
9497 for(i = 0; i < info->typeattr.cFuncs; ++i){
9498 TLBFuncDesc *desc = &info->funcdescs[i];
9500 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9502 /* optional fields */
9503 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9504 if(!list_empty(&desc->custdata_list))
9505 recorded_size += 7 * sizeof(INT);
9506 else if(desc->HelpStringContext != 0)
9507 recorded_size += 6 * sizeof(INT);
9508 /* res9? resA? */
9509 else if(desc->Entry)
9510 recorded_size += 3 * sizeof(INT);
9511 else if(desc->HelpString)
9512 recorded_size += 2 * sizeof(INT);
9513 else if(desc->helpcontext)
9514 recorded_size += sizeof(INT);
9516 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9518 for(j = 0; j < desc->funcdesc.cParams; ++j){
9519 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9520 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9521 break;
9525 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9528 for(i = 0; i < info->typeattr.cVars; ++i){
9529 TLBVarDesc *desc = &info->vardescs[i];
9531 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9533 /* optional fields */
9534 if(desc->HelpStringContext != 0)
9535 recorded_size += 5 * sizeof(INT);
9536 else if(!list_empty(&desc->custdata_list))
9537 recorded_size += 4 * sizeof(INT);
9538 /* res9? */
9539 else if(desc->HelpString)
9540 recorded_size += 2 * sizeof(INT);
9541 else if(desc->HelpContext != 0)
9542 recorded_size += sizeof(INT);
9544 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9547 if(!recorded_size && !extra_size)
9548 return ret;
9550 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9552 aux_seg->len += recorded_size + extra_size;
9554 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9556 if(aux_seg->data)
9557 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9558 else
9559 aux_seg->data = heap_alloc(aux_seg->len);
9561 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9563 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9564 offs = 0;
9566 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9567 for(i = 0; i < info->typeattr.cFuncs; ++i){
9568 TLBFuncDesc *desc = &info->funcdescs[i];
9569 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9571 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9572 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9573 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9574 funcrecord->VtableOffset = desc->funcdesc.oVft;
9576 /* FKCCIC:
9577 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9578 * ^^^funckind
9579 * ^^^ ^invkind
9580 * ^has_cust_data
9581 * ^^^^callconv
9582 * ^has_param_defaults
9583 * ^oEntry_is_intresource
9585 funcrecord->FKCCIC =
9586 desc->funcdesc.funckind |
9587 (desc->funcdesc.invkind << 3) |
9588 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9589 (desc->funcdesc.callconv << 8);
9591 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9592 funcrecord->FKCCIC |= 0x2000;
9594 for(j = 0; j < desc->funcdesc.cParams; ++j){
9595 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9596 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9597 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9600 if(paramdefault_size > 0)
9601 funcrecord->FKCCIC |= 0x1000;
9603 funcrecord->nrargs = desc->funcdesc.cParams;
9604 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9606 /* optional fields */
9607 /* res9? resA? */
9608 if(!list_empty(&desc->custdata_list)){
9609 size += 7 * sizeof(INT);
9610 funcrecord->HelpContext = desc->helpcontext;
9611 if(desc->HelpString)
9612 funcrecord->oHelpString = desc->HelpString->offset;
9613 else
9614 funcrecord->oHelpString = -1;
9615 if(!desc->Entry)
9616 funcrecord->oEntry = -1;
9617 else if(IS_INTRESOURCE(desc->Entry))
9618 funcrecord->oEntry = LOWORD(desc->Entry);
9619 else
9620 funcrecord->oEntry = desc->Entry->offset;
9621 funcrecord->res9 = -1;
9622 funcrecord->resA = -1;
9623 funcrecord->HelpStringContext = desc->HelpStringContext;
9624 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9625 }else if(desc->HelpStringContext != 0){
9626 size += 6 * sizeof(INT);
9627 funcrecord->HelpContext = desc->helpcontext;
9628 if(desc->HelpString)
9629 funcrecord->oHelpString = desc->HelpString->offset;
9630 else
9631 funcrecord->oHelpString = -1;
9632 if(!desc->Entry)
9633 funcrecord->oEntry = -1;
9634 else if(IS_INTRESOURCE(desc->Entry))
9635 funcrecord->oEntry = LOWORD(desc->Entry);
9636 else
9637 funcrecord->oEntry = desc->Entry->offset;
9638 funcrecord->res9 = -1;
9639 funcrecord->resA = -1;
9640 funcrecord->HelpStringContext = desc->HelpStringContext;
9641 }else if(desc->Entry){
9642 size += 3 * sizeof(INT);
9643 funcrecord->HelpContext = desc->helpcontext;
9644 if(desc->HelpString)
9645 funcrecord->oHelpString = desc->HelpString->offset;
9646 else
9647 funcrecord->oHelpString = -1;
9648 if(!desc->Entry)
9649 funcrecord->oEntry = -1;
9650 else if(IS_INTRESOURCE(desc->Entry))
9651 funcrecord->oEntry = LOWORD(desc->Entry);
9652 else
9653 funcrecord->oEntry = desc->Entry->offset;
9654 }else if(desc->HelpString){
9655 size += 2 * sizeof(INT);
9656 funcrecord->HelpContext = desc->helpcontext;
9657 funcrecord->oHelpString = desc->HelpString->offset;
9658 }else if(desc->helpcontext){
9659 size += sizeof(INT);
9660 funcrecord->HelpContext = desc->helpcontext;
9663 paramdefault = (DWORD*)((char *)funcrecord + size);
9664 size += paramdefault_size;
9666 for(j = 0; j < desc->funcdesc.cParams; ++j){
9667 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9669 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9670 if(desc->pParamDesc[j].Name)
9671 info->oName = desc->pParamDesc[j].Name->offset;
9672 else
9673 info->oName = -1;
9674 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9676 if(paramdefault_size){
9677 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9678 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9679 else if(paramdefault_size)
9680 *paramdefault = -1;
9681 ++paramdefault;
9684 size += sizeof(MSFT_ParameterInfo);
9687 funcrecord->Info = size | (i << 16); /* is it just the index? */
9689 *offsets = offs;
9690 offs += size;
9691 ++offsets;
9693 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9696 varrecord = (MSFT_VarRecord*)funcrecord;
9697 for(i = 0; i < info->typeattr.cVars; ++i){
9698 TLBVarDesc *desc = &info->vardescs[i];
9699 DWORD size = 5 * sizeof(INT);
9701 varrecord->vardescsize = sizeof(desc->vardesc);
9702 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9703 varrecord->Flags = desc->vardesc.wVarFlags;
9704 varrecord->VarKind = desc->vardesc.varkind;
9706 if(desc->vardesc.varkind == VAR_CONST){
9707 varrecord->vardescsize += sizeof(VARIANT);
9708 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9709 }else
9710 varrecord->OffsValue = desc->vardesc.u.oInst;
9712 /* res9? */
9713 if(desc->HelpStringContext != 0){
9714 size += 5 * sizeof(INT);
9715 varrecord->HelpContext = desc->HelpContext;
9716 if(desc->HelpString)
9717 varrecord->HelpString = desc->HelpString->offset;
9718 else
9719 varrecord->HelpString = -1;
9720 varrecord->res9 = -1;
9721 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9722 varrecord->HelpStringContext = desc->HelpStringContext;
9723 }else if(!list_empty(&desc->custdata_list)){
9724 size += 4 * sizeof(INT);
9725 varrecord->HelpContext = desc->HelpContext;
9726 if(desc->HelpString)
9727 varrecord->HelpString = desc->HelpString->offset;
9728 else
9729 varrecord->HelpString = -1;
9730 varrecord->res9 = -1;
9731 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9732 }else if(desc->HelpString){
9733 size += 2 * sizeof(INT);
9734 varrecord->HelpContext = desc->HelpContext;
9735 if(desc->HelpString)
9736 varrecord->HelpString = desc->HelpString->offset;
9737 else
9738 varrecord->HelpString = -1;
9739 }else if(desc->HelpContext != 0){
9740 size += sizeof(INT);
9741 varrecord->HelpContext = desc->HelpContext;
9744 varrecord->Info = size | (i << 16);
9746 *offsets = offs;
9747 offs += size;
9748 ++offsets;
9750 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9753 memid = (MEMBERID*)varrecord;
9754 for(i = 0; i < info->typeattr.cFuncs; ++i){
9755 TLBFuncDesc *desc = &info->funcdescs[i];
9756 *memid = desc->funcdesc.memid;
9757 ++memid;
9759 for(i = 0; i < info->typeattr.cVars; ++i){
9760 TLBVarDesc *desc = &info->vardescs[i];
9761 *memid = desc->vardesc.memid;
9762 ++memid;
9765 name = (UINT*)memid;
9766 for(i = 0; i < info->typeattr.cFuncs; ++i){
9767 TLBFuncDesc *desc = &info->funcdescs[i];
9768 if(desc->Name)
9769 *name = desc->Name->offset;
9770 else
9771 *name = -1;
9772 ++name;
9774 for(i = 0; i < info->typeattr.cVars; ++i){
9775 TLBVarDesc *desc = &info->vardescs[i];
9776 if(desc->Name)
9777 *name = desc->Name->offset;
9778 else
9779 *name = -1;
9780 ++name;
9783 return ret;
9786 typedef struct tagWMSFT_RefChunk {
9787 DWORD href;
9788 DWORD res04;
9789 DWORD res08;
9790 DWORD next;
9791 } WMSFT_RefChunk;
9793 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9795 DWORD offs = file->ref_seg.len, i;
9796 WMSFT_RefChunk *chunk;
9798 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9799 if(!file->ref_seg.data)
9800 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9801 else
9802 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9804 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9806 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9807 chunk->href = info->impltypes[i].hRef;
9808 chunk->res04 = info->impltypes[i].implflags;
9809 chunk->res08 = -1;
9810 if(i < info->typeattr.cImplTypes - 1)
9811 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9812 else
9813 chunk->next = -1;
9814 ++chunk;
9817 return offs;
9820 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9822 DWORD size;
9824 size = sizeof(MSFT_TypeInfoBase);
9826 if(data){
9827 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9828 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9829 base->typekind = TKIND_DISPATCH;
9830 else
9831 base->typekind = info->typeattr.typekind;
9832 base->typekind |= index << 16; /* TODO: There are some other flags here */
9833 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9834 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9835 base->res2 = 0;
9836 base->res3 = 0;
9837 base->res4 = 3;
9838 base->res5 = 0;
9839 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9840 base->res7 = 0;
9841 base->res8 = 0;
9842 base->res9 = 0;
9843 base->resA = 0;
9844 if(info->guid)
9845 base->posguid = info->guid->offset;
9846 else
9847 base->posguid = -1;
9848 base->flags = info->typeattr.wTypeFlags;
9849 if(info->Name) {
9850 base->NameOffset = info->Name->offset;
9852 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9853 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9854 }else {
9855 base->NameOffset = -1;
9857 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9858 if(info->DocString)
9859 base->docstringoffs = info->DocString->offset;
9860 else
9861 base->docstringoffs = -1;
9862 base->helpstringcontext = info->dwHelpStringContext;
9863 base->helpcontext = info->dwHelpContext;
9864 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9865 base->cImplTypes = info->typeattr.cImplTypes;
9866 base->cbSizeVft = info->typeattr.cbSizeVft;
9867 base->size = info->typeattr.cbSizeInstance;
9868 if(info->typeattr.typekind == TKIND_COCLASS){
9869 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9870 }else if(info->typeattr.typekind == TKIND_ALIAS){
9871 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9872 }else if(info->typeattr.typekind == TKIND_MODULE){
9873 if(info->DllName)
9874 base->datatype1 = info->DllName->offset;
9875 else
9876 base->datatype1 = -1;
9877 }else{
9878 if(info->typeattr.cImplTypes > 0)
9879 base->datatype1 = info->impltypes[0].hRef;
9880 else
9881 base->datatype1 = -1;
9883 base->datatype2 = index; /* FIXME: i think there's more here */
9884 base->res18 = 0;
9885 base->res19 = -1;
9888 return size;
9891 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9893 UINT i;
9895 file->typeinfo_seg.len = 0;
9896 for(i = 0; i < This->TypeInfoCount; ++i){
9897 ITypeInfoImpl *info = This->typeinfos[i];
9898 *junk = file->typeinfo_seg.len;
9899 ++junk;
9900 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9903 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9904 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9906 file->aux_seg.len = 0;
9907 file->aux_seg.data = NULL;
9909 file->typeinfo_seg.len = 0;
9910 for(i = 0; i < This->TypeInfoCount; ++i){
9911 ITypeInfoImpl *info = This->typeinfos[i];
9912 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9913 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9917 typedef struct tagWMSFT_ImpFile {
9918 INT guid_offs;
9919 LCID lcid;
9920 DWORD version;
9921 } WMSFT_ImpFile;
9923 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9925 TLBImpLib *implib;
9926 WMSFT_ImpFile *impfile;
9927 char *data;
9928 DWORD last_offs = 0;
9930 file->impfile_seg.len = 0;
9931 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9932 int size = 0;
9934 if(implib->name){
9935 WCHAR *path = strrchrW(implib->name, '\\');
9936 if(path)
9937 ++path;
9938 else
9939 path = implib->name;
9940 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9941 if (size == 0)
9942 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9945 size += sizeof(INT16);
9946 if (size % 4)
9947 size = (size + 4) & ~0x3;
9948 if (size < 8)
9949 size = 8;
9951 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9954 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9956 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9957 int strlen = 0, size;
9959 impfile = (WMSFT_ImpFile*)data;
9960 impfile->guid_offs = implib->guid->offset;
9961 impfile->lcid = implib->lcid;
9962 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9964 data += sizeof(WMSFT_ImpFile);
9966 if(implib->name){
9967 WCHAR *path= strrchrW(implib->name, '\\');
9968 if(path)
9969 ++path;
9970 else
9971 path = implib->name;
9972 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9973 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9974 if (strlen == 0)
9975 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9978 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9980 size = strlen + sizeof(INT16);
9981 if (size % 4)
9982 size = (size + 4) & ~0x3;
9983 if (size < 8)
9984 size = 8;
9985 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9987 data += size;
9988 implib->offset = last_offs;
9989 last_offs += size + sizeof(WMSFT_ImpFile);
9993 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9995 MSFT_ImpInfo *info;
9996 TLBRefType *ref_type;
9997 UINT i = 0;
9999 WMSFT_compile_impfile(This, file);
10001 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10002 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10004 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10005 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10006 if(ref_type->index == TLB_REF_USE_GUID){
10007 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10008 info->oGuid = ref_type->guid->offset;
10009 }else
10010 info->oGuid = ref_type->index;
10011 info->oImpFile = ref_type->pImpTLInfo->offset;
10012 ++i;
10013 ++info;
10017 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10019 file->guidhash_seg.len = 0x80;
10020 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10021 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10024 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10026 file->namehash_seg.len = 0x200;
10027 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10028 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10031 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10033 if(contents && contents->len){
10034 segdir->offset = *running_offset;
10035 segdir->length = contents->len;
10036 *running_offset += segdir->length;
10037 }else{
10038 segdir->offset = -1;
10039 segdir->length = 0;
10042 /* TODO: do these ever change? */
10043 segdir->res08 = -1;
10044 segdir->res0c = 0xf;
10047 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10049 DWORD written;
10050 if(segment)
10051 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10054 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10055 DWORD file_len)
10057 DWORD i;
10058 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10060 for(i = 0; i < This->TypeInfoCount; ++i){
10061 base->memoffset += file_len;
10062 ++base;
10065 return S_OK;
10068 static void WMSFT_free_file(WMSFT_TLBFile *file)
10070 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10071 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10072 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10073 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10074 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10075 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10076 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10077 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10078 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10079 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10080 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10081 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10082 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10083 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10086 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10088 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10089 WMSFT_TLBFile file;
10090 DWORD written, junk_size, junk_offs, running_offset;
10091 BOOL br;
10092 HANDLE outfile;
10093 HRESULT hres;
10094 DWORD *junk;
10095 UINT i;
10097 TRACE("%p\n", This);
10099 for(i = 0; i < This->TypeInfoCount; ++i)
10100 if(This->typeinfos[i]->needs_layout)
10101 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10103 memset(&file, 0, sizeof(file));
10105 file.header.magic1 = 0x5446534D;
10106 file.header.magic2 = 0x00010002;
10107 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10108 file.header.lcid2 = This->set_lcid;
10109 file.header.varflags = 0x40 | This->syskind;
10110 if (This->HelpFile)
10111 file.header.varflags |= 0x10;
10112 if (This->HelpStringDll)
10113 file.header.varflags |= HELPDLLFLAG;
10114 file.header.version = (This->ver_minor << 16) | This->ver_major;
10115 file.header.flags = This->libflags;
10116 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10117 file.header.helpcontext = This->dwHelpContext;
10118 file.header.res44 = 0x20;
10119 file.header.res48 = 0x80;
10120 file.header.dispatchpos = This->dispatch_href;
10122 WMSFT_compile_namehash(This, &file);
10123 /* do name and string compilation to get offsets for other compilations */
10124 hres = WMSFT_compile_names(This, &file);
10125 if (FAILED(hres)){
10126 WMSFT_free_file(&file);
10127 return hres;
10130 hres = WMSFT_compile_strings(This, &file);
10131 if (FAILED(hres)){
10132 WMSFT_free_file(&file);
10133 return hres;
10136 WMSFT_compile_guidhash(This, &file);
10137 hres = WMSFT_compile_guids(This, &file);
10138 if (FAILED(hres)){
10139 WMSFT_free_file(&file);
10140 return hres;
10143 if(This->HelpFile)
10144 file.header.helpfile = This->HelpFile->offset;
10145 else
10146 file.header.helpfile = -1;
10148 if(This->DocString)
10149 file.header.helpstring = This->DocString->offset;
10150 else
10151 file.header.helpstring = -1;
10153 /* do some more segment compilation */
10154 file.header.nimpinfos = list_count(&This->ref_list);
10155 file.header.nrtypeinfos = This->TypeInfoCount;
10157 if(This->Name)
10158 file.header.NameOffset = This->Name->offset;
10159 else
10160 file.header.NameOffset = -1;
10162 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10164 if(This->guid)
10165 file.header.posguid = This->guid->offset;
10166 else
10167 file.header.posguid = -1;
10169 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10170 if(file.header.varflags & HELPDLLFLAG)
10171 junk_size += sizeof(DWORD);
10172 if(junk_size){
10173 junk = heap_alloc_zero(junk_size);
10174 if(file.header.varflags & HELPDLLFLAG){
10175 *junk = This->HelpStringDll->offset;
10176 junk_offs = 1;
10177 }else
10178 junk_offs = 0;
10179 }else{
10180 junk = NULL;
10181 junk_offs = 0;
10184 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10185 WMSFT_compile_impinfo(This, &file);
10187 running_offset = 0;
10189 TRACE("header at: 0x%x\n", running_offset);
10190 running_offset += sizeof(file.header);
10192 TRACE("junk at: 0x%x\n", running_offset);
10193 running_offset += junk_size;
10195 TRACE("segdir at: 0x%x\n", running_offset);
10196 running_offset += sizeof(file.segdir);
10198 TRACE("typeinfo at: 0x%x\n", running_offset);
10199 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10201 TRACE("guidhashtab at: 0x%x\n", running_offset);
10202 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10204 TRACE("guidtab at: 0x%x\n", running_offset);
10205 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10207 TRACE("reftab at: 0x%x\n", running_offset);
10208 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10210 TRACE("impinfo at: 0x%x\n", running_offset);
10211 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10213 TRACE("impfiles at: 0x%x\n", running_offset);
10214 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10216 TRACE("namehashtab at: 0x%x\n", running_offset);
10217 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10219 TRACE("nametab at: 0x%x\n", running_offset);
10220 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10222 TRACE("stringtab at: 0x%x\n", running_offset);
10223 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10225 TRACE("typdesc at: 0x%x\n", running_offset);
10226 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10228 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10229 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10231 TRACE("custdata at: 0x%x\n", running_offset);
10232 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10234 TRACE("cdguids at: 0x%x\n", running_offset);
10235 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10237 TRACE("res0e at: 0x%x\n", running_offset);
10238 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10240 TRACE("res0f at: 0x%x\n", running_offset);
10241 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10243 TRACE("aux_seg at: 0x%x\n", running_offset);
10245 WMSFT_fixup_typeinfos(This, &file, running_offset);
10247 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10248 FILE_ATTRIBUTE_NORMAL, 0);
10249 if (outfile == INVALID_HANDLE_VALUE){
10250 WMSFT_free_file(&file);
10251 heap_free(junk);
10252 return TYPE_E_IOERROR;
10255 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10256 if (!br) {
10257 WMSFT_free_file(&file);
10258 CloseHandle(outfile);
10259 heap_free(junk);
10260 return TYPE_E_IOERROR;
10263 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10264 heap_free(junk);
10265 if (!br) {
10266 WMSFT_free_file(&file);
10267 CloseHandle(outfile);
10268 return TYPE_E_IOERROR;
10271 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10272 if (!br) {
10273 WMSFT_free_file(&file);
10274 CloseHandle(outfile);
10275 return TYPE_E_IOERROR;
10278 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10279 WMSFT_write_segment(outfile, &file.guidhash_seg);
10280 WMSFT_write_segment(outfile, &file.guid_seg);
10281 WMSFT_write_segment(outfile, &file.ref_seg);
10282 WMSFT_write_segment(outfile, &file.impinfo_seg);
10283 WMSFT_write_segment(outfile, &file.impfile_seg);
10284 WMSFT_write_segment(outfile, &file.namehash_seg);
10285 WMSFT_write_segment(outfile, &file.name_seg);
10286 WMSFT_write_segment(outfile, &file.string_seg);
10287 WMSFT_write_segment(outfile, &file.typdesc_seg);
10288 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10289 WMSFT_write_segment(outfile, &file.custdata_seg);
10290 WMSFT_write_segment(outfile, &file.cdguids_seg);
10291 WMSFT_write_segment(outfile, &file.aux_seg);
10293 WMSFT_free_file(&file);
10295 CloseHandle(outfile);
10297 return S_OK;
10300 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10301 LPOLESTR name)
10303 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10304 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10305 return E_NOTIMPL;
10308 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10309 REFGUID guid, VARIANT *varVal)
10311 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10312 TLBGuid *tlbguid;
10314 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10316 if (!guid || !varVal)
10317 return E_INVALIDARG;
10319 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10321 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10324 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10325 ULONG helpStringContext)
10327 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10328 FIXME("%p %u - stub\n", This, helpStringContext);
10329 return E_NOTIMPL;
10332 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10333 LPOLESTR filename)
10335 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10336 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10338 if (!filename)
10339 return E_INVALIDARG;
10341 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10343 return S_OK;
10346 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10347 ICreateTypeLib2_fnQueryInterface,
10348 ICreateTypeLib2_fnAddRef,
10349 ICreateTypeLib2_fnRelease,
10350 ICreateTypeLib2_fnCreateTypeInfo,
10351 ICreateTypeLib2_fnSetName,
10352 ICreateTypeLib2_fnSetVersion,
10353 ICreateTypeLib2_fnSetGuid,
10354 ICreateTypeLib2_fnSetDocString,
10355 ICreateTypeLib2_fnSetHelpFileName,
10356 ICreateTypeLib2_fnSetHelpContext,
10357 ICreateTypeLib2_fnSetLcid,
10358 ICreateTypeLib2_fnSetLibFlags,
10359 ICreateTypeLib2_fnSaveAllChanges,
10360 ICreateTypeLib2_fnDeleteTypeInfo,
10361 ICreateTypeLib2_fnSetCustData,
10362 ICreateTypeLib2_fnSetHelpStringContext,
10363 ICreateTypeLib2_fnSetHelpStringDll
10366 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10367 REFIID riid, void **object)
10369 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10371 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10374 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10376 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10378 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10381 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10383 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10385 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10388 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10389 REFGUID guid)
10391 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10393 TRACE("%p %s\n", This, debugstr_guid(guid));
10395 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10397 return S_OK;
10400 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10401 UINT typeFlags)
10403 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10404 WORD old_flags;
10405 HRESULT hres;
10407 TRACE("%p %x\n", This, typeFlags);
10409 if (typeFlags & TYPEFLAG_FDUAL) {
10410 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10411 ITypeLib *stdole;
10412 ITypeInfo *dispatch;
10413 HREFTYPE hreftype;
10414 HRESULT hres;
10416 hres = LoadTypeLib(stdole2tlb, &stdole);
10417 if(FAILED(hres))
10418 return hres;
10420 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10421 ITypeLib_Release(stdole);
10422 if(FAILED(hres))
10423 return hres;
10425 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10426 ITypeInfo_Release(dispatch);
10427 if(FAILED(hres))
10428 return hres;
10431 old_flags = This->typeattr.wTypeFlags;
10432 This->typeattr.wTypeFlags = typeFlags;
10434 hres = ICreateTypeInfo2_LayOut(iface);
10435 if (FAILED(hres)) {
10436 This->typeattr.wTypeFlags = old_flags;
10437 return hres;
10440 return S_OK;
10443 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10444 LPOLESTR doc)
10446 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10448 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10450 if (!doc)
10451 return E_INVALIDARG;
10453 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10455 return S_OK;
10458 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10459 DWORD helpContext)
10461 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10463 TRACE("%p %d\n", This, helpContext);
10465 This->dwHelpContext = helpContext;
10467 return S_OK;
10470 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10471 WORD majorVerNum, WORD minorVerNum)
10473 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10475 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10477 This->typeattr.wMajorVerNum = majorVerNum;
10478 This->typeattr.wMinorVerNum = minorVerNum;
10480 return S_OK;
10483 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10484 ITypeInfo *typeInfo, HREFTYPE *refType)
10486 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10487 UINT index;
10488 ITypeLib *container;
10489 TLBRefType *ref_type;
10490 TLBImpLib *implib;
10491 TYPEATTR *typeattr;
10492 TLIBATTR *libattr;
10493 HRESULT hres;
10495 TRACE("%p %p %p\n", This, typeInfo, refType);
10497 if (!typeInfo || !refType)
10498 return E_INVALIDARG;
10500 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10501 if (FAILED(hres))
10502 return hres;
10504 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10505 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10507 ITypeLib_Release(container);
10509 *refType = target->hreftype;
10511 return S_OK;
10514 hres = ITypeLib_GetLibAttr(container, &libattr);
10515 if (FAILED(hres)) {
10516 ITypeLib_Release(container);
10517 return hres;
10520 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10521 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10522 implib->lcid == libattr->lcid &&
10523 implib->wVersionMajor == libattr->wMajorVerNum &&
10524 implib->wVersionMinor == libattr->wMinorVerNum)
10525 break;
10528 if(&implib->entry == &This->pTypeLib->implib_list){
10529 implib = heap_alloc_zero(sizeof(TLBImpLib));
10531 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10532 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10533 implib->name = SysAllocString(our_container->path);
10534 }else{
10535 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10536 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10537 if(FAILED(hres)){
10538 implib->name = NULL;
10539 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10543 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10544 implib->lcid = libattr->lcid;
10545 implib->wVersionMajor = libattr->wMajorVerNum;
10546 implib->wVersionMinor = libattr->wMinorVerNum;
10548 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10551 ITypeLib_ReleaseTLibAttr(container, libattr);
10552 ITypeLib_Release(container);
10554 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10555 if (FAILED(hres))
10556 return hres;
10558 index = 0;
10559 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10560 if(ref_type->index == TLB_REF_USE_GUID &&
10561 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10562 ref_type->tkind == typeattr->typekind)
10563 break;
10564 ++index;
10567 if(&ref_type->entry == &This->pTypeLib->ref_list){
10568 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10570 ref_type->tkind = typeattr->typekind;
10571 ref_type->pImpTLInfo = implib;
10572 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10574 ref_type->index = TLB_REF_USE_GUID;
10576 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10578 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10581 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10583 *refType = ref_type->reference | 0x1;
10585 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10586 This->pTypeLib->dispatch_href = *refType;
10588 return S_OK;
10591 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10592 UINT index, FUNCDESC *funcDesc)
10594 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10595 TLBFuncDesc tmp_func_desc, *func_desc;
10596 int buf_size, i;
10597 char *buffer;
10598 HRESULT hres;
10600 TRACE("%p %u %p\n", This, index, funcDesc);
10602 if (!funcDesc || funcDesc->oVft & 3)
10603 return E_INVALIDARG;
10605 switch (This->typeattr.typekind) {
10606 case TKIND_MODULE:
10607 if (funcDesc->funckind != FUNC_STATIC)
10608 return TYPE_E_BADMODULEKIND;
10609 break;
10610 case TKIND_DISPATCH:
10611 if (funcDesc->funckind != FUNC_DISPATCH)
10612 return TYPE_E_BADMODULEKIND;
10613 break;
10614 default:
10615 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10616 return TYPE_E_BADMODULEKIND;
10619 if (index > This->typeattr.cFuncs)
10620 return TYPE_E_ELEMENTNOTFOUND;
10622 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10623 !funcDesc->cParams)
10624 return TYPE_E_INCONSISTENTPROPFUNCS;
10626 #ifdef _WIN64
10627 if(This->pTypeLib->syskind == SYS_WIN64 &&
10628 funcDesc->oVft % 8 != 0)
10629 return E_INVALIDARG;
10630 #endif
10632 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10633 TLBFuncDesc_Constructor(&tmp_func_desc);
10635 tmp_func_desc.funcdesc = *funcDesc;
10637 if (tmp_func_desc.funcdesc.oVft != 0)
10638 tmp_func_desc.funcdesc.oVft |= 1;
10640 if (funcDesc->cScodes && funcDesc->lprgscode) {
10641 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10642 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10643 } else {
10644 tmp_func_desc.funcdesc.lprgscode = NULL;
10645 tmp_func_desc.funcdesc.cScodes = 0;
10648 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10649 for (i = 0; i < funcDesc->cParams; ++i) {
10650 buf_size += sizeof(ELEMDESC);
10651 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10653 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10654 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10656 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10657 if (FAILED(hres)) {
10658 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10659 heap_free(tmp_func_desc.funcdesc.lprgscode);
10660 return hres;
10663 for (i = 0; i < funcDesc->cParams; ++i) {
10664 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10665 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10666 if (FAILED(hres)) {
10667 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10668 heap_free(tmp_func_desc.funcdesc.lprgscode);
10669 return hres;
10671 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10672 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10673 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10674 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10675 if (FAILED(hres)) {
10676 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10677 heap_free(tmp_func_desc.funcdesc.lprgscode);
10678 return hres;
10683 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10685 if (This->funcdescs) {
10686 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10687 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10689 if (index < This->typeattr.cFuncs) {
10690 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10691 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10692 func_desc = This->funcdescs + index;
10693 } else
10694 func_desc = This->funcdescs + This->typeattr.cFuncs;
10696 /* move custdata lists to the new memory location */
10697 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10698 if(index != i){
10699 TLBFuncDesc *fd = &This->funcdescs[i];
10700 if(fd->custdata_list.prev == fd->custdata_list.next)
10701 list_init(&fd->custdata_list);
10702 else{
10703 fd->custdata_list.prev->next = &fd->custdata_list;
10704 fd->custdata_list.next->prev = &fd->custdata_list;
10708 } else
10709 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10711 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10712 list_init(&func_desc->custdata_list);
10714 ++This->typeattr.cFuncs;
10716 This->needs_layout = TRUE;
10718 return S_OK;
10721 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10722 UINT index, HREFTYPE refType)
10724 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10725 TLBImplType *impl_type;
10726 HRESULT hres;
10728 TRACE("%p %u %d\n", This, index, refType);
10730 switch(This->typeattr.typekind){
10731 case TKIND_COCLASS: {
10732 if (index == -1) {
10733 FIXME("Unhandled index: -1\n");
10734 return E_NOTIMPL;
10737 if(index != This->typeattr.cImplTypes)
10738 return TYPE_E_ELEMENTNOTFOUND;
10740 break;
10742 case TKIND_INTERFACE:
10743 case TKIND_DISPATCH:
10744 if (index != 0 || This->typeattr.cImplTypes)
10745 return TYPE_E_ELEMENTNOTFOUND;
10746 break;
10747 default:
10748 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10749 return E_NOTIMPL;
10752 if (This->impltypes){
10753 UINT i;
10755 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10756 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10758 if (index < This->typeattr.cImplTypes) {
10759 memmove(This->impltypes + index + 1, This->impltypes + index,
10760 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10761 impl_type = This->impltypes + index;
10762 } else
10763 impl_type = This->impltypes + This->typeattr.cImplTypes;
10765 /* move custdata lists to the new memory location */
10766 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10767 if(index != i){
10768 TLBImplType *it = &This->impltypes[i];
10769 if(it->custdata_list.prev == it->custdata_list.next)
10770 list_init(&it->custdata_list);
10771 else{
10772 it->custdata_list.prev->next = &it->custdata_list;
10773 it->custdata_list.next->prev = &it->custdata_list;
10777 } else
10778 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10780 memset(impl_type, 0, sizeof(TLBImplType));
10781 TLBImplType_Constructor(impl_type);
10782 impl_type->hRef = refType;
10784 ++This->typeattr.cImplTypes;
10786 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10787 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10789 hres = ICreateTypeInfo2_LayOut(iface);
10790 if (FAILED(hres))
10791 return hres;
10793 return S_OK;
10796 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10797 UINT index, INT implTypeFlags)
10799 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10800 TLBImplType *impl_type = &This->impltypes[index];
10802 TRACE("%p %u %x\n", This, index, implTypeFlags);
10804 if (This->typeattr.typekind != TKIND_COCLASS)
10805 return TYPE_E_BADMODULEKIND;
10807 if (index >= This->typeattr.cImplTypes)
10808 return TYPE_E_ELEMENTNOTFOUND;
10810 impl_type->implflags = implTypeFlags;
10812 return S_OK;
10815 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10816 WORD alignment)
10818 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10820 TRACE("%p %d\n", This, alignment);
10822 This->typeattr.cbAlignment = alignment;
10824 return S_OK;
10827 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10828 LPOLESTR schema)
10830 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10832 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10834 if (!schema)
10835 return E_INVALIDARG;
10837 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10839 This->typeattr.lpstrSchema = This->Schema->str;
10841 return S_OK;
10844 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10845 UINT index, VARDESC *varDesc)
10847 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10848 TLBVarDesc *var_desc;
10850 TRACE("%p %u %p\n", This, index, varDesc);
10852 if (This->vardescs){
10853 UINT i;
10855 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10856 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10858 if (index < This->typeattr.cVars) {
10859 memmove(This->vardescs + index + 1, This->vardescs + index,
10860 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10861 var_desc = This->vardescs + index;
10862 } else
10863 var_desc = This->vardescs + This->typeattr.cVars;
10865 /* move custdata lists to the new memory location */
10866 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10867 if(index != i){
10868 TLBVarDesc *var = &This->vardescs[i];
10869 if(var->custdata_list.prev == var->custdata_list.next)
10870 list_init(&var->custdata_list);
10871 else{
10872 var->custdata_list.prev->next = &var->custdata_list;
10873 var->custdata_list.next->prev = &var->custdata_list;
10877 } else
10878 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10880 TLBVarDesc_Constructor(var_desc);
10881 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10882 var_desc->vardesc = *var_desc->vardesc_create;
10884 ++This->typeattr.cVars;
10886 This->needs_layout = TRUE;
10888 return S_OK;
10891 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10892 UINT index, LPOLESTR *names, UINT numNames)
10894 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10895 TLBFuncDesc *func_desc = &This->funcdescs[index];
10896 int i;
10898 TRACE("%p %u %p %u\n", This, index, names, numNames);
10900 if (!names)
10901 return E_INVALIDARG;
10903 if (index >= This->typeattr.cFuncs || numNames == 0)
10904 return TYPE_E_ELEMENTNOTFOUND;
10906 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10907 if(numNames > func_desc->funcdesc.cParams)
10908 return TYPE_E_ELEMENTNOTFOUND;
10909 } else
10910 if(numNames > func_desc->funcdesc.cParams + 1)
10911 return TYPE_E_ELEMENTNOTFOUND;
10913 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10914 TLBFuncDesc *iter = &This->funcdescs[i];
10915 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10916 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10917 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10918 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10919 continue;
10920 return TYPE_E_AMBIGUOUSNAME;
10924 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10926 for (i = 1; i < numNames; ++i) {
10927 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10928 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10931 return S_OK;
10934 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10935 UINT index, LPOLESTR name)
10937 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10939 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10941 if(!name)
10942 return E_INVALIDARG;
10944 if(index >= This->typeattr.cVars)
10945 return TYPE_E_ELEMENTNOTFOUND;
10947 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10948 return S_OK;
10951 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10952 TYPEDESC *tdescAlias)
10954 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10955 HRESULT hr;
10957 TRACE("%p %p\n", This, tdescAlias);
10959 if(!tdescAlias)
10960 return E_INVALIDARG;
10962 if(This->typeattr.typekind != TKIND_ALIAS)
10963 return TYPE_E_BADMODULEKIND;
10965 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10966 if(FAILED(hr))
10967 return hr;
10969 heap_free(This->tdescAlias);
10970 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10971 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10973 return S_OK;
10976 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10977 UINT index, LPOLESTR dllName, LPOLESTR procName)
10979 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10980 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10981 return E_NOTIMPL;
10984 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10985 UINT index, LPOLESTR docString)
10987 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10988 TLBFuncDesc *func_desc = &This->funcdescs[index];
10990 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10992 if(!docString)
10993 return E_INVALIDARG;
10995 if(index >= This->typeattr.cFuncs)
10996 return TYPE_E_ELEMENTNOTFOUND;
10998 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11000 return S_OK;
11003 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11004 UINT index, LPOLESTR docString)
11006 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11007 TLBVarDesc *var_desc = &This->vardescs[index];
11009 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11011 if(!docString)
11012 return E_INVALIDARG;
11014 if(index >= This->typeattr.cVars)
11015 return TYPE_E_ELEMENTNOTFOUND;
11017 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11019 return S_OK;
11022 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11023 UINT index, DWORD helpContext)
11025 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11026 TLBFuncDesc *func_desc = &This->funcdescs[index];
11028 TRACE("%p %u %d\n", This, index, helpContext);
11030 if(index >= This->typeattr.cFuncs)
11031 return TYPE_E_ELEMENTNOTFOUND;
11033 func_desc->helpcontext = helpContext;
11035 return S_OK;
11038 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11039 UINT index, DWORD helpContext)
11041 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11042 TLBVarDesc *var_desc = &This->vardescs[index];
11044 TRACE("%p %u %d\n", This, index, helpContext);
11046 if(index >= This->typeattr.cVars)
11047 return TYPE_E_ELEMENTNOTFOUND;
11049 var_desc->HelpContext = helpContext;
11051 return S_OK;
11054 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11055 UINT index, BSTR bstrMops)
11057 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11058 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11059 return E_NOTIMPL;
11062 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11063 IDLDESC *idlDesc)
11065 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11067 TRACE("%p %p\n", This, idlDesc);
11069 if (!idlDesc)
11070 return E_INVALIDARG;
11072 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11073 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11075 return S_OK;
11078 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11080 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11081 ITypeInfo *tinfo;
11082 TLBFuncDesc *func_desc;
11083 UINT user_vft = 0, i, depth = 0;
11084 HRESULT hres = S_OK;
11086 TRACE("%p\n", This);
11088 This->needs_layout = FALSE;
11090 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
11091 if (FAILED(hres))
11092 return hres;
11094 if (This->typeattr.typekind == TKIND_INTERFACE) {
11095 ITypeInfo *inh;
11096 TYPEATTR *attr;
11097 HREFTYPE inh_href;
11099 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11101 if (SUCCEEDED(hres)) {
11102 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
11104 if (SUCCEEDED(hres)) {
11105 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11106 if (FAILED(hres)) {
11107 ITypeInfo_Release(inh);
11108 ITypeInfo_Release(tinfo);
11109 return hres;
11111 This->typeattr.cbSizeVft = attr->cbSizeVft;
11112 ITypeInfo_ReleaseTypeAttr(inh, attr);
11115 ++depth;
11116 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11117 if(SUCCEEDED(hres)){
11118 ITypeInfo *next;
11119 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11120 if(SUCCEEDED(hres)){
11121 ITypeInfo_Release(inh);
11122 inh = next;
11125 }while(SUCCEEDED(hres));
11126 hres = S_OK;
11128 ITypeInfo_Release(inh);
11129 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11130 This->typeattr.cbSizeVft = 0;
11131 hres = S_OK;
11132 } else {
11133 ITypeInfo_Release(tinfo);
11134 return hres;
11136 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11137 This->typeattr.cbSizeVft = 0;
11138 hres = S_OK;
11139 } else {
11140 ITypeInfo_Release(tinfo);
11141 return hres;
11143 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11144 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11145 else
11146 This->typeattr.cbSizeVft = 0;
11148 func_desc = This->funcdescs;
11149 i = 0;
11150 while (i < This->typeattr.cFuncs) {
11151 if (!(func_desc->funcdesc.oVft & 0x1))
11152 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11154 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11155 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11157 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11159 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11160 TLBFuncDesc *iter;
11161 UINT j = 0;
11162 BOOL reset = FALSE;
11164 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11166 iter = This->funcdescs;
11167 while (j < This->typeattr.cFuncs) {
11168 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11169 if (!reset) {
11170 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11171 reset = TRUE;
11172 } else
11173 ++func_desc->funcdesc.memid;
11174 iter = This->funcdescs;
11175 j = 0;
11176 } else {
11177 ++iter;
11178 ++j;
11183 ++func_desc;
11184 ++i;
11187 if (user_vft > This->typeattr.cbSizeVft)
11188 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11190 for(i = 0; i < This->typeattr.cVars; ++i){
11191 TLBVarDesc *var_desc = &This->vardescs[i];
11192 if(var_desc->vardesc.memid == MEMBERID_NIL){
11193 UINT j = 0;
11194 BOOL reset = FALSE;
11195 TLBVarDesc *iter;
11197 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11199 iter = This->vardescs;
11200 while (j < This->typeattr.cVars) {
11201 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11202 if (!reset) {
11203 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11204 reset = TRUE;
11205 } else
11206 ++var_desc->vardesc.memid;
11207 iter = This->vardescs;
11208 j = 0;
11209 } else {
11210 ++iter;
11211 ++j;
11217 ITypeInfo_Release(tinfo);
11218 return hres;
11221 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11222 UINT index)
11224 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11225 FIXME("%p %u - stub\n", This, index);
11226 return E_NOTIMPL;
11229 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11230 MEMBERID memid, INVOKEKIND invKind)
11232 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11233 FIXME("%p %x %d - stub\n", This, memid, invKind);
11234 return E_NOTIMPL;
11237 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11238 UINT index)
11240 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11241 FIXME("%p %u - stub\n", This, index);
11242 return E_NOTIMPL;
11245 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11246 MEMBERID memid)
11248 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11249 FIXME("%p %x - stub\n", This, memid);
11250 return E_NOTIMPL;
11253 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11254 UINT index)
11256 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11257 FIXME("%p %u - stub\n", This, index);
11258 return E_NOTIMPL;
11261 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11262 REFGUID guid, VARIANT *varVal)
11264 TLBGuid *tlbguid;
11266 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11268 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11270 if (!guid || !varVal)
11271 return E_INVALIDARG;
11273 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11275 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11278 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11279 UINT index, REFGUID guid, VARIANT *varVal)
11281 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11282 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11283 return E_NOTIMPL;
11286 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11287 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11289 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11290 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11291 return E_NOTIMPL;
11294 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11295 UINT index, REFGUID guid, VARIANT *varVal)
11297 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11298 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11299 return E_NOTIMPL;
11302 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11303 UINT index, REFGUID guid, VARIANT *varVal)
11305 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11306 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11307 return E_NOTIMPL;
11310 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11311 ULONG helpStringContext)
11313 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11315 TRACE("%p %u\n", This, helpStringContext);
11317 This->dwHelpStringContext = helpStringContext;
11319 return S_OK;
11322 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11323 UINT index, ULONG helpStringContext)
11325 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11326 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11327 return E_NOTIMPL;
11330 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11331 UINT index, ULONG helpStringContext)
11333 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11334 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11335 return E_NOTIMPL;
11338 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11340 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11341 FIXME("%p - stub\n", This);
11342 return E_NOTIMPL;
11345 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11346 LPOLESTR name)
11348 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11350 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11352 if (!name)
11353 return E_INVALIDARG;
11355 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11357 return S_OK;
11360 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11361 ICreateTypeInfo2_fnQueryInterface,
11362 ICreateTypeInfo2_fnAddRef,
11363 ICreateTypeInfo2_fnRelease,
11364 ICreateTypeInfo2_fnSetGuid,
11365 ICreateTypeInfo2_fnSetTypeFlags,
11366 ICreateTypeInfo2_fnSetDocString,
11367 ICreateTypeInfo2_fnSetHelpContext,
11368 ICreateTypeInfo2_fnSetVersion,
11369 ICreateTypeInfo2_fnAddRefTypeInfo,
11370 ICreateTypeInfo2_fnAddFuncDesc,
11371 ICreateTypeInfo2_fnAddImplType,
11372 ICreateTypeInfo2_fnSetImplTypeFlags,
11373 ICreateTypeInfo2_fnSetAlignment,
11374 ICreateTypeInfo2_fnSetSchema,
11375 ICreateTypeInfo2_fnAddVarDesc,
11376 ICreateTypeInfo2_fnSetFuncAndParamNames,
11377 ICreateTypeInfo2_fnSetVarName,
11378 ICreateTypeInfo2_fnSetTypeDescAlias,
11379 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11380 ICreateTypeInfo2_fnSetFuncDocString,
11381 ICreateTypeInfo2_fnSetVarDocString,
11382 ICreateTypeInfo2_fnSetFuncHelpContext,
11383 ICreateTypeInfo2_fnSetVarHelpContext,
11384 ICreateTypeInfo2_fnSetMops,
11385 ICreateTypeInfo2_fnSetTypeIdldesc,
11386 ICreateTypeInfo2_fnLayOut,
11387 ICreateTypeInfo2_fnDeleteFuncDesc,
11388 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11389 ICreateTypeInfo2_fnDeleteVarDesc,
11390 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11391 ICreateTypeInfo2_fnDeleteImplType,
11392 ICreateTypeInfo2_fnSetCustData,
11393 ICreateTypeInfo2_fnSetFuncCustData,
11394 ICreateTypeInfo2_fnSetParamCustData,
11395 ICreateTypeInfo2_fnSetVarCustData,
11396 ICreateTypeInfo2_fnSetImplTypeCustData,
11397 ICreateTypeInfo2_fnSetHelpStringContext,
11398 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11399 ICreateTypeInfo2_fnSetVarHelpStringContext,
11400 ICreateTypeInfo2_fnInvalidate,
11401 ICreateTypeInfo2_fnSetName
11404 /******************************************************************************
11405 * ClearCustData (OLEAUT32.171)
11407 * Clear a custom data type's data.
11409 * PARAMS
11410 * lpCust [I] The custom data type instance
11412 * RETURNS
11413 * Nothing.
11415 void WINAPI ClearCustData(CUSTDATA *lpCust)
11417 if (lpCust && lpCust->cCustData)
11419 if (lpCust->prgCustData)
11421 DWORD i;
11423 for (i = 0; i < lpCust->cCustData; i++)
11424 VariantClear(&lpCust->prgCustData[i].varValue);
11426 CoTaskMemFree(lpCust->prgCustData);
11427 lpCust->prgCustData = NULL;
11429 lpCust->cCustData = 0;