ntdll: Pass a flag instead of a file handle to load_builtin_dll().
[wine.git] / dlls / oleaut32 / typelib.c
blobacd4d07c89e0619331baf066a8cadff82634e05d
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/heap.h"
77 #include "wine/list.h"
79 WINE_DEFAULT_DEBUG_CHANNEL(ole);
80 WINE_DECLARE_DEBUG_CHANNEL(typelib);
82 typedef struct
84 WORD offset;
85 WORD length;
86 WORD flags;
87 WORD id;
88 WORD handle;
89 WORD usage;
90 } NE_NAMEINFO;
92 typedef struct
94 WORD type_id; /* Type identifier */
95 WORD count; /* Number of resources of this type */
96 DWORD resloader; /* SetResourceHandler() */
98 * Name info array.
100 } NE_TYPEINFO;
102 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
103 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
104 static void TLB_FreeVarDesc(VARDESC*);
106 /****************************************************************************
107 * FromLExxx
109 * Takes p_iVal (which is in little endian) and returns it
110 * in the host machine's byte order.
112 #ifdef WORDS_BIGENDIAN
113 static WORD FromLEWord(WORD p_iVal)
115 return (((p_iVal & 0x00FF) << 8) |
116 ((p_iVal & 0xFF00) >> 8));
120 static DWORD FromLEDWord(DWORD p_iVal)
122 return (((p_iVal & 0x000000FF) << 24) |
123 ((p_iVal & 0x0000FF00) << 8) |
124 ((p_iVal & 0x00FF0000) >> 8) |
125 ((p_iVal & 0xFF000000) >> 24));
127 #else
128 #define FromLEWord(X) (X)
129 #define FromLEDWord(X) (X)
130 #endif
132 #define DISPATCH_HREF_OFFSET 0x01000000
133 #define DISPATCH_HREF_MASK 0xff000000
135 /****************************************************************************
136 * FromLExxx
138 * Fix byte order in any structure if necessary
140 #ifdef WORDS_BIGENDIAN
141 static void FromLEWords(void *p_Val, int p_iSize)
143 WORD *Val = p_Val;
145 p_iSize /= sizeof(WORD);
147 while (p_iSize) {
148 *Val = FromLEWord(*Val);
149 Val++;
150 p_iSize--;
155 static void FromLEDWords(void *p_Val, int p_iSize)
157 DWORD *Val = p_Val;
159 p_iSize /= sizeof(DWORD);
161 while (p_iSize) {
162 *Val = FromLEDWord(*Val);
163 Val++;
164 p_iSize--;
167 #else
168 #define FromLEWords(X,Y) /*nothing*/
169 #define FromLEDWords(X,Y) /*nothing*/
170 #endif
173 * Find a typelib key which matches a requested maj.min version.
175 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
177 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
178 WCHAR buffer[60];
179 char key_name[16];
180 DWORD len, i;
181 INT best_maj = -1, best_min = -1;
182 HKEY hkey;
184 memcpy( buffer, typelibW, sizeof(typelibW) );
185 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
187 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
188 return FALSE;
190 len = sizeof(key_name);
191 i = 0;
192 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
194 INT v_maj, v_min;
196 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
198 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
200 if (*wMaj == 0xffff && *wMin == 0xffff)
202 if (v_maj > best_maj) best_maj = v_maj;
203 if (v_min > best_min) best_min = v_min;
205 else if (*wMaj == v_maj)
207 best_maj = v_maj;
209 if (*wMin == v_min)
211 best_min = v_min;
212 break; /* exact match */
214 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
217 len = sizeof(key_name);
219 RegCloseKey( hkey );
221 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
223 if (*wMaj == 0xffff && *wMin == 0xffff)
225 if (best_maj >= 0 && best_min >= 0)
227 *wMaj = best_maj;
228 *wMin = best_min;
229 return TRUE;
233 if (*wMaj == best_maj && best_min >= 0)
235 *wMin = best_min;
236 return TRUE;
238 return FALSE;
241 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
242 /* buffer must be at least 60 characters long */
243 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
245 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
246 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
248 memcpy( buffer, TypelibW, sizeof(TypelibW) );
249 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
250 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
251 return buffer;
254 /* get the path of an interface key, in the form "Interface\\<guid>" */
255 /* buffer must be at least 50 characters long */
256 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
258 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
260 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
261 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
262 return buffer;
265 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
266 /* buffer must be at least 16 characters long */
267 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
269 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
270 static const WCHAR win16W[] = {'w','i','n','1','6',0};
271 static const WCHAR win32W[] = {'w','i','n','3','2',0};
272 static const WCHAR win64W[] = {'w','i','n','6','4',0};
274 sprintfW( buffer, LcidFormatW, lcid );
275 switch(syskind)
277 case SYS_WIN16: strcatW( buffer, win16W ); break;
278 case SYS_WIN32: strcatW( buffer, win32W ); break;
279 case SYS_WIN64: strcatW( buffer, win64W ); break;
280 default:
281 TRACE("Typelib is for unsupported syskind %i\n", syskind);
282 return NULL;
284 return buffer;
287 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
289 struct tlibredirect_data
291 ULONG size;
292 DWORD res;
293 ULONG name_len;
294 ULONG name_offset;
295 LANGID langid;
296 WORD flags;
297 ULONG help_len;
298 ULONG help_offset;
299 WORD major_version;
300 WORD minor_version;
303 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
304 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
305 SYSKIND syskind, LCID lcid, BSTR *path, BOOL redir )
307 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
308 LCID myLCID = lcid;
309 HKEY hkey;
310 WCHAR buffer[60];
311 WCHAR Path[MAX_PATH];
312 LONG res;
314 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
316 if (redir)
318 ACTCTX_SECTION_KEYED_DATA data;
320 data.cbSize = sizeof(data);
321 if (FindActCtxSectionGuid( 0, NULL, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION, guid, &data ))
323 struct tlibredirect_data *tlib = (struct tlibredirect_data*)data.lpData;
324 WCHAR *nameW;
325 DWORD len;
327 if ((wMaj != 0xffff || wMin != 0xffff) && (tlib->major_version != wMaj || tlib->minor_version < wMin))
328 return TYPE_E_LIBNOTREGISTERED;
330 nameW = (WCHAR*)((BYTE*)data.lpSectionBase + tlib->name_offset);
331 len = SearchPathW( NULL, nameW, NULL, ARRAY_SIZE( Path ), Path, NULL );
332 if (!len) return TYPE_E_LIBNOTREGISTERED;
334 TRACE_(typelib)("got path from context %s\n", debugstr_w(Path));
335 *path = SysAllocString( Path );
336 return S_OK;
340 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
341 get_typelib_key( guid, wMaj, wMin, buffer );
343 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
344 if (res == ERROR_FILE_NOT_FOUND)
346 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
347 return TYPE_E_LIBNOTREGISTERED;
349 else if (res != ERROR_SUCCESS)
351 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
352 return TYPE_E_REGISTRYACCESS;
355 while (hr != S_OK)
357 LONG dwPathLen = sizeof(Path);
359 get_lcid_subkey( myLCID, syskind, buffer );
361 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
363 if (!lcid)
364 break;
365 else if (myLCID == lcid)
367 /* try with sub-langid */
368 myLCID = SUBLANGID(lcid);
370 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
372 /* try with system langid */
373 myLCID = 0;
375 else
377 break;
380 else
382 *path = SysAllocString( Path );
383 hr = S_OK;
386 RegCloseKey( hkey );
387 TRACE_(typelib)("-- 0x%08x\n", hr);
388 return hr;
391 /****************************************************************************
392 * QueryPathOfRegTypeLib [OLEAUT32.164]
394 * Gets the path to a registered type library.
396 * PARAMS
397 * guid [I] referenced guid
398 * wMaj [I] major version
399 * wMin [I] minor version
400 * lcid [I] locale id
401 * path [O] path of typelib
403 * RETURNS
404 * Success: S_OK.
405 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
406 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
407 * opened.
409 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
411 BOOL redir = TRUE;
412 #ifdef _WIN64
413 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path, TRUE );
414 if(SUCCEEDED(hres))
415 return hres;
416 redir = FALSE;
417 #endif
418 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path, redir );
421 /******************************************************************************
422 * CreateTypeLib [OLEAUT32.160] creates a typelib
424 * RETURNS
425 * Success: S_OK
426 * Failure: Status
428 HRESULT WINAPI CreateTypeLib(
429 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
431 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
432 return E_FAIL;
435 /******************************************************************************
436 * LoadTypeLib [OLEAUT32.161]
438 * Loads a type library
440 * PARAMS
441 * szFile [I] Name of file to load from.
442 * pptLib [O] Pointer that receives ITypeLib object on success.
444 * RETURNS
445 * Success: S_OK
446 * Failure: Status
448 * SEE
449 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
451 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
453 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
454 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
457 /******************************************************************************
458 * LoadTypeLibEx [OLEAUT32.183]
460 * Loads and optionally registers a type library
462 * RETURNS
463 * Success: S_OK
464 * Failure: Status
466 HRESULT WINAPI LoadTypeLibEx(
467 LPCOLESTR szFile, /* [in] Name of file to load from */
468 REGKIND regkind, /* [in] Specify kind of registration */
469 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
471 WCHAR szPath[MAX_PATH+1];
472 HRESULT res;
474 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
476 if (!szFile || !pptLib)
477 return E_INVALIDARG;
479 *pptLib = NULL;
481 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
483 if (SUCCEEDED(res))
484 switch(regkind)
486 case REGKIND_DEFAULT:
487 /* don't register typelibs supplied with full path. Experimentation confirms the following */
488 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
489 (szFile[0] && (szFile[1] == ':'))) break;
490 /* else fall-through */
492 case REGKIND_REGISTER:
493 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
495 ITypeLib_Release(*pptLib);
496 *pptLib = 0;
498 break;
499 case REGKIND_NONE:
500 break;
503 TRACE(" returns %08x\n",res);
504 return res;
507 /******************************************************************************
508 * LoadRegTypeLib [OLEAUT32.162]
510 * Loads a registered type library.
512 * PARAMS
513 * rguid [I] GUID of the registered type library.
514 * wVerMajor [I] major version.
515 * wVerMinor [I] minor version.
516 * lcid [I] locale ID.
517 * ppTLib [O] pointer that receives an ITypeLib object on success.
519 * RETURNS
520 * Success: S_OK.
521 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
522 * LoadTypeLib.
524 HRESULT WINAPI LoadRegTypeLib(
525 REFGUID rguid,
526 WORD wVerMajor,
527 WORD wVerMinor,
528 LCID lcid,
529 ITypeLib **ppTLib)
531 BSTR bstr=NULL;
532 HRESULT res;
534 *ppTLib = NULL;
536 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
538 if(SUCCEEDED(res))
540 res= LoadTypeLib(bstr, ppTLib);
541 SysFreeString(bstr);
543 if ((wVerMajor!=0xffff || wVerMinor!=0xffff) && *ppTLib)
545 TLIBATTR *attr;
547 res = ITypeLib_GetLibAttr(*ppTLib, &attr);
548 if (res == S_OK)
550 BOOL mismatch = attr->wMajorVerNum != wVerMajor || attr->wMinorVerNum < wVerMinor;
551 ITypeLib_ReleaseTLibAttr(*ppTLib, attr);
553 if (mismatch)
555 ITypeLib_Release(*ppTLib);
556 *ppTLib = NULL;
557 res = TYPE_E_LIBNOTREGISTERED;
563 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
565 return res;
569 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
570 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
571 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
572 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
573 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
574 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
576 static void TLB_register_interface(TLIBATTR *libattr, LPOLESTR name, TYPEATTR *tattr, DWORD flag)
578 WCHAR keyName[60];
579 HKEY key, subKey;
581 static const WCHAR typelib_proxy_clsid[] = {'{','0','0','0','2','0','4','2','4','-',
582 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
583 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
584 static const WCHAR dispatch_proxy_clsid[] = {'{','0','0','0','2','0','4','2','0','-',
585 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
586 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
588 get_interface_key( &tattr->guid, keyName );
589 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
590 KEY_WRITE | flag, NULL, &key, NULL) == ERROR_SUCCESS)
592 const WCHAR *proxy_clsid;
594 if (tattr->typekind == TKIND_INTERFACE || (tattr->wTypeFlags & TYPEFLAG_FDUAL))
595 proxy_clsid = typelib_proxy_clsid;
596 else
597 proxy_clsid = dispatch_proxy_clsid;
599 if (name)
600 RegSetValueExW(key, NULL, 0, REG_SZ,
601 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
603 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
604 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
605 RegSetValueExW(subKey, NULL, 0, REG_SZ,
606 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
607 RegCloseKey(subKey);
610 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
611 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS) {
612 RegSetValueExW(subKey, NULL, 0, REG_SZ,
613 (const BYTE *)proxy_clsid, sizeof(typelib_proxy_clsid));
614 RegCloseKey(subKey);
617 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
618 KEY_WRITE | flag, NULL, &subKey, NULL) == ERROR_SUCCESS)
620 WCHAR buffer[40];
621 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
622 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
624 StringFromGUID2(&libattr->guid, buffer, 40);
625 RegSetValueExW(subKey, NULL, 0, REG_SZ,
626 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
627 sprintfW(buffer, fmtver, libattr->wMajorVerNum, libattr->wMinorVerNum);
628 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
629 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
630 RegCloseKey(subKey);
633 RegCloseKey(key);
637 /******************************************************************************
638 * RegisterTypeLib [OLEAUT32.163]
639 * Adds information about a type library to the System Registry
640 * NOTES
641 * Docs: ITypeLib FAR * ptlib
642 * Docs: OLECHAR FAR* szFullPath
643 * Docs: OLECHAR FAR* szHelpDir
645 * RETURNS
646 * Success: S_OK
647 * Failure: Status
649 HRESULT WINAPI RegisterTypeLib(
650 ITypeLib * ptlib, /* [in] Pointer to the library*/
651 OLECHAR * szFullPath, /* [in] full Path of the library*/
652 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
653 may be NULL*/
655 HRESULT res;
656 TLIBATTR *attr;
657 WCHAR keyName[60];
658 WCHAR tmp[16];
659 HKEY key, subKey;
660 UINT types, tidx;
661 TYPEKIND kind;
662 DWORD disposition;
664 if (ptlib == NULL || szFullPath == NULL)
665 return E_INVALIDARG;
667 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
668 return E_FAIL;
670 #ifndef _WIN64
671 if (attr->syskind == SYS_WIN64) return TYPE_E_BADMODULEKIND;
672 #endif
674 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
676 res = S_OK;
677 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
678 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
680 LPOLESTR doc;
682 /* Set the human-readable name of the typelib */
683 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
684 res = E_FAIL;
685 else if (doc)
687 if (RegSetValueExW(key, NULL, 0, REG_SZ,
688 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
689 res = E_FAIL;
691 SysFreeString(doc);
694 /* Make up the name of the typelib path subkey */
695 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
697 /* Create the typelib path subkey */
698 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
699 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
701 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
702 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
703 res = E_FAIL;
705 RegCloseKey(subKey);
707 else
708 res = E_FAIL;
710 /* Create the flags subkey */
711 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
712 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
714 /* FIXME: is %u correct? */
715 static const WCHAR formatW[] = {'%','u',0};
716 WCHAR buf[20];
717 sprintfW(buf, formatW, attr->wLibFlags);
718 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
719 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
720 res = E_FAIL;
722 RegCloseKey(subKey);
724 else
725 res = E_FAIL;
727 /* create the helpdir subkey */
728 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
729 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
731 BOOL freeHelpDir = FALSE;
732 OLECHAR* pIndexStr;
734 /* if we created a new key, and helpDir was null, set the helpdir
735 to the directory which contains the typelib. However,
736 if we just opened an existing key, we leave the helpdir alone */
737 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
738 szHelpDir = SysAllocString(szFullPath);
739 pIndexStr = strrchrW(szHelpDir, '\\');
740 if (pIndexStr) {
741 *pIndexStr = 0;
743 freeHelpDir = TRUE;
746 /* if we have an szHelpDir, set it! */
747 if (szHelpDir != NULL) {
748 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
749 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
750 res = E_FAIL;
754 /* tidy up */
755 if (freeHelpDir) SysFreeString(szHelpDir);
756 RegCloseKey(subKey);
758 } else {
759 res = E_FAIL;
762 RegCloseKey(key);
764 else
765 res = E_FAIL;
767 /* register OLE Automation-compatible interfaces for this typelib */
768 types = ITypeLib_GetTypeInfoCount(ptlib);
769 for (tidx=0; tidx<types; tidx++) {
770 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
771 LPOLESTR name = NULL;
772 ITypeInfo *tinfo = NULL;
774 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
776 switch (kind) {
777 case TKIND_INTERFACE:
778 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
779 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
780 break;
782 case TKIND_DISPATCH:
783 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
784 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
785 break;
787 default:
788 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
789 break;
792 if (tinfo) {
793 TYPEATTR *tattr = NULL;
794 ITypeInfo_GetTypeAttr(tinfo, &tattr);
796 if (tattr) {
797 TRACE_(typelib)("guid=%s, flags=%04x (",
798 debugstr_guid(&tattr->guid),
799 tattr->wTypeFlags);
801 if (TRACE_ON(typelib)) {
802 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
803 XX(FAPPOBJECT);
804 XX(FCANCREATE);
805 XX(FLICENSED);
806 XX(FPREDECLID);
807 XX(FHIDDEN);
808 XX(FCONTROL);
809 XX(FDUAL);
810 XX(FNONEXTENSIBLE);
811 XX(FOLEAUTOMATION);
812 XX(FRESTRICTED);
813 XX(FAGGREGATABLE);
814 XX(FREPLACEABLE);
815 XX(FDISPATCHABLE);
816 XX(FREVERSEBIND);
817 XX(FPROXY);
818 #undef XX
819 MESSAGE("\n");
822 /* Register all dispinterfaces (which includes dual interfaces) and
823 oleautomation interfaces */
824 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
825 kind == TKIND_DISPATCH)
827 BOOL is_wow64;
828 DWORD opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
830 /* register interface<->typelib coupling */
831 TLB_register_interface(attr, name, tattr, 0);
833 /* register TLBs into the opposite registry view, too */
834 if(opposite == KEY_WOW64_32KEY ||
835 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64))
836 TLB_register_interface(attr, name, tattr, opposite);
839 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
842 ITypeInfo_Release(tinfo);
845 SysFreeString(name);
849 ITypeLib_ReleaseTLibAttr(ptlib, attr);
851 return res;
854 static void TLB_unregister_interface(GUID *guid, REGSAM flag)
856 WCHAR subKeyName[50];
857 HKEY subKey;
859 /* the path to the type */
860 get_interface_key( guid, subKeyName );
862 /* Delete its bits */
863 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE | flag, &subKey) != ERROR_SUCCESS)
864 return;
866 RegDeleteKeyW(subKey, ProxyStubClsidW);
867 RegDeleteKeyW(subKey, ProxyStubClsid32W);
868 RegDeleteKeyW(subKey, TypeLibW);
869 RegCloseKey(subKey);
870 RegDeleteKeyExW(HKEY_CLASSES_ROOT, subKeyName, flag, 0);
873 /******************************************************************************
874 * UnRegisterTypeLib [OLEAUT32.186]
875 * Removes information about a type library from the System Registry
876 * NOTES
878 * RETURNS
879 * Success: S_OK
880 * Failure: Status
882 HRESULT WINAPI UnRegisterTypeLib(
883 REFGUID libid, /* [in] Guid of the library */
884 WORD wVerMajor, /* [in] major version */
885 WORD wVerMinor, /* [in] minor version */
886 LCID lcid, /* [in] locale id */
887 SYSKIND syskind)
889 BSTR tlibPath = NULL;
890 DWORD tmpLength;
891 WCHAR keyName[60];
892 WCHAR subKeyName[50];
893 int result = S_OK;
894 DWORD i = 0;
895 BOOL deleteOtherStuff;
896 HKEY key = NULL;
897 TYPEATTR* typeAttr = NULL;
898 TYPEKIND kind;
899 ITypeInfo* typeInfo = NULL;
900 ITypeLib* typeLib = NULL;
901 int numTypes;
903 TRACE("(IID: %s)\n",debugstr_guid(libid));
905 /* Create the path to the key */
906 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
908 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
910 TRACE("Unsupported syskind %i\n", syskind);
911 result = E_INVALIDARG;
912 goto end;
915 /* get the path to the typelib on disk */
916 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath, FALSE) != S_OK) {
917 result = E_INVALIDARG;
918 goto end;
921 /* Try and open the key to the type library. */
922 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
923 result = E_INVALIDARG;
924 goto end;
927 /* Try and load the type library */
928 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
929 result = TYPE_E_INVALIDSTATE;
930 goto end;
933 /* remove any types registered with this typelib */
934 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
935 for (i=0; i<numTypes; i++) {
936 /* get the kind of type */
937 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
938 goto enddeleteloop;
941 /* skip non-interfaces, and get type info for the type */
942 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
943 goto enddeleteloop;
945 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
946 goto enddeleteloop;
948 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
949 goto enddeleteloop;
952 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
953 kind == TKIND_DISPATCH)
955 BOOL is_wow64;
956 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
958 TLB_unregister_interface(&typeAttr->guid, 0);
960 /* unregister TLBs into the opposite registry view, too */
961 if(opposite == KEY_WOW64_32KEY ||
962 (IsWow64Process(GetCurrentProcess(), &is_wow64) && is_wow64)) {
963 TLB_unregister_interface(&typeAttr->guid, opposite);
967 enddeleteloop:
968 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
969 typeAttr = NULL;
970 if (typeInfo) ITypeInfo_Release(typeInfo);
971 typeInfo = NULL;
974 /* Now, delete the type library path subkey */
975 get_lcid_subkey( lcid, syskind, subKeyName );
976 RegDeleteKeyW(key, subKeyName);
977 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
978 RegDeleteKeyW(key, subKeyName);
980 /* check if there is anything besides the FLAGS/HELPDIR keys.
981 If there is, we don't delete them */
982 tmpLength = ARRAY_SIZE(subKeyName);
983 deleteOtherStuff = TRUE;
984 i = 0;
985 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
986 tmpLength = ARRAY_SIZE(subKeyName);
988 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
989 if (!strcmpW(subKeyName, FLAGSW)) continue;
990 if (!strcmpW(subKeyName, HELPDIRW)) continue;
991 deleteOtherStuff = FALSE;
992 break;
995 /* only delete the other parts of the key if we're absolutely sure */
996 if (deleteOtherStuff) {
997 RegDeleteKeyW(key, FLAGSW);
998 RegDeleteKeyW(key, HELPDIRW);
999 RegCloseKey(key);
1000 key = NULL;
1002 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1003 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
1004 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
1007 end:
1008 SysFreeString(tlibPath);
1009 if (typeLib) ITypeLib_Release(typeLib);
1010 if (key) RegCloseKey(key);
1011 return result;
1014 /******************************************************************************
1015 * RegisterTypeLibForUser [OLEAUT32.442]
1016 * Adds information about a type library to the user registry
1017 * NOTES
1018 * Docs: ITypeLib FAR * ptlib
1019 * Docs: OLECHAR FAR* szFullPath
1020 * Docs: OLECHAR FAR* szHelpDir
1022 * RETURNS
1023 * Success: S_OK
1024 * Failure: Status
1026 HRESULT WINAPI RegisterTypeLibForUser(
1027 ITypeLib * ptlib, /* [in] Pointer to the library*/
1028 OLECHAR * szFullPath, /* [in] full Path of the library*/
1029 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
1030 may be NULL*/
1032 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
1033 debugstr_w(szFullPath), debugstr_w(szHelpDir));
1034 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
1037 /******************************************************************************
1038 * UnRegisterTypeLibForUser [OLEAUT32.443]
1039 * Removes information about a type library from the user registry
1041 * RETURNS
1042 * Success: S_OK
1043 * Failure: Status
1045 HRESULT WINAPI UnRegisterTypeLibForUser(
1046 REFGUID libid, /* [in] GUID of the library */
1047 WORD wVerMajor, /* [in] major version */
1048 WORD wVerMinor, /* [in] minor version */
1049 LCID lcid, /* [in] locale id */
1050 SYSKIND syskind)
1052 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1053 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
1054 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
1057 /*======================= ITypeLib implementation =======================*/
1059 typedef struct tagTLBGuid {
1060 GUID guid;
1061 INT hreftype;
1062 UINT offset;
1063 struct list entry;
1064 } TLBGuid;
1066 typedef struct tagTLBCustData
1068 TLBGuid *guid;
1069 VARIANT data;
1070 struct list entry;
1071 } TLBCustData;
1073 /* data structure for import typelibs */
1074 typedef struct tagTLBImpLib
1076 int offset; /* offset in the file (MSFT)
1077 offset in nametable (SLTG)
1078 just used to identify library while reading
1079 data from file */
1080 TLBGuid *guid; /* libid */
1081 BSTR name; /* name */
1083 LCID lcid; /* lcid of imported typelib */
1085 WORD wVersionMajor; /* major version number */
1086 WORD wVersionMinor; /* minor version number */
1088 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
1089 NULL if not yet loaded */
1090 struct list entry;
1091 } TLBImpLib;
1093 typedef struct tagTLBString {
1094 BSTR str;
1095 UINT offset;
1096 struct list entry;
1097 } TLBString;
1099 /* internal ITypeLib data */
1100 typedef struct tagITypeLibImpl
1102 ITypeLib2 ITypeLib2_iface;
1103 ITypeComp ITypeComp_iface;
1104 ICreateTypeLib2 ICreateTypeLib2_iface;
1105 LONG ref;
1106 TLBGuid *guid;
1107 LCID lcid;
1108 SYSKIND syskind;
1109 int ptr_size;
1110 WORD ver_major;
1111 WORD ver_minor;
1112 WORD libflags;
1113 LCID set_lcid;
1115 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1116 * exported to the application as a UNICODE string.
1118 struct list string_list;
1119 struct list name_list;
1120 struct list guid_list;
1122 const TLBString *Name;
1123 const TLBString *DocString;
1124 const TLBString *HelpFile;
1125 const TLBString *HelpStringDll;
1126 DWORD dwHelpContext;
1127 int TypeInfoCount; /* nr of typeinfo's in librarry */
1128 struct tagITypeInfoImpl **typeinfos;
1129 struct list custdata_list;
1130 struct list implib_list;
1131 int ctTypeDesc; /* number of items in type desc array */
1132 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1133 library. Only used while reading MSFT
1134 typelibs */
1135 struct list ref_list; /* list of ref types in this typelib */
1136 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1139 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1140 struct list entry;
1141 WCHAR *path;
1142 INT index;
1143 } ITypeLibImpl;
1145 static const ITypeLib2Vtbl tlbvt;
1146 static const ITypeCompVtbl tlbtcvt;
1147 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl;
1149 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1151 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1154 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1156 return impl_from_ITypeLib2((ITypeLib2*)iface);
1159 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1161 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1164 static inline ITypeLibImpl *impl_from_ICreateTypeLib2( ICreateTypeLib2 *iface )
1166 return CONTAINING_RECORD(iface, ITypeLibImpl, ICreateTypeLib2_iface);
1169 /* ITypeLib methods */
1170 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1171 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1173 /*======================= ITypeInfo implementation =======================*/
1175 /* data for referenced types */
1176 typedef struct tagTLBRefType
1178 INT index; /* Type index for internal ref or for external ref
1179 it the format is SLTG. -2 indicates to
1180 use guid */
1182 TYPEKIND tkind;
1183 TLBGuid *guid; /* guid of the referenced type */
1184 /* if index == TLB_REF_USE_GUID */
1186 HREFTYPE reference; /* The href of this ref */
1187 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1188 TLB_REF_INTERNAL for internal refs
1189 TLB_REF_NOT_FOUND for broken refs */
1191 struct list entry;
1192 } TLBRefType;
1194 #define TLB_REF_USE_GUID -2
1196 #define TLB_REF_INTERNAL (void*)-2
1197 #define TLB_REF_NOT_FOUND (void*)-1
1199 /* internal Parameter data */
1200 typedef struct tagTLBParDesc
1202 const TLBString *Name;
1203 struct list custdata_list;
1204 } TLBParDesc;
1206 /* internal Function data */
1207 typedef struct tagTLBFuncDesc
1209 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1210 const TLBString *Name; /* the name of this function */
1211 TLBParDesc *pParamDesc; /* array with param names and custom data */
1212 int helpcontext;
1213 int HelpStringContext;
1214 const TLBString *HelpString;
1215 const TLBString *Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1216 struct list custdata_list;
1217 } TLBFuncDesc;
1219 /* internal Variable data */
1220 typedef struct tagTLBVarDesc
1222 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1223 VARDESC *vardesc_create; /* additional data needed for storing VARDESC */
1224 const TLBString *Name; /* the name of this variable */
1225 int HelpContext;
1226 int HelpStringContext;
1227 const TLBString *HelpString;
1228 struct list custdata_list;
1229 } TLBVarDesc;
1231 /* internal implemented interface data */
1232 typedef struct tagTLBImplType
1234 HREFTYPE hRef; /* hRef of interface */
1235 int implflags; /* IMPLFLAG_*s */
1236 struct list custdata_list;
1237 } TLBImplType;
1239 /* internal TypeInfo data */
1240 typedef struct tagITypeInfoImpl
1242 ITypeInfo2 ITypeInfo2_iface;
1243 ITypeComp ITypeComp_iface;
1244 ICreateTypeInfo2 ICreateTypeInfo2_iface;
1245 LONG ref;
1246 BOOL not_attached_to_typelib;
1247 BOOL needs_layout;
1249 TLBGuid *guid;
1250 TYPEATTR typeattr;
1251 TYPEDESC *tdescAlias;
1253 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1254 int index; /* index in this typelib; */
1255 HREFTYPE hreftype; /* hreftype for app object binding */
1256 /* type libs seem to store the doc strings in ascii
1257 * so why should we do it in unicode?
1259 const TLBString *Name;
1260 const TLBString *DocString;
1261 const TLBString *DllName;
1262 const TLBString *Schema;
1263 DWORD dwHelpContext;
1264 DWORD dwHelpStringContext;
1266 /* functions */
1267 TLBFuncDesc *funcdescs;
1269 /* variables */
1270 TLBVarDesc *vardescs;
1272 /* Implemented Interfaces */
1273 TLBImplType *impltypes;
1275 struct list *pcustdata_list;
1276 struct list custdata_list;
1277 } ITypeInfoImpl;
1279 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1281 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1284 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1286 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1289 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1291 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1294 static inline ITypeInfoImpl *info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2 *iface )
1296 return CONTAINING_RECORD(iface, ITypeInfoImpl, ICreateTypeInfo2_iface);
1299 static const ITypeInfo2Vtbl tinfvt;
1300 static const ITypeCompVtbl tcompvt;
1301 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl;
1303 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1304 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1306 typedef struct tagTLBContext
1308 unsigned int oStart; /* start of TLB in file */
1309 unsigned int pos; /* current pos */
1310 unsigned int length; /* total length */
1311 void *mapping; /* memory mapping */
1312 MSFT_SegDir * pTblDir;
1313 ITypeLibImpl* pLibInfo;
1314 } TLBContext;
1317 static inline BSTR TLB_get_bstr(const TLBString *str)
1319 return str != NULL ? str->str : NULL;
1322 static inline int TLB_str_memcmp(void *left, const TLBString *str, DWORD len)
1324 if(!str)
1325 return 1;
1326 return memcmp(left, str->str, len);
1329 static inline const GUID *TLB_get_guidref(const TLBGuid *guid)
1331 return guid != NULL ? &guid->guid : NULL;
1334 static inline const GUID *TLB_get_guid_null(const TLBGuid *guid)
1336 return guid != NULL ? &guid->guid : &GUID_NULL;
1339 static int get_ptr_size(SYSKIND syskind)
1341 switch(syskind){
1342 case SYS_WIN64:
1343 return 8;
1344 case SYS_WIN32:
1345 case SYS_MAC:
1346 case SYS_WIN16:
1347 return 4;
1349 WARN("Unhandled syskind: 0x%x\n", syskind);
1350 return 4;
1354 debug
1356 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1357 if (pTD->vt & VT_RESERVED)
1358 szVarType += strlen(strcpy(szVarType, "reserved | "));
1359 if (pTD->vt & VT_BYREF)
1360 szVarType += strlen(strcpy(szVarType, "ref to "));
1361 if (pTD->vt & VT_ARRAY)
1362 szVarType += strlen(strcpy(szVarType, "array of "));
1363 if (pTD->vt & VT_VECTOR)
1364 szVarType += strlen(strcpy(szVarType, "vector of "));
1365 switch(pTD->vt & VT_TYPEMASK) {
1366 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1367 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1368 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1369 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1370 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1371 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1372 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1373 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1374 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1375 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1376 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1377 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1378 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1379 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1380 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1381 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1382 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1383 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1384 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1385 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1386 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1387 pTD->u.hreftype); break;
1388 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1389 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1390 case VT_PTR: sprintf(szVarType, "ptr to ");
1391 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1392 break;
1393 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1394 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1395 break;
1396 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1397 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1398 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1399 break;
1401 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1405 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1406 char buf[200];
1407 USHORT flags = edesc->u.paramdesc.wParamFlags;
1408 dump_TypeDesc(&edesc->tdesc,buf);
1409 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1410 MESSAGE("\t\tu.paramdesc.wParamFlags");
1411 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1412 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1413 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1414 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1415 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1416 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1417 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1418 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1419 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1421 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1422 int i;
1423 MESSAGE("memid is %08x\n",funcdesc->memid);
1424 for (i=0;i<funcdesc->cParams;i++) {
1425 MESSAGE("Param %d:\n",i);
1426 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1428 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1429 switch (funcdesc->funckind) {
1430 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1431 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1432 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1433 case FUNC_STATIC: MESSAGE("static");break;
1434 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1435 default: MESSAGE("unknown");break;
1437 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1438 switch (funcdesc->invkind) {
1439 case INVOKE_FUNC: MESSAGE("func");break;
1440 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1441 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1442 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1444 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1445 switch (funcdesc->callconv) {
1446 case CC_CDECL: MESSAGE("cdecl");break;
1447 case CC_PASCAL: MESSAGE("pascal");break;
1448 case CC_STDCALL: MESSAGE("stdcall");break;
1449 case CC_SYSCALL: MESSAGE("syscall");break;
1450 default:break;
1452 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1453 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1454 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1456 MESSAGE("\telemdescFunc (return value type):\n");
1457 dump_ELEMDESC(&funcdesc->elemdescFunc);
1460 static const char * const typekind_desc[] =
1462 "TKIND_ENUM",
1463 "TKIND_RECORD",
1464 "TKIND_MODULE",
1465 "TKIND_INTERFACE",
1466 "TKIND_DISPATCH",
1467 "TKIND_COCLASS",
1468 "TKIND_ALIAS",
1469 "TKIND_UNION",
1470 "TKIND_MAX"
1473 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1475 int i;
1476 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd->Name)), pfd->funcdesc.cParams);
1477 for (i=0;i<pfd->funcdesc.cParams;i++)
1478 MESSAGE("\tparm%d: %s\n",i,debugstr_w(TLB_get_bstr(pfd->pParamDesc[i].Name)));
1481 dump_FUNCDESC(&(pfd->funcdesc));
1483 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd->HelpString)));
1484 if(pfd->Entry == NULL)
1485 MESSAGE("\tentry: (null)\n");
1486 else if(pfd->Entry == (void*)-1)
1487 MESSAGE("\tentry: invalid\n");
1488 else if(IS_INTRESOURCE(pfd->Entry))
1489 MESSAGE("\tentry: %p\n", pfd->Entry);
1490 else
1491 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd->Entry)));
1493 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1495 while (n)
1497 dump_TLBFuncDescOne(pfd);
1498 ++pfd;
1499 --n;
1502 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1504 while (n)
1506 TRACE_(typelib)("%s\n", debugstr_w(TLB_get_bstr(pvd->Name)));
1507 ++pvd;
1508 --n;
1512 static void dump_TLBImpLib(const TLBImpLib *import)
1514 TRACE_(typelib)("%s %s\n", debugstr_guid(TLB_get_guidref(import->guid)),
1515 debugstr_w(import->name));
1516 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1517 import->wVersionMinor, import->lcid, import->offset);
1520 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1522 TLBRefType *ref;
1524 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1526 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1527 if(ref->index == -1)
1528 TRACE_(typelib)("%s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
1529 else
1530 TRACE_(typelib)("type no: %d\n", ref->index);
1532 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1534 TRACE_(typelib)("in lib\n");
1535 dump_TLBImpLib(ref->pImpTLInfo);
1540 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1542 if(!impl)
1543 return;
1544 while (n) {
1545 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1546 impl->hRef, impl->implflags);
1547 ++impl;
1548 --n;
1552 static void dump_DispParms(const DISPPARAMS * pdp)
1554 unsigned int index;
1556 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1558 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1560 TRACE("named args:\n");
1561 for (index = 0; index < pdp->cNamedArgs; index++)
1562 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1565 if (pdp->cArgs && pdp->rgvarg)
1567 TRACE("args:\n");
1568 for (index = 0; index < pdp->cArgs; index++)
1569 TRACE(" [%d] %s\n", index, debugstr_variant(pdp->rgvarg+index));
1573 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1575 TRACE("%p ref=%u\n", pty, pty->ref);
1576 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty->Name)), debugstr_w(TLB_get_bstr(pty->DocString)));
1577 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty->guid)));
1578 TRACE("kind:%s\n", typekind_desc[pty->typeattr.typekind]);
1579 TRACE("fct:%u var:%u impl:%u\n", pty->typeattr.cFuncs, pty->typeattr.cVars, pty->typeattr.cImplTypes);
1580 TRACE("wTypeFlags: 0x%04x\n", pty->typeattr.wTypeFlags);
1581 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1582 if (pty->typeattr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty->DllName)));
1583 if (TRACE_ON(ole))
1584 dump_TLBFuncDesc(pty->funcdescs, pty->typeattr.cFuncs);
1585 dump_TLBVarDesc(pty->vardescs, pty->typeattr.cVars);
1586 dump_TLBImplType(pty->impltypes, pty->typeattr.cImplTypes);
1589 static void dump_VARDESC(const VARDESC *v)
1591 MESSAGE("memid %d\n",v->memid);
1592 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1593 MESSAGE("oInst %d\n",v->u.oInst);
1594 dump_ELEMDESC(&(v->elemdescVar));
1595 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1596 MESSAGE("varkind %d\n",v->varkind);
1599 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1601 /* VT_LPWSTR is largest type that, may appear in type description */
1602 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1603 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1604 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1605 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1606 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1607 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1608 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1609 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1612 static void TLB_abort(void)
1614 DebugBreak();
1617 /* returns the size required for a deep copy of a typedesc into a
1618 * flat buffer */
1619 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1621 SIZE_T size = 0;
1623 if (alloc_initial_space)
1624 size += sizeof(TYPEDESC);
1626 switch (tdesc->vt)
1628 case VT_PTR:
1629 case VT_SAFEARRAY:
1630 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1631 break;
1632 case VT_CARRAY:
1633 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1634 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1635 break;
1637 return size;
1640 /* deep copy a typedesc into a flat buffer */
1641 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1643 if (!dest)
1645 dest = buffer;
1646 buffer = (char *)buffer + sizeof(TYPEDESC);
1649 *dest = *src;
1651 switch (src->vt)
1653 case VT_PTR:
1654 case VT_SAFEARRAY:
1655 dest->u.lptdesc = buffer;
1656 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1657 break;
1658 case VT_CARRAY:
1659 dest->u.lpadesc = buffer;
1660 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1661 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1662 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1663 break;
1665 return buffer;
1668 /* free custom data allocated by MSFT_CustData */
1669 static inline void TLB_FreeCustData(struct list *custdata_list)
1671 TLBCustData *cd, *cdn;
1672 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1674 list_remove(&cd->entry);
1675 VariantClear(&cd->data);
1676 heap_free(cd);
1680 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1682 DWORD len;
1683 BSTR ret;
1685 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1686 ret = SysAllocStringLen(NULL, len - 1);
1687 if (!ret) return ret;
1688 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1689 return ret;
1692 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1693 UINT n, MEMBERID memid)
1695 while(n){
1696 if(funcdescs->funcdesc.memid == memid)
1697 return funcdescs;
1698 ++funcdescs;
1699 --n;
1701 return NULL;
1704 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1705 UINT n, MEMBERID memid)
1707 while(n){
1708 if(vardescs->vardesc.memid == memid)
1709 return vardescs;
1710 ++vardescs;
1711 --n;
1713 return NULL;
1716 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1717 UINT n, const OLECHAR *name)
1719 while(n){
1720 if(!lstrcmpiW(TLB_get_bstr(vardescs->Name), name))
1721 return vardescs;
1722 ++vardescs;
1723 --n;
1725 return NULL;
1728 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1730 TLBCustData *cust_data;
1731 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1732 if(IsEqualIID(TLB_get_guid_null(cust_data->guid), guid))
1733 return cust_data;
1734 return NULL;
1737 static inline ITypeInfoImpl *TLB_get_typeinfo_by_name(ITypeInfoImpl **typeinfos,
1738 UINT n, const OLECHAR *name)
1740 while(n){
1741 if(!lstrcmpiW(TLB_get_bstr((*typeinfos)->Name), name))
1742 return *typeinfos;
1743 ++typeinfos;
1744 --n;
1746 return NULL;
1749 static void TLBVarDesc_Constructor(TLBVarDesc *var_desc)
1751 list_init(&var_desc->custdata_list);
1754 static TLBVarDesc *TLBVarDesc_Alloc(UINT n)
1756 TLBVarDesc *ret;
1758 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1759 if(!ret)
1760 return NULL;
1762 while(n){
1763 TLBVarDesc_Constructor(&ret[n-1]);
1764 --n;
1767 return ret;
1770 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1772 TLBParDesc *ret;
1774 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1775 if(!ret)
1776 return NULL;
1778 while(n){
1779 list_init(&ret[n-1].custdata_list);
1780 --n;
1783 return ret;
1786 static void TLBFuncDesc_Constructor(TLBFuncDesc *func_desc)
1788 list_init(&func_desc->custdata_list);
1791 static TLBFuncDesc *TLBFuncDesc_Alloc(UINT n)
1793 TLBFuncDesc *ret;
1795 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1796 if(!ret)
1797 return NULL;
1799 while(n){
1800 TLBFuncDesc_Constructor(&ret[n-1]);
1801 --n;
1804 return ret;
1807 static void TLBImplType_Constructor(TLBImplType *impl)
1809 list_init(&impl->custdata_list);
1812 static TLBImplType *TLBImplType_Alloc(UINT n)
1814 TLBImplType *ret;
1816 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1817 if(!ret)
1818 return NULL;
1820 while(n){
1821 TLBImplType_Constructor(&ret[n-1]);
1822 --n;
1825 return ret;
1828 static TLBGuid *TLB_append_guid(struct list *guid_list,
1829 const GUID *new_guid, HREFTYPE hreftype)
1831 TLBGuid *guid;
1833 LIST_FOR_EACH_ENTRY(guid, guid_list, TLBGuid, entry) {
1834 if (IsEqualGUID(&guid->guid, new_guid))
1835 return guid;
1838 guid = heap_alloc(sizeof(TLBGuid));
1839 if (!guid)
1840 return NULL;
1842 memcpy(&guid->guid, new_guid, sizeof(GUID));
1843 guid->hreftype = hreftype;
1845 list_add_tail(guid_list, &guid->entry);
1847 return guid;
1850 static HRESULT TLB_set_custdata(struct list *custdata_list, TLBGuid *tlbguid, VARIANT *var)
1852 TLBCustData *cust_data;
1854 switch(V_VT(var)){
1855 case VT_I4:
1856 case VT_R4:
1857 case VT_UI4:
1858 case VT_INT:
1859 case VT_UINT:
1860 case VT_HRESULT:
1861 case VT_BSTR:
1862 break;
1863 default:
1864 return DISP_E_BADVARTYPE;
1867 cust_data = TLB_get_custdata_by_guid(custdata_list, TLB_get_guid_null(tlbguid));
1869 if (!cust_data) {
1870 cust_data = heap_alloc(sizeof(TLBCustData));
1871 if (!cust_data)
1872 return E_OUTOFMEMORY;
1874 cust_data->guid = tlbguid;
1875 VariantInit(&cust_data->data);
1877 list_add_tail(custdata_list, &cust_data->entry);
1878 }else
1879 VariantClear(&cust_data->data);
1881 return VariantCopy(&cust_data->data, var);
1884 static TLBString *TLB_append_str(struct list *string_list, BSTR new_str)
1886 TLBString *str;
1888 if(!new_str)
1889 return NULL;
1891 LIST_FOR_EACH_ENTRY(str, string_list, TLBString, entry) {
1892 if (strcmpW(str->str, new_str) == 0)
1893 return str;
1896 str = heap_alloc(sizeof(TLBString));
1897 if (!str)
1898 return NULL;
1900 str->str = SysAllocString(new_str);
1901 if (!str->str) {
1902 heap_free(str);
1903 return NULL;
1906 list_add_tail(string_list, &str->entry);
1908 return str;
1911 static HRESULT TLB_get_size_from_hreftype(ITypeInfoImpl *info, HREFTYPE href,
1912 ULONG *size, WORD *align)
1914 ITypeInfo *other;
1915 TYPEATTR *attr;
1916 HRESULT hr;
1918 hr = ITypeInfo2_GetRefTypeInfo(&info->ITypeInfo2_iface, href, &other);
1919 if(FAILED(hr))
1920 return hr;
1922 hr = ITypeInfo_GetTypeAttr(other, &attr);
1923 if(FAILED(hr)){
1924 ITypeInfo_Release(other);
1925 return hr;
1928 if(size)
1929 *size = attr->cbSizeInstance;
1930 if(align)
1931 *align = attr->cbAlignment;
1933 ITypeInfo_ReleaseTypeAttr(other, attr);
1934 ITypeInfo_Release(other);
1936 return S_OK;
1939 static HRESULT TLB_size_instance(ITypeInfoImpl *info, SYSKIND sys,
1940 TYPEDESC *tdesc, ULONG *size, WORD *align)
1942 ULONG i, sub, ptr_size;
1943 HRESULT hr;
1945 ptr_size = get_ptr_size(sys);
1947 switch(tdesc->vt){
1948 case VT_VOID:
1949 *size = 0;
1950 break;
1951 case VT_I1:
1952 case VT_UI1:
1953 *size = 1;
1954 break;
1955 case VT_I2:
1956 case VT_BOOL:
1957 case VT_UI2:
1958 *size = 2;
1959 break;
1960 case VT_I4:
1961 case VT_R4:
1962 case VT_ERROR:
1963 case VT_UI4:
1964 case VT_INT:
1965 case VT_UINT:
1966 case VT_HRESULT:
1967 *size = 4;
1968 break;
1969 case VT_R8:
1970 case VT_I8:
1971 case VT_UI8:
1972 *size = 8;
1973 break;
1974 case VT_BSTR:
1975 case VT_DISPATCH:
1976 case VT_UNKNOWN:
1977 case VT_PTR:
1978 case VT_SAFEARRAY:
1979 case VT_LPSTR:
1980 case VT_LPWSTR:
1981 *size = ptr_size;
1982 break;
1983 case VT_DATE:
1984 *size = sizeof(DATE);
1985 break;
1986 case VT_VARIANT:
1987 *size = sizeof(VARIANT);
1988 #ifdef _WIN64
1989 if(sys == SYS_WIN32)
1990 *size -= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1991 #endif
1992 break;
1993 case VT_DECIMAL:
1994 *size = sizeof(DECIMAL);
1995 break;
1996 case VT_CY:
1997 *size = sizeof(CY);
1998 break;
1999 case VT_CARRAY:
2000 *size = 0;
2001 for(i = 0; i < tdesc->u.lpadesc->cDims; ++i)
2002 *size += tdesc->u.lpadesc->rgbounds[i].cElements;
2003 hr = TLB_size_instance(info, sys, &tdesc->u.lpadesc->tdescElem, &sub, align);
2004 if(FAILED(hr))
2005 return hr;
2006 *size *= sub;
2007 return S_OK;
2008 case VT_USERDEFINED:
2009 return TLB_get_size_from_hreftype(info, tdesc->u.hreftype, size, align);
2010 default:
2011 FIXME("Unsized VT: 0x%x\n", tdesc->vt);
2012 return E_FAIL;
2015 if(align){
2016 if(*size < 4)
2017 *align = *size;
2018 else
2019 *align = 4;
2022 return S_OK;
2025 /**********************************************************************
2027 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2030 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
2032 if (where != DO_NOT_SEEK)
2034 where += pcx->oStart;
2035 if (where > pcx->length)
2037 /* FIXME */
2038 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
2039 TLB_abort();
2041 pcx->pos = where;
2045 /* read function */
2046 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
2048 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2049 pcx->pos, count, pcx->oStart, pcx->length, where);
2051 MSFT_Seek(pcx, where);
2052 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
2053 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
2054 pcx->pos += count;
2055 return count;
2058 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
2059 LONG where )
2061 DWORD ret;
2063 ret = MSFT_Read(buffer, count, pcx, where);
2064 FromLEDWords(buffer, ret);
2066 return ret;
2069 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
2070 LONG where )
2072 DWORD ret;
2074 ret = MSFT_Read(buffer, count, pcx, where);
2075 FromLEWords(buffer, ret);
2077 return ret;
2080 static HRESULT MSFT_ReadAllGuids(TLBContext *pcx)
2082 TLBGuid *guid;
2083 MSFT_GuidEntry entry;
2084 int offs = 0;
2086 MSFT_Seek(pcx, pcx->pTblDir->pGuidTab.offset);
2087 while (1) {
2088 if (offs >= pcx->pTblDir->pGuidTab.length)
2089 return S_OK;
2091 MSFT_ReadLEWords(&entry, sizeof(MSFT_GuidEntry), pcx, DO_NOT_SEEK);
2093 guid = heap_alloc(sizeof(TLBGuid));
2095 guid->offset = offs;
2096 guid->guid = entry.guid;
2097 guid->hreftype = entry.hreftype;
2099 list_add_tail(&pcx->pLibInfo->guid_list, &guid->entry);
2101 offs += sizeof(MSFT_GuidEntry);
2105 static TLBGuid *MSFT_ReadGuid( int offset, TLBContext *pcx)
2107 TLBGuid *ret;
2109 LIST_FOR_EACH_ENTRY(ret, &pcx->pLibInfo->guid_list, TLBGuid, entry){
2110 if(ret->offset == offset){
2111 TRACE_(typelib)("%s\n", debugstr_guid(&ret->guid));
2112 return ret;
2116 return NULL;
2119 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
2121 MSFT_NameIntro niName;
2123 if (offset < 0)
2125 ERR_(typelib)("bad offset %d\n", offset);
2126 return -1;
2129 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
2130 pcx->pTblDir->pNametab.offset+offset);
2132 return niName.hreftype;
2135 static HRESULT MSFT_ReadAllNames(TLBContext *pcx)
2137 char *string;
2138 MSFT_NameIntro intro;
2139 INT16 len_piece;
2140 int offs = 0, lengthInChars;
2142 MSFT_Seek(pcx, pcx->pTblDir->pNametab.offset);
2143 while (1) {
2144 TLBString *tlbstr;
2146 if (offs >= pcx->pTblDir->pNametab.length)
2147 return S_OK;
2149 MSFT_ReadLEWords(&intro, sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2150 intro.namelen &= 0xFF;
2151 len_piece = intro.namelen + sizeof(MSFT_NameIntro);
2152 if(len_piece % 4)
2153 len_piece = (len_piece + 4) & ~0x3;
2154 if(len_piece < 8)
2155 len_piece = 8;
2157 string = heap_alloc(len_piece + 1);
2158 MSFT_Read(string, len_piece - sizeof(MSFT_NameIntro), pcx, DO_NOT_SEEK);
2159 string[intro.namelen] = '\0';
2161 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2162 string, -1, NULL, 0);
2163 if (!lengthInChars) {
2164 heap_free(string);
2165 return E_UNEXPECTED;
2168 tlbstr = heap_alloc(sizeof(TLBString));
2170 tlbstr->offset = offs;
2171 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2172 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2174 heap_free(string);
2176 list_add_tail(&pcx->pLibInfo->name_list, &tlbstr->entry);
2178 offs += len_piece;
2182 static TLBString *MSFT_ReadName( TLBContext *pcx, int offset)
2184 TLBString *tlbstr;
2186 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->name_list, TLBString, entry) {
2187 if (tlbstr->offset == offset) {
2188 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2189 return tlbstr;
2193 return NULL;
2196 static TLBString *MSFT_ReadString( TLBContext *pcx, int offset)
2198 TLBString *tlbstr;
2200 LIST_FOR_EACH_ENTRY(tlbstr, &pcx->pLibInfo->string_list, TLBString, entry) {
2201 if (tlbstr->offset == offset) {
2202 TRACE_(typelib)("%s\n", debugstr_w(tlbstr->str));
2203 return tlbstr;
2207 return NULL;
2211 * read a value and fill a VARIANT structure
2213 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
2215 int size;
2217 TRACE_(typelib)("\n");
2219 if(offset <0) { /* data are packed in here */
2220 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
2221 V_I4(pVar) = offset & 0x3ffffff;
2222 return;
2224 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
2225 pcx->pTblDir->pCustData.offset + offset );
2226 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
2227 switch (V_VT(pVar)){
2228 case VT_EMPTY: /* FIXME: is this right? */
2229 case VT_NULL: /* FIXME: is this right? */
2230 case VT_I2 : /* this should not happen */
2231 case VT_I4 :
2232 case VT_R4 :
2233 case VT_ERROR :
2234 case VT_BOOL :
2235 case VT_I1 :
2236 case VT_UI1 :
2237 case VT_UI2 :
2238 case VT_UI4 :
2239 case VT_INT :
2240 case VT_UINT :
2241 case VT_VOID : /* FIXME: is this right? */
2242 case VT_HRESULT :
2243 size=4; break;
2244 case VT_R8 :
2245 case VT_CY :
2246 case VT_DATE :
2247 case VT_I8 :
2248 case VT_UI8 :
2249 case VT_DECIMAL : /* FIXME: is this right? */
2250 case VT_FILETIME :
2251 size=8;break;
2252 /* pointer types with known behaviour */
2253 case VT_BSTR :{
2254 char * ptr;
2255 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
2256 if(size == -1){
2257 V_BSTR(pVar) = NULL;
2258 }else{
2259 ptr = heap_alloc_zero(size);
2260 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);
2261 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
2262 /* FIXME: do we need a AtoW conversion here? */
2263 V_UNION(pVar, bstrVal[size])='\0';
2264 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
2265 heap_free(ptr);
2268 size=-4; break;
2269 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2270 case VT_DISPATCH :
2271 case VT_VARIANT :
2272 case VT_UNKNOWN :
2273 case VT_PTR :
2274 case VT_SAFEARRAY :
2275 case VT_CARRAY :
2276 case VT_USERDEFINED :
2277 case VT_LPSTR :
2278 case VT_LPWSTR :
2279 case VT_BLOB :
2280 case VT_STREAM :
2281 case VT_STORAGE :
2282 case VT_STREAMED_OBJECT :
2283 case VT_STORED_OBJECT :
2284 case VT_BLOB_OBJECT :
2285 case VT_CF :
2286 case VT_CLSID :
2287 default:
2288 size=0;
2289 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2290 V_VT(pVar));
2293 if(size>0) /* (big|small) endian correct? */
2294 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
2295 return;
2298 * create a linked list with custom data
2300 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
2302 MSFT_CDGuid entry;
2303 TLBCustData* pNew;
2304 int count=0;
2306 TRACE_(typelib)("\n");
2308 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
2310 while(offset >=0){
2311 count++;
2312 pNew=heap_alloc_zero(sizeof(TLBCustData));
2313 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
2314 pNew->guid = MSFT_ReadGuid(entry.GuidOffset, pcx);
2315 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
2316 list_add_head(custdata_list, &pNew->entry);
2317 offset = entry.next;
2319 return count;
2322 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd)
2324 if(type <0)
2325 pTd->vt=type & VT_TYPEMASK;
2326 else
2327 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
2329 TRACE_(typelib)("vt type = %X\n", pTd->vt);
2332 static BOOL TLB_is_propgetput(INVOKEKIND invkind)
2334 return (invkind == INVOKE_PROPERTYGET ||
2335 invkind == INVOKE_PROPERTYPUT ||
2336 invkind == INVOKE_PROPERTYPUTREF);
2339 static void
2340 MSFT_DoFuncs(TLBContext* pcx,
2341 ITypeInfoImpl* pTI,
2342 int cFuncs,
2343 int cVars,
2344 int offset,
2345 TLBFuncDesc** pptfd)
2348 * member information is stored in a data structure at offset
2349 * indicated by the memoffset field of the typeinfo structure
2350 * There are several distinctive parts.
2351 * The first part starts with a field that holds the total length
2352 * of this (first) part excluding this field. Then follow the records,
2353 * for each member there is one record.
2355 * The first entry is always the length of the record (including this
2356 * length word).
2357 * The rest of the record depends on the type of the member. If there is
2358 * a field indicating the member type (function, variable, interface, etc)
2359 * I have not found it yet. At this time we depend on the information
2360 * in the type info and the usual order how things are stored.
2362 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2363 * for each member;
2365 * Third is an equal sized array with file offsets to the name entry
2366 * of each member.
2368 * The fourth and last (?) part is an array with offsets to the records
2369 * in the first part of this file segment.
2372 int infolen, nameoffset, reclength, i;
2373 int recoffset = offset + sizeof(INT);
2375 char *recbuf = heap_alloc(0xffff);
2376 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2377 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2379 TRACE_(typelib)("\n");
2381 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2383 *pptfd = TLBFuncDesc_Alloc(cFuncs);
2384 ptfd = *pptfd;
2385 for ( i = 0; i < cFuncs ; i++ )
2387 int optional;
2389 /* name, eventually add to a hash table */
2390 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2391 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2393 /* read the function information record */
2394 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2396 reclength &= 0xffff;
2398 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2400 /* size without argument data */
2401 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2402 if (pFuncRec->FKCCIC & 0x1000)
2403 optional -= pFuncRec->nrargs * sizeof(INT);
2405 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2406 ptfd->helpcontext = pFuncRec->HelpContext;
2408 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2409 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2411 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2413 if (pFuncRec->FKCCIC & 0x2000 )
2415 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2416 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2417 ptfd->Entry = (TLBString*)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2419 else
2420 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2422 else
2423 ptfd->Entry = (TLBString*)-1;
2425 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2426 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2428 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2429 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2431 /* fill the FuncDesc Structure */
2432 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2433 offset + infolen + ( i + 1) * sizeof(INT));
2435 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2436 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2437 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2438 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2439 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2440 ptfd->funcdesc.oVft = (pFuncRec->VtableOffset & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
2441 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2443 /* nameoffset is sometimes -1 on the second half of a propget/propput
2444 * pair of functions */
2445 if ((nameoffset == -1) && (i > 0) &&
2446 TLB_is_propgetput(ptfd_prev->funcdesc.invkind) &&
2447 TLB_is_propgetput(ptfd->funcdesc.invkind))
2448 ptfd->Name = ptfd_prev->Name;
2449 else
2450 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2452 MSFT_GetTdesc(pcx,
2453 pFuncRec->DataType,
2454 &ptfd->funcdesc.elemdescFunc.tdesc);
2456 /* do the parameters/arguments */
2457 if(pFuncRec->nrargs)
2459 int j = 0;
2460 MSFT_ParameterInfo paraminfo;
2462 ptfd->funcdesc.lprgelemdescParam =
2463 heap_alloc_zero(pFuncRec->nrargs * (sizeof(ELEMDESC) + sizeof(PARAMDESCEX)));
2465 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2467 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2468 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2470 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2472 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2474 MSFT_GetTdesc(pcx,
2475 paraminfo.DataType,
2476 &elemdesc->tdesc);
2478 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2480 /* name */
2481 if (paraminfo.oName != -1)
2482 ptfd->pParamDesc[j].Name =
2483 MSFT_ReadName( pcx, paraminfo.oName );
2484 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(TLB_get_bstr(ptfd->pParamDesc[j].Name)));
2486 /* default value */
2487 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2488 (pFuncRec->FKCCIC & 0x1000) )
2490 INT* pInt = (INT *)((char *)pFuncRec +
2491 reclength -
2492 (pFuncRec->nrargs * 4) * sizeof(INT) );
2494 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2496 pParamDesc->pparamdescex = (PARAMDESCEX*)(ptfd->funcdesc.lprgelemdescParam+pFuncRec->nrargs)+j;
2497 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2499 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2500 pInt[j], pcx);
2502 else
2503 elemdesc->u.paramdesc.pparamdescex = NULL;
2505 /* custom info */
2506 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2507 j*sizeof(pFuncRec->oArgCustData[0])) &&
2508 pFuncRec->FKCCIC & 0x80 )
2510 MSFT_CustData(pcx,
2511 pFuncRec->oArgCustData[j],
2512 &ptfd->pParamDesc[j].custdata_list);
2515 /* SEEK value = jump to offset,
2516 * from there jump to the end of record,
2517 * go back by (j-1) arguments
2519 MSFT_ReadLEDWords( &paraminfo ,
2520 sizeof(MSFT_ParameterInfo), pcx,
2521 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2522 * sizeof(MSFT_ParameterInfo)));
2526 /* scode is not used: archaic win16 stuff FIXME: right? */
2527 ptfd->funcdesc.cScodes = 0 ;
2528 ptfd->funcdesc.lprgscode = NULL ;
2530 ptfd_prev = ptfd;
2531 ++ptfd;
2532 recoffset += reclength;
2534 heap_free(recbuf);
2537 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2538 int cVars, int offset, TLBVarDesc ** pptvd)
2540 int infolen, nameoffset, reclength;
2541 char recbuf[256];
2542 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2543 TLBVarDesc *ptvd;
2544 int i;
2545 int recoffset;
2547 TRACE_(typelib)("\n");
2549 ptvd = *pptvd = TLBVarDesc_Alloc(cVars);
2550 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2551 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2552 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2553 recoffset += offset+sizeof(INT);
2554 for(i=0;i<cVars;i++, ++ptvd){
2555 /* name, eventually add to a hash table */
2556 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2557 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2558 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2559 /* read the variable information record */
2560 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2561 reclength &= 0xff;
2562 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2564 /* optional data */
2565 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2566 ptvd->HelpContext = pVarRec->HelpContext;
2568 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2569 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2571 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2572 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2574 /* fill the VarDesc Structure */
2575 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2576 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2577 ptvd->vardesc.varkind = pVarRec->VarKind;
2578 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2579 MSFT_GetTdesc(pcx, pVarRec->DataType,
2580 &ptvd->vardesc.elemdescVar.tdesc);
2581 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2582 if(pVarRec->VarKind == VAR_CONST ){
2583 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2584 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2585 pVarRec->OffsValue, pcx);
2586 } else
2587 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2588 recoffset += reclength;
2592 /* process Implemented Interfaces of a com class */
2593 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2594 int offset)
2596 int i;
2597 MSFT_RefRecord refrec;
2598 TLBImplType *pImpl;
2600 TRACE_(typelib)("\n");
2602 pTI->impltypes = TLBImplType_Alloc(count);
2603 pImpl = pTI->impltypes;
2604 for(i=0;i<count;i++){
2605 if(offset<0) break; /* paranoia */
2606 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2607 pImpl->hRef = refrec.reftype;
2608 pImpl->implflags=refrec.flags;
2609 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2610 offset=refrec.onext;
2611 ++pImpl;
2615 #ifdef _WIN64
2616 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2617 * and some structures, and fix the alignment */
2618 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl *info)
2620 if(info->typeattr.typekind == TKIND_ALIAS){
2621 switch(info->tdescAlias->vt){
2622 case VT_BSTR:
2623 case VT_DISPATCH:
2624 case VT_UNKNOWN:
2625 case VT_PTR:
2626 case VT_SAFEARRAY:
2627 case VT_LPSTR:
2628 case VT_LPWSTR:
2629 info->typeattr.cbSizeInstance = sizeof(void*);
2630 info->typeattr.cbAlignment = sizeof(void*);
2631 break;
2632 case VT_CARRAY:
2633 case VT_USERDEFINED:
2634 TLB_size_instance(info, SYS_WIN64, info->tdescAlias, &info->typeattr.cbSizeInstance, &info->typeattr.cbAlignment);
2635 break;
2636 case VT_VARIANT:
2637 info->typeattr.cbSizeInstance = sizeof(VARIANT);
2638 info->typeattr.cbAlignment = 8;
2639 default:
2640 if(info->typeattr.cbSizeInstance < sizeof(void*))
2641 info->typeattr.cbAlignment = info->typeattr.cbSizeInstance;
2642 else
2643 info->typeattr.cbAlignment = sizeof(void*);
2644 break;
2646 }else if(info->typeattr.typekind == TKIND_INTERFACE ||
2647 info->typeattr.typekind == TKIND_DISPATCH ||
2648 info->typeattr.typekind == TKIND_COCLASS){
2649 info->typeattr.cbSizeInstance = sizeof(void*);
2650 info->typeattr.cbAlignment = sizeof(void*);
2653 #endif
2656 * process a typeinfo record
2658 static ITypeInfoImpl * MSFT_DoTypeInfo(
2659 TLBContext *pcx,
2660 int count,
2661 ITypeLibImpl * pLibInfo)
2663 MSFT_TypeInfoBase tiBase;
2664 ITypeInfoImpl *ptiRet;
2666 TRACE_(typelib)("count=%u\n", count);
2668 ptiRet = ITypeInfoImpl_Constructor();
2669 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2670 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2672 /* this is where we are coming from */
2673 ptiRet->pTypeLib = pLibInfo;
2674 ptiRet->index=count;
2676 ptiRet->guid = MSFT_ReadGuid(tiBase.posguid, pcx);
2677 ptiRet->typeattr.lcid = pLibInfo->set_lcid; /* FIXME: correct? */
2678 ptiRet->typeattr.lpstrSchema = NULL; /* reserved */
2679 ptiRet->typeattr.cbSizeInstance = tiBase.size;
2680 ptiRet->typeattr.typekind = tiBase.typekind & 0xF;
2681 ptiRet->typeattr.cFuncs = LOWORD(tiBase.cElement);
2682 ptiRet->typeattr.cVars = HIWORD(tiBase.cElement);
2683 ptiRet->typeattr.cbAlignment = (tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2684 ptiRet->typeattr.wTypeFlags = tiBase.flags;
2685 ptiRet->typeattr.wMajorVerNum = LOWORD(tiBase.version);
2686 ptiRet->typeattr.wMinorVerNum = HIWORD(tiBase.version);
2687 ptiRet->typeattr.cImplTypes = tiBase.cImplTypes;
2688 ptiRet->typeattr.cbSizeVft = tiBase.cbSizeVft;
2689 if (ptiRet->typeattr.typekind == TKIND_ALIAS) {
2690 TYPEDESC tmp;
2691 MSFT_GetTdesc(pcx, tiBase.datatype1, &tmp);
2692 ptiRet->tdescAlias = heap_alloc(TLB_SizeTypeDesc(&tmp, TRUE));
2693 TLB_CopyTypeDesc(NULL, &tmp, ptiRet->tdescAlias);
2696 /* FIXME: */
2697 /* IDLDESC idldescType; *//* never saw this one != zero */
2699 /* name, eventually add to a hash table */
2700 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2701 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2702 TRACE_(typelib)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet->Name)));
2703 /* help info */
2704 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2705 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2706 ptiRet->dwHelpContext=tiBase.helpcontext;
2708 if (ptiRet->typeattr.typekind == TKIND_MODULE)
2709 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2711 /* note: InfoType's Help file and HelpStringDll come from the containing
2712 * library. Further HelpString and Docstring appear to be the same thing :(
2714 /* functions */
2715 if(ptiRet->typeattr.cFuncs >0 )
2716 MSFT_DoFuncs(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2717 ptiRet->typeattr.cVars,
2718 tiBase.memoffset, &ptiRet->funcdescs);
2719 /* variables */
2720 if(ptiRet->typeattr.cVars >0 )
2721 MSFT_DoVars(pcx, ptiRet, ptiRet->typeattr.cFuncs,
2722 ptiRet->typeattr.cVars,
2723 tiBase.memoffset, &ptiRet->vardescs);
2724 if(ptiRet->typeattr.cImplTypes >0 ) {
2725 switch(ptiRet->typeattr.typekind)
2727 case TKIND_COCLASS:
2728 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->typeattr.cImplTypes,
2729 tiBase.datatype1);
2730 break;
2731 case TKIND_DISPATCH:
2732 /* This is not -1 when the interface is a non-base dual interface or
2733 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2734 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2735 not this interface.
2738 if (tiBase.datatype1 != -1)
2740 ptiRet->impltypes = TLBImplType_Alloc(1);
2741 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2743 break;
2744 default:
2745 ptiRet->impltypes = TLBImplType_Alloc(1);
2746 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2747 break;
2750 MSFT_CustData(pcx, tiBase.oCustData, ptiRet->pcustdata_list);
2752 TRACE_(typelib)("%s guid: %s kind:%s\n",
2753 debugstr_w(TLB_get_bstr(ptiRet->Name)),
2754 debugstr_guid(TLB_get_guidref(ptiRet->guid)),
2755 typekind_desc[ptiRet->typeattr.typekind]);
2756 if (TRACE_ON(typelib))
2757 dump_TypeInfo(ptiRet);
2759 return ptiRet;
2762 static HRESULT MSFT_ReadAllStrings(TLBContext *pcx)
2764 char *string;
2765 INT16 len_str, len_piece;
2766 int offs = 0, lengthInChars;
2768 MSFT_Seek(pcx, pcx->pTblDir->pStringtab.offset);
2769 while (1) {
2770 TLBString *tlbstr;
2772 if (offs >= pcx->pTblDir->pStringtab.length)
2773 return S_OK;
2775 MSFT_ReadLEWords(&len_str, sizeof(INT16), pcx, DO_NOT_SEEK);
2776 len_piece = len_str + sizeof(INT16);
2777 if(len_piece % 4)
2778 len_piece = (len_piece + 4) & ~0x3;
2779 if(len_piece < 8)
2780 len_piece = 8;
2782 string = heap_alloc(len_piece + 1);
2783 MSFT_Read(string, len_piece - sizeof(INT16), pcx, DO_NOT_SEEK);
2784 string[len_str] = '\0';
2786 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
2787 string, -1, NULL, 0);
2788 if (!lengthInChars) {
2789 heap_free(string);
2790 return E_UNEXPECTED;
2793 tlbstr = heap_alloc(sizeof(TLBString));
2795 tlbstr->offset = offs;
2796 tlbstr->str = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
2797 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, tlbstr->str, lengthInChars);
2799 heap_free(string);
2801 list_add_tail(&pcx->pLibInfo->string_list, &tlbstr->entry);
2803 offs += len_piece;
2807 static HRESULT MSFT_ReadAllRefs(TLBContext *pcx)
2809 TLBRefType *ref;
2810 int offs = 0;
2812 MSFT_Seek(pcx, pcx->pTblDir->pImpInfo.offset);
2813 while (offs < pcx->pTblDir->pImpInfo.length) {
2814 MSFT_ImpInfo impinfo;
2815 TLBImpLib *pImpLib;
2817 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx, DO_NOT_SEEK);
2819 ref = heap_alloc_zero(sizeof(TLBRefType));
2820 list_add_tail(&pcx->pLibInfo->ref_list, &ref->entry);
2822 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2823 if(pImpLib->offset==impinfo.oImpFile)
2824 break;
2826 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2827 ref->reference = offs;
2828 ref->pImpTLInfo = pImpLib;
2829 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2830 ref->guid = MSFT_ReadGuid(impinfo.oGuid, pcx);
2831 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref->guid)));
2832 ref->index = TLB_REF_USE_GUID;
2833 } else
2834 ref->index = impinfo.oGuid;
2835 }else{
2836 ERR("Cannot find a reference\n");
2837 ref->reference = -1;
2838 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2841 offs += sizeof(impinfo);
2844 return S_OK;
2847 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2848 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2849 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2850 * tradeoff here.
2852 static struct list tlb_cache = LIST_INIT(tlb_cache);
2853 static CRITICAL_SECTION cache_section;
2854 static CRITICAL_SECTION_DEBUG cache_section_debug =
2856 0, 0, &cache_section,
2857 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2858 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2860 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2863 typedef struct TLB_PEFile
2865 IUnknown IUnknown_iface;
2866 LONG refs;
2867 HMODULE dll;
2868 HRSRC typelib_resource;
2869 HGLOBAL typelib_global;
2870 LPVOID typelib_base;
2871 } TLB_PEFile;
2873 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2875 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2878 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2880 if (IsEqualIID(riid, &IID_IUnknown))
2882 *ppv = iface;
2883 IUnknown_AddRef(iface);
2884 return S_OK;
2886 *ppv = NULL;
2887 return E_NOINTERFACE;
2890 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2892 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2893 return InterlockedIncrement(&This->refs);
2896 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2898 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2899 ULONG refs = InterlockedDecrement(&This->refs);
2900 if (!refs)
2902 if (This->typelib_global)
2903 FreeResource(This->typelib_global);
2904 if (This->dll)
2905 FreeLibrary(This->dll);
2906 heap_free(This);
2908 return refs;
2911 static const IUnknownVtbl TLB_PEFile_Vtable =
2913 TLB_PEFile_QueryInterface,
2914 TLB_PEFile_AddRef,
2915 TLB_PEFile_Release
2918 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2920 TLB_PEFile *This;
2921 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2923 This = heap_alloc(sizeof(TLB_PEFile));
2924 if (!This)
2925 return E_OUTOFMEMORY;
2927 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2928 This->refs = 1;
2929 This->dll = NULL;
2930 This->typelib_resource = NULL;
2931 This->typelib_global = NULL;
2932 This->typelib_base = NULL;
2934 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2935 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2937 if (This->dll)
2939 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2940 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2941 if (This->typelib_resource)
2943 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2944 if (This->typelib_global)
2946 This->typelib_base = LockResource(This->typelib_global);
2948 if (This->typelib_base)
2950 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2951 *ppBase = This->typelib_base;
2952 *ppFile = &This->IUnknown_iface;
2953 return S_OK;
2958 TRACE("No TYPELIB resource found\n");
2959 hr = E_FAIL;
2962 TLB_PEFile_Release(&This->IUnknown_iface);
2963 return hr;
2966 typedef struct TLB_NEFile
2968 IUnknown IUnknown_iface;
2969 LONG refs;
2970 LPVOID typelib_base;
2971 } TLB_NEFile;
2973 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2975 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2978 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2980 if (IsEqualIID(riid, &IID_IUnknown))
2982 *ppv = iface;
2983 IUnknown_AddRef(iface);
2984 return S_OK;
2986 *ppv = NULL;
2987 return E_NOINTERFACE;
2990 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2992 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2993 return InterlockedIncrement(&This->refs);
2996 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2998 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2999 ULONG refs = InterlockedDecrement(&This->refs);
3000 if (!refs)
3002 heap_free(This->typelib_base);
3003 heap_free(This);
3005 return refs;
3008 static const IUnknownVtbl TLB_NEFile_Vtable =
3010 TLB_NEFile_QueryInterface,
3011 TLB_NEFile_AddRef,
3012 TLB_NEFile_Release
3015 /***********************************************************************
3016 * read_xx_header [internal]
3018 static int read_xx_header( HFILE lzfd )
3020 IMAGE_DOS_HEADER mzh;
3021 char magic[3];
3023 LZSeek( lzfd, 0, SEEK_SET );
3024 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
3025 return 0;
3026 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
3027 return 0;
3029 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3030 if ( 2 != LZRead( lzfd, magic, 2 ) )
3031 return 0;
3033 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
3035 if ( magic[0] == 'N' && magic[1] == 'E' )
3036 return IMAGE_OS2_SIGNATURE;
3037 if ( magic[0] == 'P' && magic[1] == 'E' )
3038 return IMAGE_NT_SIGNATURE;
3040 magic[2] = '\0';
3041 WARN("Can't handle %s files.\n", magic );
3042 return 0;
3046 /***********************************************************************
3047 * find_ne_resource [internal]
3049 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
3050 DWORD *resLen, DWORD *resOff )
3052 IMAGE_OS2_HEADER nehd;
3053 NE_TYPEINFO *typeInfo;
3054 NE_NAMEINFO *nameInfo;
3055 DWORD nehdoffset;
3056 LPBYTE resTab;
3057 DWORD resTabSize;
3058 int count;
3060 /* Read in NE header */
3061 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
3062 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return FALSE;
3064 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
3065 if ( !resTabSize )
3067 TRACE("No resources in NE dll\n" );
3068 return FALSE;
3071 /* Read in resource table */
3072 resTab = heap_alloc( resTabSize );
3073 if ( !resTab ) return FALSE;
3075 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
3076 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
3078 heap_free( resTab );
3079 return FALSE;
3082 /* Find resource */
3083 typeInfo = (NE_TYPEINFO *)(resTab + 2);
3085 if (!IS_INTRESOURCE(typeid)) /* named type */
3087 BYTE len = strlen( typeid );
3088 while (typeInfo->type_id)
3090 if (!(typeInfo->type_id & 0x8000))
3092 BYTE *p = resTab + typeInfo->type_id;
3093 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
3095 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3096 typeInfo->count * sizeof(NE_NAMEINFO));
3099 else /* numeric type id */
3101 WORD id = LOWORD(typeid) | 0x8000;
3102 while (typeInfo->type_id)
3104 if (typeInfo->type_id == id) goto found_type;
3105 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
3106 typeInfo->count * sizeof(NE_NAMEINFO));
3109 TRACE("No typeid entry found for %p\n", typeid );
3110 heap_free( resTab );
3111 return FALSE;
3113 found_type:
3114 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
3116 if (!IS_INTRESOURCE(resid)) /* named resource */
3118 BYTE len = strlen( resid );
3119 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3121 BYTE *p = resTab + nameInfo->id;
3122 if (nameInfo->id & 0x8000) continue;
3123 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
3126 else /* numeric resource id */
3128 WORD id = LOWORD(resid) | 0x8000;
3129 for (count = typeInfo->count; count > 0; count--, nameInfo++)
3130 if (nameInfo->id == id) goto found_name;
3132 TRACE("No resid entry found for %p\n", typeid );
3133 heap_free( resTab );
3134 return FALSE;
3136 found_name:
3137 /* Return resource data */
3138 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
3139 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
3141 heap_free( resTab );
3142 return TRUE;
3145 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
3147 HFILE lzfd = -1;
3148 OFSTRUCT ofs;
3149 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
3150 TLB_NEFile *This;
3152 This = heap_alloc(sizeof(TLB_NEFile));
3153 if (!This) return E_OUTOFMEMORY;
3155 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
3156 This->refs = 1;
3157 This->typelib_base = NULL;
3159 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
3160 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
3162 DWORD reslen, offset;
3163 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
3165 This->typelib_base = heap_alloc(reslen);
3166 if( !This->typelib_base )
3167 hr = E_OUTOFMEMORY;
3168 else
3170 LZSeek( lzfd, offset, SEEK_SET );
3171 reslen = LZRead( lzfd, This->typelib_base, reslen );
3172 LZClose( lzfd );
3173 *ppBase = This->typelib_base;
3174 *pdwTLBLength = reslen;
3175 *ppFile = &This->IUnknown_iface;
3176 return S_OK;
3181 if( lzfd >= 0) LZClose( lzfd );
3182 TLB_NEFile_Release(&This->IUnknown_iface);
3183 return hr;
3186 typedef struct TLB_Mapping
3188 IUnknown IUnknown_iface;
3189 LONG refs;
3190 HANDLE file;
3191 HANDLE mapping;
3192 LPVOID typelib_base;
3193 } TLB_Mapping;
3195 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
3197 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
3200 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
3202 if (IsEqualIID(riid, &IID_IUnknown))
3204 *ppv = iface;
3205 IUnknown_AddRef(iface);
3206 return S_OK;
3208 *ppv = NULL;
3209 return E_NOINTERFACE;
3212 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
3214 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3215 return InterlockedIncrement(&This->refs);
3218 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
3220 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
3221 ULONG refs = InterlockedDecrement(&This->refs);
3222 if (!refs)
3224 if (This->typelib_base)
3225 UnmapViewOfFile(This->typelib_base);
3226 if (This->mapping)
3227 CloseHandle(This->mapping);
3228 if (This->file != INVALID_HANDLE_VALUE)
3229 CloseHandle(This->file);
3230 heap_free(This);
3232 return refs;
3235 static const IUnknownVtbl TLB_Mapping_Vtable =
3237 TLB_Mapping_QueryInterface,
3238 TLB_Mapping_AddRef,
3239 TLB_Mapping_Release
3242 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
3244 TLB_Mapping *This;
3246 This = heap_alloc(sizeof(TLB_Mapping));
3247 if (!This)
3248 return E_OUTOFMEMORY;
3250 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
3251 This->refs = 1;
3252 This->file = INVALID_HANDLE_VALUE;
3253 This->mapping = NULL;
3254 This->typelib_base = NULL;
3256 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
3257 if (INVALID_HANDLE_VALUE != This->file)
3259 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
3260 if (This->mapping)
3262 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
3263 if(This->typelib_base)
3265 /* retrieve file size */
3266 *pdwTLBLength = GetFileSize(This->file, NULL);
3267 *ppBase = This->typelib_base;
3268 *ppFile = &This->IUnknown_iface;
3269 return S_OK;
3274 IUnknown_Release(&This->IUnknown_iface);
3275 return TYPE_E_CANTLOADLIBRARY;
3278 /****************************************************************************
3279 * TLB_ReadTypeLib
3281 * find the type of the typelib file and map the typelib resource into
3282 * the memory
3285 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3286 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
3288 ITypeLibImpl *entry;
3289 HRESULT ret;
3290 INT index = 1;
3291 LPWSTR index_str, file = (LPWSTR)pszFileName;
3292 LPVOID pBase = NULL;
3293 DWORD dwTLBLength = 0;
3294 IUnknown *pFile = NULL;
3295 HANDLE h;
3297 *ppTypeLib = NULL;
3299 index_str = strrchrW(pszFileName, '\\');
3300 if(index_str && *++index_str != '\0')
3302 LPWSTR end_ptr;
3303 LONG idx = strtolW(index_str, &end_ptr, 10);
3304 if(*end_ptr == '\0')
3306 int str_len = index_str - pszFileName - 1;
3307 index = idx;
3308 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
3309 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
3310 file[str_len] = 0;
3314 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
3316 if(strchrW(file, '\\'))
3318 lstrcpyW(pszPath, file);
3320 else
3322 int len = GetSystemDirectoryW(pszPath, cchPath);
3323 pszPath[len] = '\\';
3324 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
3328 if(file != pszFileName) heap_free(file);
3330 h = CreateFileW(pszPath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
3331 if(h != INVALID_HANDLE_VALUE){
3332 FILE_NAME_INFORMATION size_info;
3333 BOOL br;
3335 /* GetFileInformationByHandleEx returns the path of the file without
3336 * WOW64 redirection */
3337 br = GetFileInformationByHandleEx(h, FileNameInfo, &size_info, sizeof(size_info));
3338 if(br || GetLastError() == ERROR_MORE_DATA){
3339 FILE_NAME_INFORMATION *info;
3340 DWORD size = sizeof(*info) + size_info.FileNameLength + sizeof(WCHAR);
3342 info = HeapAlloc(GetProcessHeap(), 0, size);
3344 br = GetFileInformationByHandleEx(h, FileNameInfo, info, size);
3345 if(br){
3346 info->FileName[info->FileNameLength / sizeof(WCHAR)] = 0;
3347 lstrcpynW(pszPath + 2, info->FileName, cchPath - 2);
3350 HeapFree(GetProcessHeap(), 0, info);
3353 CloseHandle(h);
3356 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
3358 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3359 EnterCriticalSection(&cache_section);
3360 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
3362 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
3364 TRACE("cache hit\n");
3365 *ppTypeLib = &entry->ITypeLib2_iface;
3366 ITypeLib2_AddRef(*ppTypeLib);
3367 LeaveCriticalSection(&cache_section);
3368 return S_OK;
3371 LeaveCriticalSection(&cache_section);
3373 /* now actually load and parse the typelib */
3375 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3376 if (ret == TYPE_E_CANTLOADLIBRARY)
3377 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
3378 if (ret == TYPE_E_CANTLOADLIBRARY)
3379 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
3380 if (SUCCEEDED(ret))
3382 if (dwTLBLength >= 4)
3384 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
3385 if (dwSignature == MSFT_SIGNATURE)
3386 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
3387 else if (dwSignature == SLTG_SIGNATURE)
3388 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
3389 else
3391 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
3392 ret = TYPE_E_CANTLOADLIBRARY;
3395 else
3396 ret = TYPE_E_CANTLOADLIBRARY;
3397 IUnknown_Release(pFile);
3400 if(*ppTypeLib) {
3401 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
3403 TRACE("adding to cache\n");
3404 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
3405 lstrcpyW(impl->path, pszPath);
3406 /* We should really canonicalise the path here. */
3407 impl->index = index;
3409 /* FIXME: check if it has added already in the meantime */
3410 EnterCriticalSection(&cache_section);
3411 list_add_head(&tlb_cache, &impl->entry);
3412 LeaveCriticalSection(&cache_section);
3413 ret = S_OK;
3415 else
3417 if(ret != E_FAIL)
3418 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3420 ret = TYPE_E_CANTLOADLIBRARY;
3424 return ret;
3427 /*================== ITypeLib(2) Methods ===================================*/
3429 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3431 ITypeLibImpl* pTypeLibImpl;
3433 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3434 if (!pTypeLibImpl) return NULL;
3436 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3437 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3438 pTypeLibImpl->ICreateTypeLib2_iface.lpVtbl = &CreateTypeLib2Vtbl;
3439 pTypeLibImpl->ref = 1;
3441 list_init(&pTypeLibImpl->implib_list);
3442 list_init(&pTypeLibImpl->custdata_list);
3443 list_init(&pTypeLibImpl->name_list);
3444 list_init(&pTypeLibImpl->string_list);
3445 list_init(&pTypeLibImpl->guid_list);
3446 list_init(&pTypeLibImpl->ref_list);
3447 pTypeLibImpl->dispatch_href = -1;
3449 return pTypeLibImpl;
3452 /****************************************************************************
3453 * ITypeLib2_Constructor_MSFT
3455 * loading an MSFT typelib from an in-memory image
3457 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3459 TLBContext cx;
3460 LONG lPSegDir;
3461 MSFT_Header tlbHeader;
3462 MSFT_SegDir tlbSegDir;
3463 ITypeLibImpl * pTypeLibImpl;
3464 int i;
3466 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3468 pTypeLibImpl = TypeLibImpl_Constructor();
3469 if (!pTypeLibImpl) return NULL;
3471 /* get pointer to beginning of typelib data */
3472 cx.pos = 0;
3473 cx.oStart=0;
3474 cx.mapping = pLib;
3475 cx.pLibInfo = pTypeLibImpl;
3476 cx.length = dwTLBLength;
3478 /* read header */
3479 MSFT_ReadLEDWords(&tlbHeader, sizeof(tlbHeader), &cx, 0);
3480 TRACE_(typelib)("header:\n");
3481 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3482 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3483 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3484 return NULL;
3486 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3488 /* there is a small amount of information here until the next important
3489 * part:
3490 * the segment directory . Try to calculate the amount of data */
3491 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3493 /* now read the segment directory */
3494 TRACE("read segment directory (at %d)\n",lPSegDir);
3495 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3496 cx.pTblDir = &tlbSegDir;
3498 /* just check two entries */
3499 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3501 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3502 heap_free(pTypeLibImpl);
3503 return NULL;
3506 MSFT_ReadAllNames(&cx);
3507 MSFT_ReadAllStrings(&cx);
3508 MSFT_ReadAllGuids(&cx);
3510 /* now fill our internal data */
3511 /* TLIBATTR fields */
3512 pTypeLibImpl->guid = MSFT_ReadGuid(tlbHeader.posguid, &cx);
3514 pTypeLibImpl->syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3515 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3516 pTypeLibImpl->ver_major = LOWORD(tlbHeader.version);
3517 pTypeLibImpl->ver_minor = HIWORD(tlbHeader.version);
3518 pTypeLibImpl->libflags = ((WORD) tlbHeader.flags & 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE;
3520 pTypeLibImpl->set_lcid = tlbHeader.lcid2;
3521 pTypeLibImpl->lcid = tlbHeader.lcid;
3523 /* name, eventually add to a hash table */
3524 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3526 /* help info */
3527 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3528 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3530 if( tlbHeader.varflags & HELPDLLFLAG)
3532 int offset;
3533 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3534 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3537 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3539 /* custom data */
3540 if(tlbHeader.CustomDataOffset >= 0)
3542 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3545 /* fill in type descriptions */
3546 if(tlbSegDir.pTypdescTab.length > 0)
3548 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3549 INT16 td[4];
3550 pTypeLibImpl->ctTypeDesc = cTD;
3551 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3552 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3553 for(i=0; i<cTD; )
3555 /* FIXME: add several sanity checks here */
3556 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3557 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3559 /* FIXME: check safearray */
3560 if(td[3] < 0)
3561 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3562 else
3563 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3565 else if(td[0] == VT_CARRAY)
3567 /* array descr table here */
3568 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3570 else if(td[0] == VT_USERDEFINED)
3572 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3574 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3577 /* second time around to fill the array subscript info */
3578 for(i=0;i<cTD;i++)
3580 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3581 if(tlbSegDir.pArrayDescriptions.offset>0)
3583 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3584 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3586 if(td[1]<0)
3587 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3588 else
3589 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3591 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3593 for(j = 0; j<td[2]; j++)
3595 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3596 sizeof(INT), &cx, DO_NOT_SEEK);
3597 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3598 sizeof(INT), &cx, DO_NOT_SEEK);
3601 else
3603 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3604 ERR("didn't find array description data\n");
3609 /* imported type libs */
3610 if(tlbSegDir.pImpFiles.offset>0)
3612 TLBImpLib *pImpLib;
3613 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3614 UINT16 size;
3616 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3618 char *name;
3620 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3621 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3622 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3624 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3625 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3626 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3627 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3629 size >>= 2;
3630 name = heap_alloc_zero(size+1);
3631 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3632 pImpLib->name = TLB_MultiByteToBSTR(name);
3633 heap_free(name);
3635 pImpLib->guid = MSFT_ReadGuid(oGuid, &cx);
3636 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3638 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3642 MSFT_ReadAllRefs(&cx);
3644 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3646 /* type infos */
3647 if(tlbHeader.nrtypeinfos >= 0 )
3649 ITypeInfoImpl **ppTI;
3651 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3653 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3655 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3657 ++ppTI;
3658 (pTypeLibImpl->TypeInfoCount)++;
3662 #ifdef _WIN64
3663 if(pTypeLibImpl->syskind == SYS_WIN32){
3664 for(i = 0; i < pTypeLibImpl->TypeInfoCount; ++i)
3665 TLB_fix_32on64_typeinfo(pTypeLibImpl->typeinfos[i]);
3667 #endif
3669 TRACE("(%p)\n", pTypeLibImpl);
3670 return &pTypeLibImpl->ITypeLib2_iface;
3674 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3676 char b[3];
3677 int i;
3678 short s;
3680 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3681 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3682 return FALSE;
3685 guid->Data4[0] = s >> 8;
3686 guid->Data4[1] = s & 0xff;
3688 b[2] = '\0';
3689 for(i = 0; i < 6; i++) {
3690 memcpy(b, str + 24 + 2 * i, 2);
3691 guid->Data4[i + 2] = strtol(b, NULL, 16);
3693 return TRUE;
3696 static WORD SLTG_ReadString(const char *ptr, const TLBString **pStr, ITypeLibImpl *lib)
3698 WORD bytelen;
3699 DWORD len;
3700 BSTR tmp_str;
3702 *pStr = NULL;
3703 bytelen = *(const WORD*)ptr;
3704 if(bytelen == 0xffff) return 2;
3706 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3707 tmp_str = SysAllocStringLen(NULL, len);
3708 if (tmp_str) {
3709 MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, tmp_str, len);
3710 *pStr = TLB_append_str(&lib->string_list, tmp_str);
3711 SysFreeString(tmp_str);
3713 return bytelen + 2;
3716 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3718 WORD bytelen;
3720 *str = NULL;
3721 bytelen = *(const WORD*)ptr;
3722 if(bytelen == 0xffff) return 2;
3723 *str = heap_alloc(bytelen + 1);
3724 memcpy(*str, ptr + 2, bytelen);
3725 (*str)[bytelen] = '\0';
3726 return bytelen + 2;
3729 static TLBString *SLTG_ReadName(const char *pNameTable, int offset, ITypeLibImpl *lib)
3731 BSTR tmp_str;
3732 TLBString *tlbstr;
3734 LIST_FOR_EACH_ENTRY(tlbstr, &lib->name_list, TLBString, entry) {
3735 if (tlbstr->offset == offset)
3736 return tlbstr;
3739 tmp_str = TLB_MultiByteToBSTR(pNameTable + offset);
3740 tlbstr = TLB_append_str(&lib->name_list, tmp_str);
3741 SysFreeString(tmp_str);
3743 return tlbstr;
3746 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3748 char *ptr = pLibBlk;
3749 WORD w;
3751 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3752 FIXME("libblk magic = %04x\n", w);
3753 return 0;
3756 ptr += 6;
3757 if((w = *(WORD*)ptr) != 0xffff) {
3758 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3759 ptr += w;
3761 ptr += 2;
3763 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString, pTypeLibImpl);
3765 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile, pTypeLibImpl);
3767 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3768 ptr += 4;
3770 pTypeLibImpl->syskind = *(WORD*)ptr;
3771 pTypeLibImpl->ptr_size = get_ptr_size(pTypeLibImpl->syskind);
3772 ptr += 2;
3774 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3775 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3776 else
3777 pTypeLibImpl->lcid = pTypeLibImpl->set_lcid = 0;
3778 ptr += 2;
3780 ptr += 4; /* skip res12 */
3782 pTypeLibImpl->libflags = *(WORD*)ptr;
3783 ptr += 2;
3785 pTypeLibImpl->ver_major = *(WORD*)ptr;
3786 ptr += 2;
3788 pTypeLibImpl->ver_minor = *(WORD*)ptr;
3789 ptr += 2;
3791 pTypeLibImpl->guid = TLB_append_guid(&pTypeLibImpl->guid_list, (GUID*)ptr, -2);
3792 ptr += sizeof(GUID);
3794 return ptr - (char*)pLibBlk;
3797 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3798 typedef struct
3800 unsigned int num;
3801 HREFTYPE refs[1];
3802 } sltg_ref_lookup_t;
3804 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3805 HREFTYPE *typelib_ref)
3807 if(table && typeinfo_ref < table->num)
3809 *typelib_ref = table->refs[typeinfo_ref];
3810 return S_OK;
3813 ERR_(typelib)("Unable to find reference\n");
3814 *typelib_ref = -1;
3815 return E_FAIL;
3818 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3820 BOOL done = FALSE;
3822 while(!done) {
3823 if((*pType & 0xe00) == 0xe00) {
3824 pTD->vt = VT_PTR;
3825 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3826 pTD = pTD->u.lptdesc;
3828 switch(*pType & 0x3f) {
3829 case VT_PTR:
3830 pTD->vt = VT_PTR;
3831 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3832 pTD = pTD->u.lptdesc;
3833 break;
3835 case VT_USERDEFINED:
3836 pTD->vt = VT_USERDEFINED;
3837 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3838 done = TRUE;
3839 break;
3841 case VT_CARRAY:
3843 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3844 array */
3846 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3848 pTD->vt = VT_CARRAY;
3849 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3850 pTD->u.lpadesc->cDims = pSA->cDims;
3851 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3852 pSA->cDims * sizeof(SAFEARRAYBOUND));
3854 pTD = &pTD->u.lpadesc->tdescElem;
3855 break;
3858 case VT_SAFEARRAY:
3860 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3861 useful? */
3863 pType++;
3864 pTD->vt = VT_SAFEARRAY;
3865 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3866 pTD = pTD->u.lptdesc;
3867 break;
3869 default:
3870 pTD->vt = *pType & 0x3f;
3871 done = TRUE;
3872 break;
3874 pType++;
3876 return pType;
3879 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3880 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3882 /* Handle [in/out] first */
3883 if((*pType & 0xc000) == 0xc000)
3884 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3885 else if(*pType & 0x8000)
3886 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3887 else if(*pType & 0x4000)
3888 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3889 else
3890 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3892 if(*pType & 0x2000)
3893 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3895 if(*pType & 0x80)
3896 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3898 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3902 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3903 char *pNameTable)
3905 unsigned int ref;
3906 char *name;
3907 TLBRefType *ref_type;
3908 sltg_ref_lookup_t *table;
3909 HREFTYPE typelib_ref;
3911 if(pRef->magic != SLTG_REF_MAGIC) {
3912 FIXME("Ref magic = %x\n", pRef->magic);
3913 return NULL;
3915 name = ( (char*)pRef->names + pRef->number);
3917 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3918 table->num = pRef->number >> 3;
3920 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3922 /* We don't want the first href to be 0 */
3923 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3925 for(ref = 0; ref < pRef->number >> 3; ref++) {
3926 char *refname;
3927 unsigned int lib_offs, type_num;
3929 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3931 name += SLTG_ReadStringA(name, &refname);
3932 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3933 FIXME_(typelib)("Can't sscanf ref\n");
3934 if(lib_offs != 0xffff) {
3935 TLBImpLib *import;
3937 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3938 if(import->offset == lib_offs)
3939 break;
3941 if(&import->entry == &pTL->implib_list) {
3942 char fname[MAX_PATH+1];
3943 int len;
3944 GUID tmpguid;
3946 import = heap_alloc_zero(sizeof(*import));
3947 import->offset = lib_offs;
3948 TLB_GUIDFromString( pNameTable + lib_offs + 4, &tmpguid);
3949 import->guid = TLB_append_guid(&pTL->guid_list, &tmpguid, 2);
3950 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3951 &import->wVersionMajor,
3952 &import->wVersionMinor,
3953 &import->lcid, fname) != 4) {
3954 FIXME_(typelib)("can't sscanf ref %s\n",
3955 pNameTable + lib_offs + 40);
3957 len = strlen(fname);
3958 if(fname[len-1] != '#')
3959 FIXME("fname = %s\n", fname);
3960 fname[len-1] = '\0';
3961 import->name = TLB_MultiByteToBSTR(fname);
3962 list_add_tail(&pTL->implib_list, &import->entry);
3964 ref_type->pImpTLInfo = import;
3966 /* Store a reference to IDispatch */
3967 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid->guid, &IID_StdOle) && type_num == 4)
3968 pTL->dispatch_href = typelib_ref;
3970 } else { /* internal ref */
3971 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3973 ref_type->reference = typelib_ref;
3974 ref_type->index = type_num;
3976 heap_free(refname);
3977 list_add_tail(&pTL->ref_list, &ref_type->entry);
3979 table->refs[ref] = typelib_ref;
3980 typelib_ref += 4;
3982 if((BYTE)*name != SLTG_REF_MAGIC)
3983 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3984 dump_TLBRefType(pTL);
3985 return table;
3988 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3989 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3991 SLTG_ImplInfo *info;
3992 TLBImplType *pImplType;
3993 /* I don't really get this structure, usually it's 0x16 bytes
3994 long, but iuser.tlb contains some that are 0x18 bytes long.
3995 That's ok because we can use the next ptr to jump to the next
3996 one. But how do we know the length of the last one? The WORD
3997 at offs 0x8 might be the clue. For now I'm just assuming that
3998 the last one is the regular 0x16 bytes. */
4000 info = (SLTG_ImplInfo*)pBlk;
4001 while(1){
4002 pTI->typeattr.cImplTypes++;
4003 if(info->next == 0xffff)
4004 break;
4005 info = (SLTG_ImplInfo*)(pBlk + info->next);
4008 info = (SLTG_ImplInfo*)pBlk;
4009 pTI->impltypes = TLBImplType_Alloc(pTI->typeattr.cImplTypes);
4010 pImplType = pTI->impltypes;
4011 while(1) {
4012 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
4013 pImplType->implflags = info->impltypeflags;
4014 ++pImplType;
4016 if(info->next == 0xffff)
4017 break;
4018 if(OneOnly)
4019 FIXME_(typelib)("Interface inheriting more than one interface\n");
4020 info = (SLTG_ImplInfo*)(pBlk + info->next);
4022 info++; /* see comment at top of function */
4023 return (char*)info;
4026 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
4027 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4029 TLBVarDesc *pVarDesc;
4030 const TLBString *prevName = NULL;
4031 SLTG_Variable *pItem;
4032 unsigned short i;
4033 WORD *pType;
4035 pVarDesc = pTI->vardescs = TLBVarDesc_Alloc(cVars);
4037 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
4038 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
4040 pVarDesc->vardesc.memid = pItem->memid;
4042 if (pItem->magic != SLTG_VAR_MAGIC &&
4043 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
4044 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
4045 return;
4048 if (pItem->name == 0xfffe)
4049 pVarDesc->Name = prevName;
4050 else
4051 pVarDesc->Name = SLTG_ReadName(pNameTable, pItem->name, pTI->pTypeLib);
4053 TRACE_(typelib)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc->Name)));
4054 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
4055 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
4057 if(pItem->flags & 0x02)
4058 pType = &pItem->type;
4059 else
4060 pType = (WORD*)(pBlk + pItem->type);
4062 if (pItem->flags & ~0xda)
4063 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
4065 SLTG_DoElem(pType, pBlk,
4066 &pVarDesc->vardesc.elemdescVar, ref_lookup);
4068 if (TRACE_ON(typelib)) {
4069 char buf[300];
4070 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
4071 TRACE_(typelib)("elemdescVar: %s\n", buf);
4074 if (pItem->flags & 0x40) {
4075 TRACE_(typelib)("VAR_DISPATCH\n");
4076 pVarDesc->vardesc.varkind = VAR_DISPATCH;
4078 else if (pItem->flags & 0x10) {
4079 TRACE_(typelib)("VAR_CONST\n");
4080 pVarDesc->vardesc.varkind = VAR_CONST;
4081 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
4082 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
4083 if (pItem->flags & 0x08)
4084 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
4085 else {
4086 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
4088 case VT_LPSTR:
4089 case VT_LPWSTR:
4090 case VT_BSTR:
4092 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
4093 BSTR str;
4094 TRACE_(typelib)("len = %u\n", len);
4095 if (len == 0xffff) {
4096 str = NULL;
4097 } else {
4098 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
4099 str = SysAllocStringLen(NULL, alloc_len);
4100 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
4102 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
4103 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
4104 break;
4106 case VT_I2:
4107 case VT_UI2:
4108 case VT_I4:
4109 case VT_UI4:
4110 case VT_INT:
4111 case VT_UINT:
4112 V_INT(pVarDesc->vardesc.u.lpvarValue) =
4113 *(INT*)(pBlk + pItem->byte_offs);
4114 break;
4115 default:
4116 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
4120 else {
4121 TRACE_(typelib)("VAR_PERINSTANCE\n");
4122 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
4123 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
4126 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
4127 pVarDesc->vardesc.wVarFlags = pItem->varflags;
4129 if (pItem->flags & 0x80)
4130 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
4132 prevName = pVarDesc->Name;
4134 pTI->typeattr.cVars = cVars;
4137 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
4138 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
4140 SLTG_Function *pFunc;
4141 unsigned short i;
4142 TLBFuncDesc *pFuncDesc;
4144 pTI->funcdescs = TLBFuncDesc_Alloc(cFuncs);
4146 pFuncDesc = pTI->funcdescs;
4147 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
4148 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
4150 int param;
4151 WORD *pType, *pArg;
4153 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
4154 case SLTG_FUNCTION_MAGIC:
4155 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
4156 break;
4157 case SLTG_DISPATCH_FUNCTION_MAGIC:
4158 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
4159 break;
4160 case SLTG_STATIC_FUNCTION_MAGIC:
4161 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
4162 break;
4163 default:
4164 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
4165 continue;
4167 pFuncDesc->Name = SLTG_ReadName(pNameTable, pFunc->name, pTI->pTypeLib);
4169 pFuncDesc->funcdesc.memid = pFunc->dispid;
4170 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
4171 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
4172 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
4173 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
4174 pFuncDesc->funcdesc.oVft = (pFunc->vtblpos & ~1) * sizeof(void *) / pTI->pTypeLib->ptr_size;
4176 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
4177 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
4179 if(pFunc->retnextopt & 0x80)
4180 pType = &pFunc->rettype;
4181 else
4182 pType = (WORD*)(pBlk + pFunc->rettype);
4184 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
4186 pFuncDesc->funcdesc.lprgelemdescParam =
4187 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
4188 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
4190 pArg = (WORD*)(pBlk + pFunc->arg_off);
4192 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
4193 char *paramName = pNameTable + *pArg;
4194 BOOL HaveOffs;
4195 /* If arg type follows then paramName points to the 2nd
4196 letter of the name, else the next WORD is an offset to
4197 the arg type and paramName points to the first letter.
4198 So let's take one char off paramName and see if we're
4199 pointing at an alpha-numeric char. However if *pArg is
4200 0xffff or 0xfffe then the param has no name, the former
4201 meaning that the next WORD is the type, the latter
4202 meaning that the next WORD is an offset to the type. */
4204 HaveOffs = FALSE;
4205 if(*pArg == 0xffff)
4206 paramName = NULL;
4207 else if(*pArg == 0xfffe) {
4208 paramName = NULL;
4209 HaveOffs = TRUE;
4211 else if(paramName[-1] && !isalnum(paramName[-1]))
4212 HaveOffs = TRUE;
4214 pArg++;
4216 if(HaveOffs) { /* the next word is an offset to type */
4217 pType = (WORD*)(pBlk + *pArg);
4218 SLTG_DoElem(pType, pBlk,
4219 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4220 pArg++;
4221 } else {
4222 if(paramName)
4223 paramName--;
4224 pArg = SLTG_DoElem(pArg, pBlk,
4225 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
4228 /* Are we an optional param ? */
4229 if(pFuncDesc->funcdesc.cParams - param <=
4230 pFuncDesc->funcdesc.cParamsOpt)
4231 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
4233 if(paramName) {
4234 pFuncDesc->pParamDesc[param].Name = SLTG_ReadName(pNameTable,
4235 paramName - pNameTable, pTI->pTypeLib);
4236 } else {
4237 pFuncDesc->pParamDesc[param].Name = pFuncDesc->Name;
4241 pTI->typeattr.cFuncs = cFuncs;
4244 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
4245 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4246 SLTG_TypeInfoTail *pTITail)
4248 char *pFirstItem;
4249 sltg_ref_lookup_t *ref_lookup = NULL;
4251 if(pTIHeader->href_table != 0xffffffff) {
4252 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4253 pNameTable);
4256 pFirstItem = pBlk;
4258 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4259 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
4261 heap_free(ref_lookup);
4265 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
4266 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4267 const SLTG_TypeInfoTail *pTITail)
4269 char *pFirstItem;
4270 sltg_ref_lookup_t *ref_lookup = NULL;
4272 if(pTIHeader->href_table != 0xffffffff) {
4273 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4274 pNameTable);
4277 pFirstItem = pBlk;
4279 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
4280 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
4283 if (pTITail->funcs_off != 0xffff)
4284 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4286 heap_free(ref_lookup);
4288 if (TRACE_ON(typelib))
4289 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4292 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
4293 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4294 const SLTG_TypeInfoTail *pTITail)
4296 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4299 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
4300 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4301 const SLTG_TypeInfoTail *pTITail)
4303 WORD *pType;
4304 sltg_ref_lookup_t *ref_lookup = NULL;
4306 if (pTITail->simple_alias) {
4307 /* if simple alias, no more processing required */
4308 pTI->tdescAlias = heap_alloc_zero(sizeof(TYPEDESC));
4309 pTI->tdescAlias->vt = pTITail->tdescalias_vt;
4310 return;
4313 if(pTIHeader->href_table != 0xffffffff) {
4314 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4315 pNameTable);
4318 /* otherwise it is an offset to a type */
4319 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
4321 pTI->tdescAlias = heap_alloc(sizeof(TYPEDESC));
4322 SLTG_DoType(pType, pBlk, pTI->tdescAlias, ref_lookup);
4324 heap_free(ref_lookup);
4327 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
4328 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4329 const SLTG_TypeInfoTail *pTITail)
4331 sltg_ref_lookup_t *ref_lookup = NULL;
4332 if (pTIHeader->href_table != 0xffffffff)
4333 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4334 pNameTable);
4336 if (pTITail->vars_off != 0xffff)
4337 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4339 if (pTITail->funcs_off != 0xffff)
4340 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4342 if (pTITail->impls_off != 0xffff)
4343 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
4345 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4346 * of dispinterface functions including the IDispatch ones, so
4347 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4348 pTI->typeattr.cbSizeVft = pTI->typeattr.cFuncs * pTI->pTypeLib->ptr_size;
4350 heap_free(ref_lookup);
4351 if (TRACE_ON(typelib))
4352 dump_TLBFuncDesc(pTI->funcdescs, pTI->typeattr.cFuncs);
4355 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
4356 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4357 const SLTG_TypeInfoTail *pTITail)
4359 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
4362 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
4363 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
4364 const SLTG_TypeInfoTail *pTITail)
4366 sltg_ref_lookup_t *ref_lookup = NULL;
4367 if (pTIHeader->href_table != 0xffffffff)
4368 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
4369 pNameTable);
4371 if (pTITail->vars_off != 0xffff)
4372 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
4374 if (pTITail->funcs_off != 0xffff)
4375 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
4376 heap_free(ref_lookup);
4377 if (TRACE_ON(typelib))
4378 dump_TypeInfo(pTI);
4381 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4382 manageable copy of it into this */
4383 typedef struct {
4384 WORD small_no;
4385 char *index_name;
4386 char *other_name;
4387 WORD res1a;
4388 WORD name_offs;
4389 WORD more_bytes;
4390 char *extra;
4391 WORD res20;
4392 DWORD helpcontext;
4393 WORD res26;
4394 GUID uuid;
4395 } SLTG_InternalOtherTypeInfo;
4397 /****************************************************************************
4398 * ITypeLib2_Constructor_SLTG
4400 * loading a SLTG typelib from an in-memory image
4402 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
4404 ITypeLibImpl *pTypeLibImpl;
4405 SLTG_Header *pHeader;
4406 SLTG_BlkEntry *pBlkEntry;
4407 SLTG_Magic *pMagic;
4408 SLTG_Index *pIndex;
4409 SLTG_Pad9 *pPad9;
4410 LPVOID pBlk, pFirstBlk;
4411 SLTG_LibBlk *pLibBlk;
4412 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
4413 char *pAfterOTIBlks = NULL;
4414 char *pNameTable, *ptr;
4415 int i;
4416 DWORD len, order;
4417 ITypeInfoImpl **ppTypeInfoImpl;
4419 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
4422 pTypeLibImpl = TypeLibImpl_Constructor();
4423 if (!pTypeLibImpl) return NULL;
4425 pHeader = pLib;
4427 TRACE_(typelib)("header:\n");
4428 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
4429 pHeader->nrOfFileBlks );
4430 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
4431 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
4432 pHeader->SLTG_magic);
4433 return NULL;
4436 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4437 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
4439 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4440 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
4442 /* Next we have a magic block */
4443 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
4445 /* Let's see if we're still in sync */
4446 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
4447 sizeof(SLTG_COMPOBJ_MAGIC))) {
4448 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
4449 return NULL;
4451 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4452 sizeof(SLTG_DIR_MAGIC))) {
4453 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4454 return NULL;
4457 pIndex = (SLTG_Index*)(pMagic+1);
4459 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4461 pFirstBlk = pPad9 + 1;
4463 /* We'll set up a ptr to the main library block, which is the last one. */
4465 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1;
4466 pBlkEntry[order].next != 0;
4467 order = pBlkEntry[order].next - 1) {
4468 pBlk = (char*)pBlk + pBlkEntry[order].len;
4470 pLibBlk = pBlk;
4472 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4474 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4475 interspersed */
4477 len += 0x40;
4479 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4481 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4484 ptr = (char*)pLibBlk + len;
4486 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4487 WORD w, extra;
4488 len = 0;
4490 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4492 w = *(WORD*)(ptr + 2);
4493 if(w != 0xffff) {
4494 len += w;
4495 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4496 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4497 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4499 w = *(WORD*)(ptr + 4 + len);
4500 if(w != 0xffff) {
4501 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4502 len += w;
4503 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4504 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4505 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4507 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4508 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4509 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4510 if(extra) {
4511 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4512 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4513 len += extra;
4515 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4516 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4517 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4518 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4519 len += sizeof(SLTG_OtherTypeInfo);
4520 ptr += len;
4523 pAfterOTIBlks = ptr;
4525 /* Skip this WORD and get the next DWORD */
4526 len = *(DWORD*)(pAfterOTIBlks + 2);
4528 /* Now add this to pLibBLk look at what we're pointing at and
4529 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4530 dust and we should be pointing at the beginning of the name
4531 table */
4533 pNameTable = (char*)pLibBlk + len;
4535 switch(*(WORD*)pNameTable) {
4536 case 0xffff:
4537 break;
4538 case 0x0200:
4539 pNameTable += 0x20;
4540 break;
4541 default:
4542 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4543 break;
4546 pNameTable += 0x216;
4548 pNameTable += 2;
4550 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4552 pTypeLibImpl->Name = SLTG_ReadName(pNameTable, pLibBlk->name, pTypeLibImpl);
4555 /* Hopefully we now have enough ptrs set up to actually read in
4556 some TypeInfos. It's not clear which order to do them in, so
4557 I'll just follow the links along the BlkEntry chain and read
4558 them in the order in which they are in the file */
4560 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4561 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4563 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4564 pBlkEntry[order].next != 0;
4565 order = pBlkEntry[order].next - 1, i++) {
4567 SLTG_TypeInfoHeader *pTIHeader;
4568 SLTG_TypeInfoTail *pTITail;
4569 SLTG_MemberHeader *pMemHeader;
4571 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4572 FIXME_(typelib)("Index strings don't match\n");
4573 heap_free(pOtherTypeInfoBlks);
4574 return NULL;
4577 pTIHeader = pBlk;
4578 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4579 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4580 heap_free(pOtherTypeInfoBlks);
4581 return NULL;
4583 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4584 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4585 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4587 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4588 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4589 (*ppTypeInfoImpl)->index = i;
4590 (*ppTypeInfoImpl)->Name = SLTG_ReadName(pNameTable, pOtherTypeInfoBlks[i].name_offs, pTypeLibImpl);
4591 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4592 (*ppTypeInfoImpl)->guid = TLB_append_guid(&pTypeLibImpl->guid_list, &pOtherTypeInfoBlks[i].uuid, 2);
4593 (*ppTypeInfoImpl)->typeattr.typekind = pTIHeader->typekind;
4594 (*ppTypeInfoImpl)->typeattr.wMajorVerNum = pTIHeader->major_version;
4595 (*ppTypeInfoImpl)->typeattr.wMinorVerNum = pTIHeader->minor_version;
4596 (*ppTypeInfoImpl)->typeattr.wTypeFlags =
4597 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4599 if((*ppTypeInfoImpl)->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
4600 (*ppTypeInfoImpl)->typeattr.typekind = TKIND_DISPATCH;
4602 if((pTIHeader->typeflags1 & 7) != 2)
4603 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4604 if(pTIHeader->typeflags3 != 2)
4605 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4607 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4608 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl)->Name)),
4609 typekind_desc[pTIHeader->typekind],
4610 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl)->guid)),
4611 (*ppTypeInfoImpl)->typeattr.wTypeFlags);
4613 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4615 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4617 (*ppTypeInfoImpl)->typeattr.cbAlignment = pTITail->cbAlignment;
4618 (*ppTypeInfoImpl)->typeattr.cbSizeInstance = pTITail->cbSizeInstance;
4619 (*ppTypeInfoImpl)->typeattr.cbSizeVft = pTITail->cbSizeVft;
4621 switch(pTIHeader->typekind) {
4622 case TKIND_ENUM:
4623 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4624 pTIHeader, pTITail);
4625 break;
4627 case TKIND_RECORD:
4628 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4629 pTIHeader, pTITail);
4630 break;
4632 case TKIND_INTERFACE:
4633 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4634 pTIHeader, pTITail);
4635 break;
4637 case TKIND_COCLASS:
4638 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4639 pTIHeader, pTITail);
4640 break;
4642 case TKIND_ALIAS:
4643 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4644 pTIHeader, pTITail);
4645 break;
4647 case TKIND_DISPATCH:
4648 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4649 pTIHeader, pTITail);
4650 break;
4652 case TKIND_MODULE:
4653 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4654 pTIHeader, pTITail);
4655 break;
4657 default:
4658 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4659 break;
4663 /* could get cFuncs, cVars and cImplTypes from here
4664 but we've already set those */
4665 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4666 X(06);
4667 X(16);
4668 X(18);
4669 X(1a);
4670 X(1e);
4671 X(24);
4672 X(26);
4673 X(2a);
4674 X(2c);
4675 X(2e);
4676 X(30);
4677 X(32);
4678 X(34);
4679 #undef X
4680 ++ppTypeInfoImpl;
4681 pBlk = (char*)pBlk + pBlkEntry[order].len;
4684 if(i != pTypeLibImpl->TypeInfoCount) {
4685 FIXME("Somehow processed %d TypeInfos\n", i);
4686 heap_free(pOtherTypeInfoBlks);
4687 return NULL;
4690 heap_free(pOtherTypeInfoBlks);
4691 return &pTypeLibImpl->ITypeLib2_iface;
4694 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4696 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4698 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4700 if(IsEqualIID(riid, &IID_IUnknown) ||
4701 IsEqualIID(riid,&IID_ITypeLib)||
4702 IsEqualIID(riid,&IID_ITypeLib2))
4704 *ppv = &This->ITypeLib2_iface;
4706 else if(IsEqualIID(riid, &IID_ICreateTypeLib) ||
4707 IsEqualIID(riid, &IID_ICreateTypeLib2))
4709 *ppv = &This->ICreateTypeLib2_iface;
4711 else
4713 *ppv = NULL;
4714 TRACE("-- Interface: E_NOINTERFACE\n");
4715 return E_NOINTERFACE;
4718 IUnknown_AddRef((IUnknown*)*ppv);
4719 return S_OK;
4722 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4724 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4725 ULONG ref = InterlockedIncrement(&This->ref);
4727 TRACE("(%p) ref=%u\n", This, ref);
4729 return ref;
4732 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4734 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4735 ULONG ref = InterlockedDecrement(&This->ref);
4737 TRACE("(%p) ref=%u\n",This, ref);
4739 if (!ref)
4741 TLBImpLib *pImpLib, *pImpLibNext;
4742 TLBRefType *ref_type, *ref_type_next;
4743 TLBString *tlbstr, *tlbstr_next;
4744 TLBGuid *tlbguid, *tlbguid_next;
4745 int i;
4747 /* remove cache entry */
4748 if(This->path)
4750 TRACE("removing from cache list\n");
4751 EnterCriticalSection(&cache_section);
4752 if(This->entry.next)
4753 list_remove(&This->entry);
4754 LeaveCriticalSection(&cache_section);
4755 heap_free(This->path);
4757 TRACE(" destroying ITypeLib(%p)\n",This);
4759 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->string_list, TLBString, entry) {
4760 list_remove(&tlbstr->entry);
4761 SysFreeString(tlbstr->str);
4762 heap_free(tlbstr);
4765 LIST_FOR_EACH_ENTRY_SAFE(tlbstr, tlbstr_next, &This->name_list, TLBString, entry) {
4766 list_remove(&tlbstr->entry);
4767 SysFreeString(tlbstr->str);
4768 heap_free(tlbstr);
4771 LIST_FOR_EACH_ENTRY_SAFE(tlbguid, tlbguid_next, &This->guid_list, TLBGuid, entry) {
4772 list_remove(&tlbguid->entry);
4773 heap_free(tlbguid);
4776 TLB_FreeCustData(&This->custdata_list);
4778 for (i = 0; i < This->ctTypeDesc; i++)
4779 if (This->pTypeDesc[i].vt == VT_CARRAY)
4780 heap_free(This->pTypeDesc[i].u.lpadesc);
4782 heap_free(This->pTypeDesc);
4784 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4786 if (pImpLib->pImpTypeLib)
4787 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4788 SysFreeString(pImpLib->name);
4790 list_remove(&pImpLib->entry);
4791 heap_free(pImpLib);
4794 LIST_FOR_EACH_ENTRY_SAFE(ref_type, ref_type_next, &This->ref_list, TLBRefType, entry)
4796 list_remove(&ref_type->entry);
4797 heap_free(ref_type);
4800 for (i = 0; i < This->TypeInfoCount; ++i){
4801 heap_free(This->typeinfos[i]->tdescAlias);
4802 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4804 heap_free(This->typeinfos);
4805 heap_free(This);
4806 return 0;
4809 return ref;
4812 /* ITypeLib::GetTypeInfoCount
4814 * Returns the number of type descriptions in the type library
4816 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4818 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4819 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4820 return This->TypeInfoCount;
4823 /* ITypeLib::GetTypeInfo
4825 * retrieves the specified type description in the library.
4827 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4828 ITypeLib2 *iface,
4829 UINT index,
4830 ITypeInfo **ppTInfo)
4832 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4834 TRACE("%p %u %p\n", This, index, ppTInfo);
4836 if(!ppTInfo)
4837 return E_INVALIDARG;
4839 if(index >= This->TypeInfoCount)
4840 return TYPE_E_ELEMENTNOTFOUND;
4842 *ppTInfo = (ITypeInfo *)&This->typeinfos[index]->ITypeInfo2_iface;
4843 ITypeInfo_AddRef(*ppTInfo);
4845 return S_OK;
4849 /* ITypeLibs::GetTypeInfoType
4851 * Retrieves the type of a type description.
4853 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4854 ITypeLib2 *iface,
4855 UINT index,
4856 TYPEKIND *pTKind)
4858 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4860 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4862 if(!pTKind)
4863 return E_INVALIDARG;
4865 if(index >= This->TypeInfoCount)
4866 return TYPE_E_ELEMENTNOTFOUND;
4868 *pTKind = This->typeinfos[index]->typeattr.typekind;
4870 return S_OK;
4873 /* ITypeLib::GetTypeInfoOfGuid
4875 * Retrieves the type description that corresponds to the specified GUID.
4878 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4879 ITypeLib2 *iface,
4880 REFGUID guid,
4881 ITypeInfo **ppTInfo)
4883 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4884 int i;
4886 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4888 for(i = 0; i < This->TypeInfoCount; ++i){
4889 if(IsEqualIID(TLB_get_guid_null(This->typeinfos[i]->guid), guid)){
4890 *ppTInfo = (ITypeInfo *)&This->typeinfos[i]->ITypeInfo2_iface;
4891 ITypeInfo_AddRef(*ppTInfo);
4892 return S_OK;
4896 return TYPE_E_ELEMENTNOTFOUND;
4899 /* ITypeLib::GetLibAttr
4901 * Retrieves the structure that contains the library's attributes.
4904 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4905 ITypeLib2 *iface,
4906 LPTLIBATTR *attr)
4908 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4910 TRACE("(%p, %p)\n", This, attr);
4912 if (!attr) return E_INVALIDARG;
4914 *attr = heap_alloc(sizeof(**attr));
4915 if (!*attr) return E_OUTOFMEMORY;
4917 (*attr)->guid = *TLB_get_guid_null(This->guid);
4918 (*attr)->lcid = This->set_lcid;
4919 (*attr)->syskind = This->syskind;
4920 (*attr)->wMajorVerNum = This->ver_major;
4921 (*attr)->wMinorVerNum = This->ver_minor;
4922 (*attr)->wLibFlags = This->libflags;
4924 return S_OK;
4927 /* ITypeLib::GetTypeComp
4929 * Enables a client compiler to bind to a library's types, variables,
4930 * constants, and global functions.
4933 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4934 ITypeLib2 *iface,
4935 ITypeComp **ppTComp)
4937 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4939 TRACE("(%p)->(%p)\n",This,ppTComp);
4940 *ppTComp = &This->ITypeComp_iface;
4941 ITypeComp_AddRef(*ppTComp);
4943 return S_OK;
4946 /* ITypeLib::GetDocumentation
4948 * Retrieves the library's documentation string, the complete Help file name
4949 * and path, and the context identifier for the library Help topic in the Help
4950 * file.
4952 * On a successful return all non-null BSTR pointers will have been set,
4953 * possibly to NULL.
4955 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4956 ITypeLib2 *iface,
4957 INT index,
4958 BSTR *pBstrName,
4959 BSTR *pBstrDocString,
4960 DWORD *pdwHelpContext,
4961 BSTR *pBstrHelpFile)
4963 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4964 HRESULT result = E_INVALIDARG;
4965 ITypeInfo *pTInfo;
4967 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4968 This, index,
4969 pBstrName, pBstrDocString,
4970 pdwHelpContext, pBstrHelpFile);
4972 if(index<0)
4974 /* documentation for the typelib */
4975 if(pBstrName)
4977 if (This->Name)
4979 if(!(*pBstrName = SysAllocString(TLB_get_bstr(This->Name))))
4980 goto memerr1;
4982 else
4983 *pBstrName = NULL;
4985 if(pBstrDocString)
4987 if (This->DocString)
4989 if(!(*pBstrDocString = SysAllocString(TLB_get_bstr(This->DocString))))
4990 goto memerr2;
4992 else
4993 *pBstrDocString = NULL;
4995 if(pdwHelpContext)
4997 *pdwHelpContext = This->dwHelpContext;
4999 if(pBstrHelpFile)
5001 if (This->HelpFile)
5003 if(!(*pBstrHelpFile = SysAllocString(TLB_get_bstr(This->HelpFile))))
5004 goto memerr3;
5006 else
5007 *pBstrHelpFile = NULL;
5010 result = S_OK;
5012 else
5014 /* for a typeinfo */
5015 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
5017 if(SUCCEEDED(result))
5019 result = ITypeInfo_GetDocumentation(pTInfo,
5020 MEMBERID_NIL,
5021 pBstrName,
5022 pBstrDocString,
5023 pdwHelpContext, pBstrHelpFile);
5025 ITypeInfo_Release(pTInfo);
5028 return result;
5029 memerr3:
5030 if (pBstrDocString) SysFreeString (*pBstrDocString);
5031 memerr2:
5032 if (pBstrName) SysFreeString (*pBstrName);
5033 memerr1:
5034 return STG_E_INSUFFICIENTMEMORY;
5037 /* ITypeLib::IsName
5039 * Indicates whether a passed-in string contains the name of a type or member
5040 * described in the library.
5043 static HRESULT WINAPI ITypeLib2_fnIsName(
5044 ITypeLib2 *iface,
5045 LPOLESTR szNameBuf,
5046 ULONG lHashVal,
5047 BOOL *pfName)
5049 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5050 int tic;
5051 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
5053 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
5054 pfName);
5056 *pfName=TRUE;
5057 for(tic = 0; tic < This->TypeInfoCount; ++tic){
5058 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5059 if(!TLB_str_memcmp(szNameBuf, pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5060 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5061 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
5062 int pc;
5063 if(!TLB_str_memcmp(szNameBuf, pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5064 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++){
5065 if(!TLB_str_memcmp(szNameBuf, pFInfo->pParamDesc[pc].Name, nNameBufLen))
5066 goto ITypeLib2_fnIsName_exit;
5069 for(vrc = 0; vrc < pTInfo->typeattr.cVars; ++vrc){
5070 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
5071 if(!TLB_str_memcmp(szNameBuf, pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
5075 *pfName=FALSE;
5077 ITypeLib2_fnIsName_exit:
5078 TRACE("(%p)slow! search for %s: %sfound!\n", This,
5079 debugstr_w(szNameBuf), *pfName ? "" : "NOT ");
5081 return S_OK;
5084 /* ITypeLib::FindName
5086 * Finds occurrences of a type description in a type library. This may be used
5087 * to quickly verify that a name exists in a type library.
5090 static HRESULT WINAPI ITypeLib2_fnFindName(
5091 ITypeLib2 *iface,
5092 LPOLESTR name,
5093 ULONG hash,
5094 ITypeInfo **ppTInfo,
5095 MEMBERID *memid,
5096 UINT16 *found)
5098 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5099 int tic;
5100 UINT count = 0;
5101 UINT len;
5103 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
5105 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
5106 return E_INVALIDARG;
5108 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
5109 for(tic = 0; count < *found && tic < This->TypeInfoCount; ++tic) {
5110 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
5111 TLBVarDesc *var;
5112 UINT fdc;
5114 if(!TLB_str_memcmp(name, pTInfo->Name, len)) {
5115 memid[count] = MEMBERID_NIL;
5116 goto ITypeLib2_fnFindName_exit;
5119 for(fdc = 0; fdc < pTInfo->typeattr.cFuncs; ++fdc) {
5120 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
5122 if(!TLB_str_memcmp(name, func->Name, len)) {
5123 memid[count] = func->funcdesc.memid;
5124 goto ITypeLib2_fnFindName_exit;
5128 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->typeattr.cVars, name);
5129 if (var) {
5130 memid[count] = var->vardesc.memid;
5131 goto ITypeLib2_fnFindName_exit;
5134 continue;
5135 ITypeLib2_fnFindName_exit:
5136 ITypeInfo2_AddRef(&pTInfo->ITypeInfo2_iface);
5137 ppTInfo[count] = (ITypeInfo *)&pTInfo->ITypeInfo2_iface;
5138 count++;
5140 TRACE("found %d typeinfos\n", count);
5142 *found = count;
5144 return S_OK;
5147 /* ITypeLib::ReleaseTLibAttr
5149 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5152 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
5153 ITypeLib2 *iface,
5154 TLIBATTR *pTLibAttr)
5156 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5157 TRACE("(%p)->(%p)\n", This, pTLibAttr);
5158 heap_free(pTLibAttr);
5161 /* ITypeLib2::GetCustData
5163 * gets the custom data
5165 static HRESULT WINAPI ITypeLib2_fnGetCustData(
5166 ITypeLib2 * iface,
5167 REFGUID guid,
5168 VARIANT *pVarVal)
5170 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5171 TLBCustData *pCData;
5173 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
5175 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
5176 if(!pCData)
5177 return TYPE_E_ELEMENTNOTFOUND;
5179 VariantInit(pVarVal);
5180 VariantCopy(pVarVal, &pCData->data);
5182 return S_OK;
5185 /* ITypeLib2::GetLibStatistics
5187 * Returns statistics about a type library that are required for efficient
5188 * sizing of hash tables.
5191 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
5192 ITypeLib2 * iface,
5193 ULONG *pcUniqueNames,
5194 ULONG *pcchUniqueNames)
5196 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5198 FIXME("(%p): stub!\n", This);
5200 if(pcUniqueNames) *pcUniqueNames=1;
5201 if(pcchUniqueNames) *pcchUniqueNames=1;
5202 return S_OK;
5205 /* ITypeLib2::GetDocumentation2
5207 * Retrieves the library's documentation string, the complete Help file name
5208 * and path, the localization context to use, and the context ID for the
5209 * library Help topic in the Help file.
5212 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
5213 ITypeLib2 * iface,
5214 INT index,
5215 LCID lcid,
5216 BSTR *pbstrHelpString,
5217 DWORD *pdwHelpStringContext,
5218 BSTR *pbstrHelpStringDll)
5220 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5221 HRESULT result;
5222 ITypeInfo *pTInfo;
5224 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
5226 /* the help string should be obtained from the helpstringdll,
5227 * using the _DLLGetDocumentation function, based on the supplied
5228 * lcid. Nice to do sometime...
5230 if(index<0)
5232 /* documentation for the typelib */
5233 if(pbstrHelpString)
5234 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->DocString));
5235 if(pdwHelpStringContext)
5236 *pdwHelpStringContext=This->dwHelpContext;
5237 if(pbstrHelpStringDll)
5238 *pbstrHelpStringDll=SysAllocString(TLB_get_bstr(This->HelpStringDll));
5240 result = S_OK;
5242 else
5244 /* for a typeinfo */
5245 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
5247 if(SUCCEEDED(result))
5249 ITypeInfo2 * pTInfo2;
5250 result = ITypeInfo_QueryInterface(pTInfo,
5251 &IID_ITypeInfo2,
5252 (LPVOID*) &pTInfo2);
5254 if(SUCCEEDED(result))
5256 result = ITypeInfo2_GetDocumentation2(pTInfo2,
5257 MEMBERID_NIL,
5258 lcid,
5259 pbstrHelpString,
5260 pdwHelpStringContext,
5261 pbstrHelpStringDll);
5263 ITypeInfo2_Release(pTInfo2);
5266 ITypeInfo_Release(pTInfo);
5269 return result;
5272 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
5274 TLBCustData *pCData;
5275 unsigned int ct;
5276 CUSTDATAITEM *cdi;
5278 ct = list_count(custdata_list);
5280 pCustData->prgCustData = CoTaskMemAlloc(ct * sizeof(CUSTDATAITEM));
5281 if(!pCustData->prgCustData)
5282 return E_OUTOFMEMORY;
5284 pCustData->cCustData = ct;
5286 cdi = pCustData->prgCustData;
5287 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
5288 cdi->guid = *TLB_get_guid_null(pCData->guid);
5289 VariantCopy(&cdi->varValue, &pCData->data);
5290 ++cdi;
5293 return S_OK;
5297 /* ITypeLib2::GetAllCustData
5299 * Gets all custom data items for the library.
5302 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
5303 ITypeLib2 * iface,
5304 CUSTDATA *pCustData)
5306 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
5307 TRACE("(%p)->(%p)\n", This, pCustData);
5308 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
5311 static const ITypeLib2Vtbl tlbvt = {
5312 ITypeLib2_fnQueryInterface,
5313 ITypeLib2_fnAddRef,
5314 ITypeLib2_fnRelease,
5315 ITypeLib2_fnGetTypeInfoCount,
5316 ITypeLib2_fnGetTypeInfo,
5317 ITypeLib2_fnGetTypeInfoType,
5318 ITypeLib2_fnGetTypeInfoOfGuid,
5319 ITypeLib2_fnGetLibAttr,
5320 ITypeLib2_fnGetTypeComp,
5321 ITypeLib2_fnGetDocumentation,
5322 ITypeLib2_fnIsName,
5323 ITypeLib2_fnFindName,
5324 ITypeLib2_fnReleaseTLibAttr,
5326 ITypeLib2_fnGetCustData,
5327 ITypeLib2_fnGetLibStatistics,
5328 ITypeLib2_fnGetDocumentation2,
5329 ITypeLib2_fnGetAllCustData
5333 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5335 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5337 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
5340 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
5342 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5344 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
5347 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
5349 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5351 return ITypeLib2_Release(&This->ITypeLib2_iface);
5354 static HRESULT WINAPI ITypeLibComp_fnBind(
5355 ITypeComp * iface,
5356 OLECHAR * szName,
5357 ULONG lHash,
5358 WORD wFlags,
5359 ITypeInfo ** ppTInfo,
5360 DESCKIND * pDescKind,
5361 BINDPTR * pBindPtr)
5363 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5364 BOOL typemismatch = FALSE;
5365 int i;
5367 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5369 *pDescKind = DESCKIND_NONE;
5370 pBindPtr->lptcomp = NULL;
5371 *ppTInfo = NULL;
5373 for(i = 0; i < This->TypeInfoCount; ++i){
5374 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5375 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo->Name)));
5377 /* FIXME: check wFlags here? */
5378 /* FIXME: we should use a hash table to look this info up using lHash
5379 * instead of an O(n) search */
5380 if ((pTypeInfo->typeattr.typekind == TKIND_ENUM) ||
5381 (pTypeInfo->typeattr.typekind == TKIND_MODULE))
5383 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name->str, szName))
5385 *pDescKind = DESCKIND_TYPECOMP;
5386 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
5387 ITypeComp_AddRef(pBindPtr->lptcomp);
5388 TRACE("module or enum: %s\n", debugstr_w(szName));
5389 return S_OK;
5393 if ((pTypeInfo->typeattr.typekind == TKIND_MODULE) ||
5394 (pTypeInfo->typeattr.typekind == TKIND_ENUM))
5396 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5397 HRESULT hr;
5399 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5400 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
5402 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
5403 return S_OK;
5405 else if (hr == TYPE_E_TYPEMISMATCH)
5406 typemismatch = TRUE;
5409 if ((pTypeInfo->typeattr.typekind == TKIND_COCLASS) &&
5410 (pTypeInfo->typeattr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
5412 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
5413 HRESULT hr;
5414 ITypeInfo *subtypeinfo;
5415 BINDPTR subbindptr;
5416 DESCKIND subdesckind;
5418 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
5419 &subtypeinfo, &subdesckind, &subbindptr);
5420 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
5422 TYPEDESC tdesc_appobject;
5423 const VARDESC vardesc_appobject =
5425 -2, /* memid */
5426 NULL, /* lpstrSchema */
5428 0 /* oInst */
5431 /* ELEMDESC */
5433 /* TYPEDESC */
5435 &tdesc_appobject
5437 VT_PTR
5440 0, /* wVarFlags */
5441 VAR_STATIC /* varkind */
5444 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
5445 tdesc_appobject.vt = VT_USERDEFINED;
5447 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
5449 /* cleanup things filled in by Bind call so we can put our
5450 * application object data in there instead */
5451 switch (subdesckind)
5453 case DESCKIND_FUNCDESC:
5454 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
5455 break;
5456 case DESCKIND_VARDESC:
5457 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
5458 break;
5459 default:
5460 break;
5462 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
5464 if (pTypeInfo->hreftype == -1)
5465 FIXME("no hreftype for interface %p\n", pTypeInfo);
5467 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
5468 if (FAILED(hr))
5469 return hr;
5471 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5472 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5473 ITypeInfo_AddRef(*ppTInfo);
5474 return S_OK;
5476 else if (hr == TYPE_E_TYPEMISMATCH)
5477 typemismatch = TRUE;
5481 if (typemismatch)
5483 TRACE("type mismatch %s\n", debugstr_w(szName));
5484 return TYPE_E_TYPEMISMATCH;
5486 else
5488 TRACE("name not found %s\n", debugstr_w(szName));
5489 return S_OK;
5493 static HRESULT WINAPI ITypeLibComp_fnBindType(
5494 ITypeComp * iface,
5495 OLECHAR * szName,
5496 ULONG lHash,
5497 ITypeInfo ** ppTInfo,
5498 ITypeComp ** ppTComp)
5500 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5501 ITypeInfoImpl *info;
5503 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5505 if(!szName || !ppTInfo || !ppTComp)
5506 return E_INVALIDARG;
5508 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, szName);
5509 if(!info){
5510 *ppTInfo = NULL;
5511 *ppTComp = NULL;
5512 return S_OK;
5515 *ppTInfo = (ITypeInfo *)&info->ITypeInfo2_iface;
5516 ITypeInfo_AddRef(*ppTInfo);
5517 *ppTComp = &info->ITypeComp_iface;
5518 ITypeComp_AddRef(*ppTComp);
5520 return S_OK;
5523 static const ITypeCompVtbl tlbtcvt =
5526 ITypeLibComp_fnQueryInterface,
5527 ITypeLibComp_fnAddRef,
5528 ITypeLibComp_fnRelease,
5530 ITypeLibComp_fnBind,
5531 ITypeLibComp_fnBindType
5534 /*================== ITypeInfo(2) Methods ===================================*/
5535 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5537 ITypeInfoImpl *pTypeInfoImpl;
5539 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5540 if (pTypeInfoImpl)
5542 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5543 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5544 pTypeInfoImpl->ICreateTypeInfo2_iface.lpVtbl = &CreateTypeInfo2Vtbl;
5545 pTypeInfoImpl->ref = 0;
5546 pTypeInfoImpl->hreftype = -1;
5547 pTypeInfoImpl->typeattr.memidConstructor = MEMBERID_NIL;
5548 pTypeInfoImpl->typeattr.memidDestructor = MEMBERID_NIL;
5549 pTypeInfoImpl->pcustdata_list = &pTypeInfoImpl->custdata_list;
5550 list_init(pTypeInfoImpl->pcustdata_list);
5552 TRACE("(%p)\n", pTypeInfoImpl);
5553 return pTypeInfoImpl;
5556 /* ITypeInfo::QueryInterface
5558 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5559 ITypeInfo2 *iface,
5560 REFIID riid,
5561 VOID **ppvObject)
5563 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5565 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5567 *ppvObject=NULL;
5568 if(IsEqualIID(riid, &IID_IUnknown) ||
5569 IsEqualIID(riid,&IID_ITypeInfo)||
5570 IsEqualIID(riid,&IID_ITypeInfo2))
5571 *ppvObject = &This->ITypeInfo2_iface;
5572 else if(IsEqualIID(riid, &IID_ICreateTypeInfo) ||
5573 IsEqualIID(riid, &IID_ICreateTypeInfo2))
5574 *ppvObject = &This->ICreateTypeInfo2_iface;
5575 else if(IsEqualIID(riid, &IID_ITypeComp))
5576 *ppvObject = &This->ITypeComp_iface;
5578 if(*ppvObject){
5579 IUnknown_AddRef((IUnknown*)*ppvObject);
5580 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5581 return S_OK;
5583 TRACE("-- Interface: E_NOINTERFACE\n");
5584 return E_NOINTERFACE;
5587 /* ITypeInfo::AddRef
5589 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5591 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5592 ULONG ref = InterlockedIncrement(&This->ref);
5594 TRACE("(%p)->ref is %u\n",This, ref);
5596 if (ref == 1 /* incremented from 0 */)
5597 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5599 return ref;
5602 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5604 UINT i;
5606 TRACE("destroying ITypeInfo(%p)\n",This);
5608 for (i = 0; i < This->typeattr.cFuncs; ++i)
5610 int j;
5611 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5612 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5614 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5615 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5616 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5617 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5619 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5620 heap_free(pFInfo->pParamDesc);
5621 TLB_FreeCustData(&pFInfo->custdata_list);
5623 heap_free(This->funcdescs);
5625 for(i = 0; i < This->typeattr.cVars; ++i)
5627 TLBVarDesc *pVInfo = &This->vardescs[i];
5628 if (pVInfo->vardesc_create) {
5629 TLB_FreeVarDesc(pVInfo->vardesc_create);
5630 } else if (pVInfo->vardesc.varkind == VAR_CONST) {
5631 VariantClear(pVInfo->vardesc.u.lpvarValue);
5632 heap_free(pVInfo->vardesc.u.lpvarValue);
5634 TLB_FreeCustData(&pVInfo->custdata_list);
5636 heap_free(This->vardescs);
5638 if(This->impltypes){
5639 for (i = 0; i < This->typeattr.cImplTypes; ++i){
5640 TLBImplType *pImpl = &This->impltypes[i];
5641 TLB_FreeCustData(&pImpl->custdata_list);
5643 heap_free(This->impltypes);
5646 TLB_FreeCustData(&This->custdata_list);
5648 heap_free(This);
5651 /* ITypeInfo::Release
5653 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5655 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5656 ULONG ref = InterlockedDecrement(&This->ref);
5658 TRACE("(%p)->(%u)\n",This, ref);
5660 if (!ref)
5662 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5663 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5664 if (not_attached_to_typelib)
5665 heap_free(This);
5666 /* otherwise This will be freed when typelib is freed */
5669 return ref;
5672 /* ITypeInfo::GetTypeAttr
5674 * Retrieves a TYPEATTR structure that contains the attributes of the type
5675 * description.
5678 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5679 LPTYPEATTR *ppTypeAttr)
5681 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5682 SIZE_T size;
5684 TRACE("(%p)\n",This);
5686 size = sizeof(**ppTypeAttr);
5687 if (This->typeattr.typekind == TKIND_ALIAS && This->tdescAlias)
5688 size += TLB_SizeTypeDesc(This->tdescAlias, FALSE);
5690 *ppTypeAttr = heap_alloc(size);
5691 if (!*ppTypeAttr)
5692 return E_OUTOFMEMORY;
5694 **ppTypeAttr = This->typeattr;
5695 (*ppTypeAttr)->guid = *TLB_get_guid_null(This->guid);
5697 if (This->tdescAlias)
5698 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias, This->tdescAlias, *ppTypeAttr + 1);
5700 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5701 /* This should include all the inherited funcs */
5702 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / This->pTypeLib->ptr_size;
5703 /* This is always the size of IDispatch's vtbl */
5704 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5705 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5707 return S_OK;
5710 /* ITypeInfo::GetTypeComp
5712 * Retrieves the ITypeComp interface for the type description, which enables a
5713 * client compiler to bind to the type description's members.
5716 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5717 ITypeComp * *ppTComp)
5719 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5721 TRACE("(%p)->(%p)\n", This, ppTComp);
5723 *ppTComp = &This->ITypeComp_iface;
5724 ITypeComp_AddRef(*ppTComp);
5725 return S_OK;
5728 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5730 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5731 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5732 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5733 return size;
5736 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5738 *dest = *src;
5739 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5740 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5742 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5743 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5744 *buffer += sizeof(PARAMDESCEX);
5745 *pparamdescex_dest = *pparamdescex_src;
5746 pparamdescex_dest->cBytes = sizeof(PARAMDESCEX);
5747 VariantInit(&pparamdescex_dest->varDefaultValue);
5748 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5749 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5751 else
5752 dest->u.paramdesc.pparamdescex = NULL;
5753 return S_OK;
5756 static HRESULT TLB_SanitizeBSTR(BSTR str)
5758 UINT len = SysStringLen(str), i;
5759 for (i = 0; i < len; ++i)
5760 if (str[i] > 0x7f)
5761 str[i] = '?';
5762 return S_OK;
5765 static HRESULT TLB_SanitizeVariant(VARIANT *var)
5767 if (V_VT(var) == VT_INT)
5768 return VariantChangeType(var, var, 0, VT_I4);
5769 else if (V_VT(var) == VT_UINT)
5770 return VariantChangeType(var, var, 0, VT_UI4);
5771 else if (V_VT(var) == VT_BSTR)
5772 return TLB_SanitizeBSTR(V_BSTR(var));
5774 return S_OK;
5777 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5779 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5780 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5783 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5785 FUNCDESC *dest;
5786 char *buffer;
5787 SIZE_T size = sizeof(*src);
5788 SHORT i;
5789 HRESULT hr;
5791 size += sizeof(*src->lprgscode) * src->cScodes;
5792 size += TLB_SizeElemDesc(&src->elemdescFunc);
5793 for (i = 0; i < src->cParams; i++)
5795 size += sizeof(ELEMDESC);
5796 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5799 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5800 if (!dest) return E_OUTOFMEMORY;
5802 *dest = *src;
5803 if (dispinterface) /* overwrite funckind */
5804 dest->funckind = FUNC_DISPATCH;
5805 buffer = (char *)(dest + 1);
5807 dest->oVft = dest->oVft & 0xFFFC;
5809 if (dest->cScodes) {
5810 dest->lprgscode = (SCODE *)buffer;
5811 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5812 buffer += sizeof(*src->lprgscode) * src->cScodes;
5813 } else
5814 dest->lprgscode = NULL;
5816 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5817 if (FAILED(hr))
5819 SysFreeString((BSTR)dest);
5820 return hr;
5823 if (dest->cParams) {
5824 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5825 buffer += sizeof(ELEMDESC) * src->cParams;
5826 for (i = 0; i < src->cParams; i++)
5828 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5829 if (FAILED(hr))
5830 break;
5832 if (FAILED(hr))
5834 /* undo the above actions */
5835 for (i = i - 1; i >= 0; i--)
5836 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5837 TLB_FreeElemDesc(&dest->elemdescFunc);
5838 SysFreeString((BSTR)dest);
5839 return hr;
5841 } else
5842 dest->lprgelemdescParam = NULL;
5844 /* special treatment for dispinterfaces: this makes functions appear
5845 * to return their [retval] value when it is really returning an
5846 * HRESULT */
5847 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5849 if (dest->cParams &&
5850 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5852 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5853 if (elemdesc->tdesc.vt != VT_PTR)
5855 ERR("elemdesc should have started with VT_PTR instead of:\n");
5856 if (ERR_ON(ole))
5857 dump_ELEMDESC(elemdesc);
5858 return E_UNEXPECTED;
5861 /* copy last parameter to the return value. we are using a flat
5862 * buffer so there is no danger of leaking memory in
5863 * elemdescFunc */
5864 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5866 /* remove the last parameter */
5867 dest->cParams--;
5869 else
5870 /* otherwise this function is made to appear to have no return
5871 * value */
5872 dest->elemdescFunc.tdesc.vt = VT_VOID;
5876 *dest_ptr = dest;
5877 return S_OK;
5880 static void TLB_FreeVarDesc(VARDESC *var_desc)
5882 TLB_FreeElemDesc(&var_desc->elemdescVar);
5883 if (var_desc->varkind == VAR_CONST)
5884 VariantClear(var_desc->u.lpvarValue);
5885 SysFreeString((BSTR)var_desc);
5888 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5890 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5892 if (index >= This->typeattr.cFuncs)
5893 return TYPE_E_ELEMENTNOTFOUND;
5895 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5896 return S_OK;
5899 /* internal function to make the inherited interfaces' methods appear
5900 * part of the interface */
5901 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5902 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5904 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5905 HRESULT hr;
5906 UINT implemented_funcs = 0;
5908 if (funcs)
5909 *funcs = 0;
5910 else
5911 *hrefoffset = DISPATCH_HREF_OFFSET;
5913 if(This->impltypes)
5915 ITypeInfo *pSubTypeInfo;
5916 UINT sub_funcs;
5918 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5919 if (FAILED(hr))
5920 return hr;
5922 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5923 index,
5924 ppFuncDesc,
5925 &sub_funcs, hrefoffset);
5926 implemented_funcs += sub_funcs;
5927 ITypeInfo_Release(pSubTypeInfo);
5928 if (SUCCEEDED(hr))
5929 return hr;
5930 *hrefoffset += DISPATCH_HREF_OFFSET;
5933 if (funcs)
5934 *funcs = implemented_funcs + This->typeattr.cFuncs;
5935 else
5936 *hrefoffset = 0;
5938 if (index < implemented_funcs)
5939 return E_INVALIDARG;
5940 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5941 ppFuncDesc);
5944 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5946 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5947 while (TRUE)
5949 switch (pTypeDesc->vt)
5951 case VT_USERDEFINED:
5952 pTypeDesc->u.hreftype += hrefoffset;
5953 return;
5954 case VT_PTR:
5955 case VT_SAFEARRAY:
5956 pTypeDesc = pTypeDesc->u.lptdesc;
5957 break;
5958 case VT_CARRAY:
5959 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5960 break;
5961 default:
5962 return;
5967 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5969 SHORT i;
5970 for (i = 0; i < pFuncDesc->cParams; i++)
5971 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5972 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5975 /* ITypeInfo::GetFuncDesc
5977 * Retrieves the FUNCDESC structure that contains information about a
5978 * specified function.
5981 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5982 LPFUNCDESC *ppFuncDesc)
5984 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5985 const FUNCDESC *internal_funcdesc;
5986 HRESULT hr;
5987 UINT hrefoffset = 0;
5989 TRACE("(%p) index %d\n", This, index);
5991 if (!ppFuncDesc)
5992 return E_INVALIDARG;
5994 if (This->needs_layout)
5995 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
5997 if (This->typeattr.typekind == TKIND_DISPATCH)
5998 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5999 &internal_funcdesc, NULL,
6000 &hrefoffset);
6001 else
6002 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
6003 &internal_funcdesc);
6004 if (FAILED(hr))
6006 WARN("description for function %d not found\n", index);
6007 return hr;
6010 hr = TLB_AllocAndInitFuncDesc(
6011 internal_funcdesc,
6012 ppFuncDesc,
6013 This->typeattr.typekind == TKIND_DISPATCH);
6015 if ((This->typeattr.typekind == TKIND_DISPATCH) && hrefoffset)
6016 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
6018 TRACE("-- 0x%08x\n", hr);
6019 return hr;
6022 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
6024 VARDESC *dest;
6025 char *buffer;
6026 SIZE_T size = sizeof(*src);
6027 HRESULT hr;
6029 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
6030 if (src->varkind == VAR_CONST)
6031 size += sizeof(VARIANT);
6032 size += TLB_SizeElemDesc(&src->elemdescVar);
6034 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
6035 if (!dest) return E_OUTOFMEMORY;
6037 *dest = *src;
6038 buffer = (char *)(dest + 1);
6039 if (src->lpstrSchema)
6041 int len;
6042 dest->lpstrSchema = (LPOLESTR)buffer;
6043 len = strlenW(src->lpstrSchema);
6044 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
6045 buffer += (len + 1) * sizeof(WCHAR);
6048 if (src->varkind == VAR_CONST)
6050 HRESULT hr;
6052 dest->u.lpvarValue = (VARIANT *)buffer;
6053 *dest->u.lpvarValue = *src->u.lpvarValue;
6054 buffer += sizeof(VARIANT);
6055 VariantInit(dest->u.lpvarValue);
6056 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
6057 if (FAILED(hr))
6059 SysFreeString((BSTR)dest);
6060 return hr;
6063 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
6064 if (FAILED(hr))
6066 if (src->varkind == VAR_CONST)
6067 VariantClear(dest->u.lpvarValue);
6068 SysFreeString((BSTR)dest);
6069 return hr;
6071 *dest_ptr = dest;
6072 return S_OK;
6075 /* ITypeInfo::GetVarDesc
6077 * Retrieves a VARDESC structure that describes the specified variable.
6080 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
6081 LPVARDESC *ppVarDesc)
6083 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6084 const TLBVarDesc *pVDesc = &This->vardescs[index];
6086 TRACE("(%p) index %d\n", This, index);
6088 if(index >= This->typeattr.cVars)
6089 return TYPE_E_ELEMENTNOTFOUND;
6091 if (This->needs_layout)
6092 ICreateTypeInfo2_LayOut(&This->ICreateTypeInfo2_iface);
6094 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
6097 /* ITypeInfo_GetNames
6099 * Retrieves the variable with the specified member ID (or the name of the
6100 * property or method and its parameters) that correspond to the specified
6101 * function ID.
6103 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
6104 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
6106 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6107 const TLBFuncDesc *pFDesc;
6108 const TLBVarDesc *pVDesc;
6109 int i;
6110 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
6112 if(!rgBstrNames)
6113 return E_INVALIDARG;
6115 *pcNames = 0;
6117 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
6118 if(pFDesc)
6120 if(!cMaxNames || !pFDesc->Name)
6121 return S_OK;
6123 *rgBstrNames = SysAllocString(TLB_get_bstr(pFDesc->Name));
6124 ++(*pcNames);
6126 for(i = 0; i < pFDesc->funcdesc.cParams; ++i){
6127 if(*pcNames >= cMaxNames || !pFDesc->pParamDesc[i].Name)
6128 return S_OK;
6129 rgBstrNames[*pcNames] = SysAllocString(TLB_get_bstr(pFDesc->pParamDesc[i].Name));
6130 ++(*pcNames);
6132 return S_OK;
6135 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
6136 if(pVDesc)
6138 *rgBstrNames=SysAllocString(TLB_get_bstr(pVDesc->Name));
6139 *pcNames=1;
6141 else
6143 if(This->impltypes &&
6144 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
6145 /* recursive search */
6146 ITypeInfo *pTInfo;
6147 HRESULT result;
6148 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6149 if(SUCCEEDED(result))
6151 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
6152 ITypeInfo_Release(pTInfo);
6153 return result;
6155 WARN("Could not search inherited interface!\n");
6157 else
6159 WARN("no names found\n");
6161 *pcNames=0;
6162 return TYPE_E_ELEMENTNOTFOUND;
6164 return S_OK;
6168 /* ITypeInfo::GetRefTypeOfImplType
6170 * If a type description describes a COM class, it retrieves the type
6171 * description of the implemented interface types. For an interface,
6172 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6173 * if any exist.
6176 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
6177 ITypeInfo2 *iface,
6178 UINT index,
6179 HREFTYPE *pRefType)
6181 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6182 HRESULT hr = S_OK;
6184 TRACE("(%p) index %d\n", This, index);
6185 if (TRACE_ON(ole)) dump_TypeInfo(This);
6187 if(index==(UINT)-1)
6189 /* only valid on dual interfaces;
6190 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6193 if (This->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
6195 *pRefType = -2;
6197 else
6199 hr = TYPE_E_ELEMENTNOTFOUND;
6202 else if(index == 0 && This->typeattr.typekind == TKIND_DISPATCH)
6204 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6205 *pRefType = This->pTypeLib->dispatch_href;
6207 else
6209 if(index >= This->typeattr.cImplTypes)
6210 hr = TYPE_E_ELEMENTNOTFOUND;
6211 else{
6212 *pRefType = This->impltypes[index].hRef;
6213 if (This->typeattr.typekind == TKIND_INTERFACE)
6214 *pRefType |= 0x2;
6218 if(TRACE_ON(ole))
6220 if(SUCCEEDED(hr))
6221 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
6222 else
6223 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
6226 return hr;
6229 /* ITypeInfo::GetImplTypeFlags
6231 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6232 * or base interface in a type description.
6234 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
6235 UINT index, INT *pImplTypeFlags)
6237 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6239 TRACE("(%p) index %d\n", This, index);
6241 if(!pImplTypeFlags)
6242 return E_INVALIDARG;
6244 if(This->typeattr.typekind == TKIND_DISPATCH && index == 0){
6245 *pImplTypeFlags = 0;
6246 return S_OK;
6249 if(index >= This->typeattr.cImplTypes)
6250 return TYPE_E_ELEMENTNOTFOUND;
6252 *pImplTypeFlags = This->impltypes[index].implflags;
6254 return S_OK;
6257 /* GetIDsOfNames
6258 * Maps between member names and member IDs, and parameter names and
6259 * parameter IDs.
6261 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
6262 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
6264 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6265 const TLBVarDesc *pVDesc;
6266 HRESULT ret=S_OK;
6267 UINT i, fdc;
6269 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
6270 cNames);
6272 /* init out parameters in case of failure */
6273 for (i = 0; i < cNames; i++)
6274 pMemId[i] = MEMBERID_NIL;
6276 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc) {
6277 int j;
6278 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
6279 if(!lstrcmpiW(*rgszNames, TLB_get_bstr(pFDesc->Name))) {
6280 if(cNames) *pMemId=pFDesc->funcdesc.memid;
6281 for(i=1; i < cNames; i++){
6282 for(j=0; j<pFDesc->funcdesc.cParams; j++)
6283 if(!lstrcmpiW(rgszNames[i],TLB_get_bstr(pFDesc->pParamDesc[j].Name)))
6284 break;
6285 if( j<pFDesc->funcdesc.cParams)
6286 pMemId[i]=j;
6287 else
6288 ret=DISP_E_UNKNOWNNAME;
6290 TRACE("-- 0x%08x\n", ret);
6291 return ret;
6294 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, *rgszNames);
6295 if(pVDesc){
6296 if(cNames)
6297 *pMemId = pVDesc->vardesc.memid;
6298 return ret;
6300 /* not found, see if it can be found in an inherited interface */
6301 if(This->impltypes) {
6302 /* recursive search */
6303 ITypeInfo *pTInfo;
6304 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6305 if(SUCCEEDED(ret)){
6306 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
6307 ITypeInfo_Release(pTInfo);
6308 return ret;
6310 WARN("Could not search inherited interface!\n");
6311 } else
6312 WARN("no names found\n");
6313 return DISP_E_UNKNOWNNAME;
6317 #ifdef __i386__
6319 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6320 extern double call_double_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
6321 __ASM_GLOBAL_FUNC( call_method,
6322 "pushl %ebp\n\t"
6323 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6324 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6325 "movl %esp,%ebp\n\t"
6326 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6327 "pushl %esi\n\t"
6328 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6329 "pushl %edi\n\t"
6330 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6331 "movl 12(%ebp),%edx\n\t"
6332 "movl %esp,%edi\n\t"
6333 "shll $2,%edx\n\t"
6334 "jz 1f\n\t"
6335 "subl %edx,%edi\n\t"
6336 "andl $~15,%edi\n\t"
6337 "movl %edi,%esp\n\t"
6338 "movl 12(%ebp),%ecx\n\t"
6339 "movl 16(%ebp),%esi\n\t"
6340 "cld\n\t"
6341 "rep; movsl\n"
6342 "1:\tcall *8(%ebp)\n\t"
6343 "subl %esp,%edi\n\t"
6344 "movl 20(%ebp),%ecx\n\t"
6345 "movl %edi,(%ecx)\n\t"
6346 "leal -8(%ebp),%esp\n\t"
6347 "popl %edi\n\t"
6348 __ASM_CFI(".cfi_same_value %edi\n\t")
6349 "popl %esi\n\t"
6350 __ASM_CFI(".cfi_same_value %esi\n\t")
6351 "popl %ebp\n\t"
6352 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6353 __ASM_CFI(".cfi_same_value %ebp\n\t")
6354 "ret" )
6355 __ASM_GLOBAL_FUNC( call_double_method,
6356 "jmp " __ASM_NAME("call_method") )
6358 #elif defined(__x86_64__)
6360 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
6361 extern double CDECL call_double_method( void *func, int nb_args, const DWORD_PTR *args );
6362 __ASM_GLOBAL_FUNC( call_method,
6363 "pushq %rbp\n\t"
6364 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6365 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6366 "movq %rsp,%rbp\n\t"
6367 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6368 "pushq %rsi\n\t"
6369 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6370 "pushq %rdi\n\t"
6371 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6372 "movq %rcx,%rax\n\t"
6373 "movq $4,%rcx\n\t"
6374 "cmp %rcx,%rdx\n\t"
6375 "cmovgq %rdx,%rcx\n\t"
6376 "leaq 0(,%rcx,8),%rdx\n\t"
6377 "subq %rdx,%rsp\n\t"
6378 "andq $~15,%rsp\n\t"
6379 "movq %rsp,%rdi\n\t"
6380 "movq %r8,%rsi\n\t"
6381 "rep; movsq\n\t"
6382 "movq 0(%rsp),%rcx\n\t"
6383 "movq 8(%rsp),%rdx\n\t"
6384 "movq 16(%rsp),%r8\n\t"
6385 "movq 24(%rsp),%r9\n\t"
6386 "movq 0(%rsp),%xmm0\n\t"
6387 "movq 8(%rsp),%xmm1\n\t"
6388 "movq 16(%rsp),%xmm2\n\t"
6389 "movq 24(%rsp),%xmm3\n\t"
6390 "callq *%rax\n\t"
6391 "leaq -16(%rbp),%rsp\n\t"
6392 "popq %rdi\n\t"
6393 __ASM_CFI(".cfi_same_value %rdi\n\t")
6394 "popq %rsi\n\t"
6395 __ASM_CFI(".cfi_same_value %rsi\n\t")
6396 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6397 "popq %rbp\n\t"
6398 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6399 __ASM_CFI(".cfi_same_value %rbp\n\t")
6400 "ret")
6401 __ASM_GLOBAL_FUNC( call_double_method,
6402 "jmp " __ASM_NAME("call_method") )
6404 #elif defined(__arm__)
6406 extern LONGLONG CDECL call_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6407 extern float CDECL call_float_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6408 extern double CDECL call_double_method( void *func, int nb_stk_args, const DWORD *stk_args, const DWORD *reg_args );
6409 __ASM_GLOBAL_FUNC( call_method,
6410 /* r0 = *func
6411 * r1 = nb_stk_args
6412 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6413 * 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)
6416 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6417 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6419 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6420 "beq 1f\n\t" /* Skip allocation if no stack args */
6421 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6422 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6423 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6424 "subs r1, r1, #4\n\t" /* Decrement count */
6425 "bgt 2b\n\t" /* Loop till done */
6427 "1:\n\t"
6428 #ifndef __SOFTFP__
6429 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6430 #endif
6431 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6432 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6434 "blx ip\n\t" /* Call the target function */
6436 "mov sp, fp\n\t" /* Clean the stack using fp */
6437 "pop {fp, pc}\n\t" /* Restore fp and return */
6439 __ASM_GLOBAL_FUNC( call_float_method,
6440 "b " __ASM_NAME("call_method") )
6441 __ASM_GLOBAL_FUNC( call_double_method,
6442 "b " __ASM_NAME("call_method") )
6444 #endif /* __arm__ */
6446 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6448 HRESULT hr = S_OK;
6449 ITypeInfo *tinfo2 = NULL;
6450 TYPEATTR *tattr = NULL;
6452 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6453 if (hr)
6455 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6456 "hr = 0x%08x\n",
6457 tdesc->u.hreftype, hr);
6458 return hr;
6460 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6461 if (hr)
6463 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
6464 ITypeInfo_Release(tinfo2);
6465 return hr;
6468 switch (tattr->typekind)
6470 case TKIND_ENUM:
6471 *vt |= VT_I4;
6472 break;
6474 case TKIND_ALIAS:
6475 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
6476 break;
6478 case TKIND_INTERFACE:
6479 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
6480 *vt |= VT_DISPATCH;
6481 else
6482 *vt |= VT_UNKNOWN;
6483 break;
6485 case TKIND_DISPATCH:
6486 *vt |= VT_DISPATCH;
6487 break;
6489 case TKIND_COCLASS:
6490 *vt |= VT_DISPATCH;
6491 break;
6493 case TKIND_RECORD:
6494 FIXME("TKIND_RECORD unhandled.\n");
6495 hr = E_NOTIMPL;
6496 break;
6498 case TKIND_UNION:
6499 FIXME("TKIND_UNION unhandled.\n");
6500 hr = E_NOTIMPL;
6501 break;
6503 default:
6504 FIXME("TKIND %d unhandled.\n",tattr->typekind);
6505 hr = E_NOTIMPL;
6506 break;
6508 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6509 ITypeInfo_Release(tinfo2);
6510 return hr;
6513 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6515 HRESULT hr = S_OK;
6517 /* enforce only one level of pointer indirection */
6518 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6520 tdesc = tdesc->u.lptdesc;
6522 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6523 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6524 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6525 if ((tdesc->vt == VT_USERDEFINED) ||
6526 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6528 VARTYPE vt_userdefined = 0;
6529 const TYPEDESC *tdesc_userdefined = tdesc;
6530 if (tdesc->vt == VT_PTR)
6532 vt_userdefined = VT_BYREF;
6533 tdesc_userdefined = tdesc->u.lptdesc;
6535 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6536 if ((hr == S_OK) &&
6537 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6538 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6540 *vt |= vt_userdefined;
6541 return S_OK;
6544 *vt = VT_BYREF;
6547 switch (tdesc->vt)
6549 case VT_HRESULT:
6550 *vt |= VT_ERROR;
6551 break;
6552 case VT_USERDEFINED:
6553 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6554 break;
6555 case VT_VOID:
6556 case VT_CARRAY:
6557 case VT_PTR:
6558 case VT_LPSTR:
6559 case VT_LPWSTR:
6560 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6561 hr = DISP_E_BADVARTYPE;
6562 break;
6563 case VT_SAFEARRAY:
6564 *vt |= VT_ARRAY;
6565 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6566 break;
6567 case VT_INT:
6568 *vt |= VT_I4;
6569 break;
6570 case VT_UINT:
6571 *vt |= VT_UI4;
6572 break;
6573 default:
6574 *vt |= tdesc->vt;
6575 break;
6577 return hr;
6580 static HRESULT get_iface_guid(ITypeInfo *tinfo, HREFTYPE href, GUID *guid)
6582 ITypeInfo *tinfo2;
6583 TYPEATTR *tattr;
6584 HRESULT hres;
6585 int flags, i;
6587 hres = ITypeInfo_GetRefTypeInfo(tinfo, href, &tinfo2);
6588 if(FAILED(hres))
6589 return hres;
6591 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6592 if(FAILED(hres)) {
6593 ITypeInfo_Release(tinfo2);
6594 return hres;
6597 switch(tattr->typekind) {
6598 case TKIND_ALIAS:
6599 hres = get_iface_guid(tinfo2, tattr->tdescAlias.u.hreftype, guid);
6600 break;
6602 case TKIND_INTERFACE:
6603 case TKIND_DISPATCH:
6604 *guid = tattr->guid;
6605 break;
6607 case TKIND_COCLASS:
6608 for (i = 0; i < tattr->cImplTypes; i++)
6610 ITypeInfo_GetImplTypeFlags(tinfo2, i, &flags);
6611 if (flags & IMPLTYPEFLAG_FDEFAULT)
6612 break;
6615 if (i == tattr->cImplTypes)
6616 i = 0;
6618 hres = ITypeInfo_GetRefTypeOfImplType(tinfo2, i, &href);
6619 if (SUCCEEDED(hres))
6620 hres = get_iface_guid(tinfo2, href, guid);
6621 break;
6623 default:
6624 ERR("Unexpected typekind %d\n", tattr->typekind);
6625 hres = E_UNEXPECTED;
6628 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6629 ITypeInfo_Release(tinfo2);
6630 return hres;
6633 /***********************************************************************
6634 * DispCallFunc (OLEAUT32.@)
6636 * Invokes a function of the specified calling convention, passing the
6637 * specified arguments and returns the result.
6639 * PARAMS
6640 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6641 * oVft [I] The offset in the vtable. See notes.
6642 * cc [I] Calling convention of the function to call.
6643 * vtReturn [I] The return type of the function.
6644 * cActuals [I] Number of parameters.
6645 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6646 * prgpvarg [I] The arguments to pass.
6647 * pvargResult [O] The return value of the function. Can be NULL.
6649 * RETURNS
6650 * Success: S_OK.
6651 * Failure: HRESULT code.
6653 * NOTES
6654 * The HRESULT return value of this function is not affected by the return
6655 * value of the user supplied function, which is returned in pvargResult.
6657 * If pvInstance is NULL then a non-object function is to be called and oVft
6658 * is the address of the function to call.
6660 * The cc parameter can be one of the following values:
6661 *|CC_FASTCALL
6662 *|CC_CDECL
6663 *|CC_PASCAL
6664 *|CC_STDCALL
6665 *|CC_FPFASTCALL
6666 *|CC_SYSCALL
6667 *|CC_MPWCDECL
6668 *|CC_MPWPASCAL
6671 HRESULT WINAPI
6672 DispCallFunc(
6673 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6674 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6676 #ifdef __i386__
6677 int argspos = 0, stack_offset;
6678 void *func;
6679 UINT i;
6680 DWORD *args;
6682 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6683 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6684 pvargResult, V_VT(pvargResult));
6686 if (cc != CC_STDCALL && cc != CC_CDECL)
6688 FIXME("unsupported calling convention %d\n",cc);
6689 return E_INVALIDARG;
6692 /* maximum size for an argument is sizeof(VARIANT) */
6693 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6695 if (pvInstance)
6697 const FARPROC *vtable = *(FARPROC **)pvInstance;
6698 func = vtable[oVft/sizeof(void *)];
6699 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6701 else func = (void *)oVft;
6703 switch (vtReturn)
6705 case VT_DECIMAL:
6706 case VT_VARIANT:
6707 args[argspos++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6708 break;
6709 case VT_HRESULT:
6710 WARN("invalid return type %u\n", vtReturn);
6711 heap_free( args );
6712 return E_INVALIDARG;
6713 default:
6714 break;
6717 for (i = 0; i < cActuals; i++)
6719 VARIANT *arg = prgpvarg[i];
6721 switch (prgvt[i])
6723 case VT_EMPTY:
6724 break;
6725 case VT_I8:
6726 case VT_UI8:
6727 case VT_R8:
6728 case VT_DATE:
6729 case VT_CY:
6730 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6731 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6732 break;
6733 case VT_DECIMAL:
6734 case VT_VARIANT:
6735 memcpy( &args[argspos], arg, sizeof(*arg) );
6736 argspos += sizeof(*arg) / sizeof(DWORD);
6737 break;
6738 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6739 args[argspos++] = V_BOOL(arg);
6740 break;
6741 default:
6742 args[argspos++] = V_UI4(arg);
6743 break;
6745 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6748 switch (vtReturn)
6750 case VT_EMPTY:
6751 case VT_DECIMAL:
6752 case VT_VARIANT:
6753 call_method( func, argspos, args, &stack_offset );
6754 break;
6755 case VT_R4:
6756 V_R4(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6757 break;
6758 case VT_R8:
6759 case VT_DATE:
6760 V_R8(pvargResult) = call_double_method( func, argspos, args, &stack_offset );
6761 break;
6762 case VT_I8:
6763 case VT_UI8:
6764 case VT_CY:
6765 V_UI8(pvargResult) = call_method( func, argspos, args, &stack_offset );
6766 break;
6767 default:
6768 V_UI4(pvargResult) = call_method( func, argspos, args, &stack_offset );
6769 break;
6771 heap_free( args );
6772 if (stack_offset && cc == CC_STDCALL)
6774 WARN( "stack pointer off by %d\n", stack_offset );
6775 return DISP_E_BADCALLEE;
6777 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6778 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6779 return S_OK;
6781 #elif defined(__x86_64__)
6782 int argspos = 0;
6783 UINT i;
6784 DWORD_PTR *args;
6785 void *func;
6787 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6788 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6789 pvargResult, V_VT(pvargResult));
6791 if (cc != CC_STDCALL && cc != CC_CDECL)
6793 FIXME("unsupported calling convention %d\n",cc);
6794 return E_INVALIDARG;
6797 /* maximum size for an argument is sizeof(DWORD_PTR) */
6798 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6800 if (pvInstance)
6802 const FARPROC *vtable = *(FARPROC **)pvInstance;
6803 func = vtable[oVft/sizeof(void *)];
6804 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6806 else func = (void *)oVft;
6808 switch (vtReturn)
6810 case VT_DECIMAL:
6811 case VT_VARIANT:
6812 args[argspos++] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6813 break;
6814 case VT_HRESULT:
6815 WARN("invalid return type %u\n", vtReturn);
6816 heap_free( args );
6817 return E_INVALIDARG;
6818 default:
6819 break;
6822 for (i = 0; i < cActuals; i++)
6824 VARIANT *arg = prgpvarg[i];
6826 switch (prgvt[i])
6828 case VT_DECIMAL:
6829 case VT_VARIANT:
6830 args[argspos++] = (ULONG_PTR)arg;
6831 break;
6832 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6833 args[argspos++] = V_BOOL(arg);
6834 break;
6835 default:
6836 args[argspos++] = V_UI8(arg);
6837 break;
6839 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
6842 switch (vtReturn)
6844 case VT_R4:
6845 V_R4(pvargResult) = call_double_method( func, argspos, args );
6846 break;
6847 case VT_R8:
6848 case VT_DATE:
6849 V_R8(pvargResult) = call_double_method( func, argspos, args );
6850 break;
6851 case VT_DECIMAL:
6852 case VT_VARIANT:
6853 call_method( func, argspos, args );
6854 break;
6855 default:
6856 V_UI8(pvargResult) = call_method( func, argspos, args );
6857 break;
6859 heap_free( args );
6860 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6861 TRACE("retval: %s\n", debugstr_variant(pvargResult));
6862 return S_OK;
6864 #elif defined(__arm__)
6865 int argspos;
6866 void *func;
6867 UINT i;
6868 DWORD *args;
6869 struct {
6870 #ifndef __SOFTFP__
6871 union {
6872 float s[16];
6873 double d[8];
6874 } sd;
6875 #endif
6876 DWORD r[4];
6877 } regs;
6878 int rcount; /* 32-bit register index count */
6879 #ifndef __SOFTFP__
6880 int scount = 0; /* single-precision float register index count */
6881 int dcount = 0; /* double-precision float register index count */
6882 #endif
6884 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6885 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6887 if (cc != CC_STDCALL && cc != CC_CDECL)
6889 FIXME("unsupported calling convention %d\n",cc);
6890 return E_INVALIDARG;
6893 argspos = 0;
6894 rcount = 0;
6896 if (pvInstance)
6898 const FARPROC *vtable = *(FARPROC **)pvInstance;
6899 func = vtable[oVft/sizeof(void *)];
6900 regs.r[rcount++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6902 else func = (void *)oVft;
6904 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6905 /* first as it will need to be in the 'r' registers: */
6906 switch (vtReturn)
6908 case VT_DECIMAL:
6909 case VT_VARIANT:
6910 regs.r[rcount++] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6911 break;
6912 case VT_HRESULT:
6913 WARN("invalid return type %u\n", vtReturn);
6914 return E_INVALIDARG;
6915 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6916 break;
6919 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6920 args = heap_alloc( sizeof(VARIANT) * cActuals + sizeof(DWORD) * 4 );
6922 for (i = 0; i < cActuals; i++)
6924 VARIANT *arg = prgpvarg[i];
6925 DWORD *pdwarg = (DWORD *)(arg); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6926 int ntemp; /* Used for counting words split between registers and stack */
6928 switch (prgvt[i])
6930 case VT_EMPTY:
6931 break;
6932 case VT_R8: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6933 case VT_DATE:
6934 #ifndef __SOFTFP__
6935 dcount = max( (scount + 1) / 2, dcount );
6936 if (dcount < 8)
6938 regs.sd.d[dcount++] = V_R8(arg);
6940 else
6942 argspos += (argspos % 2); /* align argspos to 8-bytes */
6943 memcpy( &args[argspos], &V_R8(arg), sizeof(V_R8(arg)) );
6944 argspos += sizeof(V_R8(arg)) / sizeof(DWORD);
6946 break;
6947 #endif
6948 case VT_I8: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6949 case VT_UI8:
6950 case VT_CY:
6951 if (rcount < 3)
6953 rcount += (rcount % 2); /* align rcount to 8-byte register pair */
6954 memcpy( &regs.r[rcount], &V_UI8(arg), sizeof(V_UI8(arg)) );
6955 rcount += sizeof(V_UI8(arg)) / sizeof(DWORD);
6957 else
6959 rcount = 4; /* Make sure we flag that all 'r' regs are full */
6960 argspos += (argspos % 2); /* align argspos to 8-bytes */
6961 memcpy( &args[argspos], &V_UI8(arg), sizeof(V_UI8(arg)) );
6962 argspos += sizeof(V_UI8(arg)) / sizeof(DWORD);
6964 break;
6965 case VT_DECIMAL: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6966 case VT_VARIANT:
6967 /* 8-byte align 'r' and/or stack: */
6968 if (rcount < 3)
6969 rcount += (rcount % 2);
6970 else
6972 rcount = 4;
6973 argspos += (argspos % 2);
6975 ntemp = sizeof(*arg) / sizeof(DWORD);
6976 while (ntemp > 0)
6978 if (rcount < 4)
6979 regs.r[rcount++] = *pdwarg++;
6980 else
6981 args[argspos++] = *pdwarg++;
6982 --ntemp;
6984 break;
6985 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6986 if (rcount < 4)
6987 regs.r[rcount++] = V_BOOL(arg);
6988 else
6989 args[argspos++] = V_BOOL(arg);
6990 break;
6991 case VT_R4: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6992 #ifndef __SOFTFP__
6993 if (!(scount % 2)) scount = max( scount, dcount * 2 );
6994 if (scount < 16)
6995 regs.sd.s[scount++] = V_R4(arg);
6996 else
6997 args[argspos++] = V_UI4(arg);
6998 break;
6999 #endif
7000 default:
7001 if (rcount < 4)
7002 regs.r[rcount++] = V_UI4(arg);
7003 else
7004 args[argspos++] = V_UI4(arg);
7005 break;
7007 TRACE("arg %u: type %s %s\n", i, debugstr_vt(prgvt[i]), debugstr_variant(arg));
7010 argspos += (argspos % 2); /* Make sure stack function alignment is 8-byte */
7012 switch (vtReturn)
7014 case VT_EMPTY: /* EMPTY = no return value */
7015 case VT_DECIMAL: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7016 case VT_VARIANT:
7017 call_method( func, argspos, args, (DWORD*)&regs );
7018 break;
7019 case VT_R4:
7020 V_R4(pvargResult) = call_float_method( func, argspos, args, (DWORD*)&regs );
7021 break;
7022 case VT_R8:
7023 case VT_DATE:
7024 V_R8(pvargResult) = call_double_method( func, argspos, args, (DWORD*)&regs );
7025 break;
7026 case VT_I8:
7027 case VT_UI8:
7028 case VT_CY:
7029 V_UI8(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7030 break;
7031 default:
7032 V_UI4(pvargResult) = call_method( func, argspos, args, (DWORD*)&regs );
7033 break;
7035 heap_free( args );
7036 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
7037 TRACE("retval: %s\n", debugstr_variant(pvargResult));
7038 return S_OK;
7040 #else
7041 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7042 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
7043 return E_NOTIMPL;
7044 #endif
7047 static inline BOOL func_restricted( const FUNCDESC *desc )
7049 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
7052 #define INVBUF_ELEMENT_SIZE \
7053 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7054 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7055 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7056 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7057 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7058 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7059 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7060 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7062 static HRESULT WINAPI ITypeInfo_fnInvoke(
7063 ITypeInfo2 *iface,
7064 VOID *pIUnk,
7065 MEMBERID memid,
7066 UINT16 wFlags,
7067 DISPPARAMS *pDispParams,
7068 VARIANT *pVarResult,
7069 EXCEPINFO *pExcepInfo,
7070 UINT *pArgErr)
7072 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7073 int i;
7074 unsigned int var_index;
7075 TYPEKIND type_kind;
7076 HRESULT hres;
7077 const TLBFuncDesc *pFuncInfo;
7078 UINT fdc;
7080 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7081 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
7084 if( This->typeattr.wTypeFlags & TYPEFLAG_FRESTRICTED )
7085 return DISP_E_MEMBERNOTFOUND;
7087 if (!pDispParams)
7089 ERR("NULL pDispParams not allowed\n");
7090 return E_INVALIDARG;
7093 dump_DispParms(pDispParams);
7095 if (pDispParams->cNamedArgs > pDispParams->cArgs)
7097 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7098 pDispParams->cNamedArgs, pDispParams->cArgs);
7099 return E_INVALIDARG;
7102 /* we do this instead of using GetFuncDesc since it will return a fake
7103 * FUNCDESC for dispinterfaces and we want the real function description */
7104 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
7105 pFuncInfo = &This->funcdescs[fdc];
7106 if ((memid == pFuncInfo->funcdesc.memid) &&
7107 (wFlags & pFuncInfo->funcdesc.invkind) &&
7108 !func_restricted( &pFuncInfo->funcdesc ))
7109 break;
7112 if (fdc < This->typeattr.cFuncs) {
7113 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
7115 if (TRACE_ON(ole))
7117 TRACE("invoking:\n");
7118 dump_TLBFuncDescOne(pFuncInfo);
7121 switch (func_desc->funckind) {
7122 case FUNC_PUREVIRTUAL:
7123 case FUNC_VIRTUAL: {
7124 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
7125 VARIANT varresult;
7126 VARIANT retval; /* pointer for storing byref retvals in */
7127 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
7128 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
7129 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
7130 UINT cNamedArgs = pDispParams->cNamedArgs;
7131 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
7132 UINT vargs_converted=0;
7134 hres = S_OK;
7136 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
7138 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
7140 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7141 hres = DISP_E_PARAMNOTFOUND;
7142 goto func_fail;
7146 if (func_desc->cParamsOpt < 0 && cNamedArgs)
7148 ERR("functions with the vararg attribute do not support named arguments\n");
7149 hres = DISP_E_NONAMEDARGS;
7150 goto func_fail;
7153 for (i = 0; i < func_desc->cParams; i++)
7155 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7156 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
7157 if (FAILED(hres))
7158 goto func_fail;
7161 TRACE("changing args\n");
7162 for (i = 0; i < func_desc->cParams; i++)
7164 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7165 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
7166 VARIANTARG *src_arg;
7168 if (wParamFlags & PARAMFLAG_FLCID)
7170 VARIANTARG *arg;
7171 arg = prgpvarg[i] = &rgvarg[i];
7172 V_VT(arg) = VT_I4;
7173 V_I4(arg) = This->pTypeLib->lcid;
7174 continue;
7177 src_arg = NULL;
7179 if (cNamedArgs)
7181 USHORT j;
7182 for (j = 0; j < cNamedArgs; j++)
7183 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
7185 src_arg = &pDispParams->rgvarg[j];
7186 break;
7190 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
7192 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7193 vargs_converted++;
7196 if (wParamFlags & PARAMFLAG_FRETVAL)
7198 /* under most conditions the caller is not allowed to
7199 * pass in a dispparam arg in the index of what would be
7200 * the retval parameter. however, there is an exception
7201 * where the extra parameter is used in an extra
7202 * IDispatch::Invoke below */
7203 if ((i < pDispParams->cArgs) &&
7204 ((func_desc->cParams != 1) || !pVarResult ||
7205 !(func_desc->invkind & INVOKE_PROPERTYGET)))
7207 hres = DISP_E_BADPARAMCOUNT;
7208 break;
7211 /* note: this check is placed so that if the caller passes
7212 * in a VARIANTARG for the retval we just ignore it, like
7213 * native does */
7214 if (i == func_desc->cParams - 1)
7216 VARIANTARG *arg;
7217 arg = prgpvarg[i] = &rgvarg[i];
7218 memset(arg, 0, sizeof(*arg));
7219 V_VT(arg) = rgvt[i];
7220 memset(&retval, 0, sizeof(retval));
7221 V_BYREF(arg) = &retval;
7223 else
7225 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
7226 hres = E_UNEXPECTED;
7227 break;
7230 else if (src_arg && !((wParamFlags & PARAMFLAG_FOPT) &&
7231 V_VT(src_arg) == VT_ERROR && V_ERROR(src_arg) == DISP_E_PARAMNOTFOUND))
7233 TRACE("%s\n", debugstr_variant(src_arg));
7235 if(rgvt[i]!=V_VT(src_arg))
7237 if (rgvt[i] == VT_VARIANT)
7238 hres = VariantCopy(&rgvarg[i], src_arg);
7239 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
7241 if (rgvt[i] == V_VT(src_arg))
7242 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
7243 else
7245 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7246 if (wParamFlags & PARAMFLAG_FIN)
7247 hres = VariantCopy(&missing_arg[i], src_arg);
7248 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
7250 V_VT(&rgvarg[i]) = rgvt[i];
7252 else if ((rgvt[i] == (VT_VARIANT | VT_ARRAY) || rgvt[i] == (VT_VARIANT | VT_ARRAY | VT_BYREF)) && func_desc->cParamsOpt < 0)
7254 SAFEARRAY *a;
7255 SAFEARRAYBOUND bound;
7256 VARIANT *v;
7257 LONG j;
7258 bound.lLbound = 0;
7259 bound.cElements = pDispParams->cArgs-i;
7260 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
7262 ERR("SafeArrayCreate failed\n");
7263 break;
7265 hres = SafeArrayAccessData(a, (LPVOID)&v);
7266 if (hres != S_OK)
7268 ERR("SafeArrayAccessData failed with %x\n", hres);
7269 SafeArrayDestroy(a);
7270 break;
7272 for (j = 0; j < bound.cElements; j++)
7273 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
7274 hres = SafeArrayUnaccessData(a);
7275 if (hres != S_OK)
7277 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7278 SafeArrayDestroy(a);
7279 break;
7281 if (rgvt[i] & VT_BYREF)
7282 V_BYREF(&rgvarg[i]) = &a;
7283 else
7284 V_ARRAY(&rgvarg[i]) = a;
7285 V_VT(&rgvarg[i]) = rgvt[i];
7287 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
7289 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7290 if (wParamFlags & PARAMFLAG_FIN)
7291 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
7292 else
7293 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
7294 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
7295 V_VT(&rgvarg[i]) = rgvt[i];
7297 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
7299 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
7300 V_VT(&rgvarg[i]) = rgvt[i];
7302 else
7304 /* FIXME: this doesn't work for VT_BYREF arguments if
7305 * they are not the same type as in the paramdesc */
7306 V_VT(&rgvarg[i]) = V_VT(src_arg);
7307 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
7308 V_VT(&rgvarg[i]) = rgvt[i];
7311 if (FAILED(hres))
7313 ERR("failed to convert param %d to %s from %s\n", i,
7314 debugstr_vt(rgvt[i]), debugstr_variant(src_arg));
7315 break;
7317 prgpvarg[i] = &rgvarg[i];
7319 else
7321 prgpvarg[i] = src_arg;
7324 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
7325 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
7326 && V_UNKNOWN(prgpvarg[i])) {
7327 IUnknown *userdefined_iface;
7328 GUID guid;
7330 if (tdesc->vt == VT_PTR)
7331 tdesc = tdesc->u.lptdesc;
7333 hres = get_iface_guid((ITypeInfo*)iface, tdesc->u.hreftype, &guid);
7334 if(FAILED(hres))
7335 break;
7337 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
7338 if(FAILED(hres)) {
7339 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
7340 break;
7343 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
7344 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
7347 else if (wParamFlags & PARAMFLAG_FOPT)
7349 VARIANTARG *arg;
7350 arg = prgpvarg[i] = &rgvarg[i];
7351 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7353 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
7354 if (FAILED(hres))
7355 break;
7357 else
7359 VARIANTARG *missing_arg;
7360 /* if the function wants a pointer to a variant then
7361 * set that up, otherwise just pass the VT_ERROR in
7362 * the argument by value */
7363 if (rgvt[i] & VT_BYREF)
7365 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
7366 V_VT(arg) = VT_VARIANT | VT_BYREF;
7367 V_VARIANTREF(arg) = missing_arg;
7369 else
7370 missing_arg = arg;
7371 V_VT(missing_arg) = VT_ERROR;
7372 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
7375 else
7377 hres = DISP_E_BADPARAMCOUNT;
7378 break;
7381 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7383 /* VT_VOID is a special case for return types, so it is not
7384 * handled in the general function */
7385 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
7386 V_VT(&varresult) = VT_EMPTY;
7387 else
7389 V_VT(&varresult) = 0;
7390 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
7391 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
7394 hres = DispCallFunc(pIUnk, func_desc->oVft & 0xFFFC, func_desc->callconv,
7395 V_VT(&varresult), func_desc->cParams, rgvt,
7396 prgpvarg, &varresult);
7398 vargs_converted = 0;
7400 for (i = 0; i < func_desc->cParams; i++)
7402 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
7403 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
7405 if (wParamFlags & PARAMFLAG_FLCID)
7406 continue;
7407 else if (wParamFlags & PARAMFLAG_FRETVAL)
7409 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg[i]));
7411 if (pVarResult)
7413 VariantInit(pVarResult);
7414 /* deref return value */
7415 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
7418 VARIANT_ClearInd(prgpvarg[i]);
7420 else if (vargs_converted < pDispParams->cArgs)
7422 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
7423 if (wParamFlags & PARAMFLAG_FOUT)
7425 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
7427 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
7429 if (FAILED(hres))
7431 ERR("failed to convert param %d to vt %d\n", i,
7432 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
7433 break;
7437 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
7438 func_desc->cParamsOpt < 0 &&
7439 i == func_desc->cParams-1)
7441 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
7442 LONG j, ubound;
7443 VARIANT *v;
7444 hres = SafeArrayGetUBound(a, 1, &ubound);
7445 if (hres != S_OK)
7447 ERR("SafeArrayGetUBound failed with %x\n", hres);
7448 break;
7450 hres = SafeArrayAccessData(a, (LPVOID)&v);
7451 if (hres != S_OK)
7453 ERR("SafeArrayAccessData failed with %x\n", hres);
7454 break;
7456 for (j = 0; j <= ubound; j++)
7457 VariantClear(&v[j]);
7458 hres = SafeArrayUnaccessData(a);
7459 if (hres != S_OK)
7461 ERR("SafeArrayUnaccessData failed with %x\n", hres);
7462 break;
7465 VariantClear(&rgvarg[i]);
7466 vargs_converted++;
7468 else if (wParamFlags & PARAMFLAG_FOPT)
7470 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
7471 VariantClear(&rgvarg[i]);
7474 VariantClear(&missing_arg[i]);
7477 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
7479 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
7480 hres = DISP_E_EXCEPTION;
7481 if (pExcepInfo)
7483 IErrorInfo *pErrorInfo;
7484 pExcepInfo->scode = V_ERROR(&varresult);
7485 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
7487 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
7488 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
7489 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
7490 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
7492 IErrorInfo_Release(pErrorInfo);
7496 if (V_VT(&varresult) != VT_ERROR)
7498 TRACE("varresult value: %s\n", debugstr_variant(&varresult));
7500 if (pVarResult)
7502 VariantClear(pVarResult);
7503 *pVarResult = varresult;
7505 else
7506 VariantClear(&varresult);
7509 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
7510 (func_desc->invkind & INVOKE_PROPERTYGET) &&
7511 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
7512 (pDispParams->cArgs != 0))
7514 if (V_VT(pVarResult) == VT_DISPATCH)
7516 IDispatch *pDispatch = V_DISPATCH(pVarResult);
7517 /* Note: not VariantClear; we still need the dispatch
7518 * pointer to be valid */
7519 VariantInit(pVarResult);
7520 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
7521 GetSystemDefaultLCID(), wFlags,
7522 pDispParams, pVarResult, pExcepInfo, pArgErr);
7523 IDispatch_Release(pDispatch);
7525 else
7527 VariantClear(pVarResult);
7528 hres = DISP_E_NOTACOLLECTION;
7532 func_fail:
7533 heap_free(buffer);
7534 break;
7536 case FUNC_DISPATCH: {
7537 IDispatch *disp;
7539 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
7540 if (SUCCEEDED(hres)) {
7541 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7542 hres = IDispatch_Invoke(
7543 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
7544 pVarResult,pExcepInfo,pArgErr
7546 if (FAILED(hres))
7547 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
7548 IDispatch_Release(disp);
7549 } else
7550 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7551 break;
7553 default:
7554 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
7555 hres = E_FAIL;
7556 break;
7559 TRACE("-- 0x%08x\n", hres);
7560 return hres;
7562 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
7563 VARDESC *var_desc;
7565 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
7566 if(FAILED(hres)) return hres;
7568 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7569 dump_VARDESC(var_desc);
7570 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
7571 return E_NOTIMPL;
7574 /* not found, look for it in inherited interfaces */
7575 ITypeInfo2_GetTypeKind(iface, &type_kind);
7576 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
7577 if(This->impltypes) {
7578 /* recursive search */
7579 ITypeInfo *pTInfo;
7580 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7581 if(SUCCEEDED(hres)){
7582 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
7583 ITypeInfo_Release(pTInfo);
7584 return hres;
7586 WARN("Could not search inherited interface!\n");
7589 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
7590 return DISP_E_MEMBERNOTFOUND;
7593 /* ITypeInfo::GetDocumentation
7595 * Retrieves the documentation string, the complete Help file name and path,
7596 * and the context ID for the Help topic for a specified type description.
7598 * (Can be tested by the Visual Basic Editor in Word for instance.)
7600 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
7601 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
7602 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
7604 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7605 const TLBFuncDesc *pFDesc;
7606 const TLBVarDesc *pVDesc;
7607 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7608 " HelpContext(%p) HelpFile(%p)\n",
7609 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
7610 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7611 if(pBstrName)
7612 *pBstrName=SysAllocString(TLB_get_bstr(This->Name));
7613 if(pBstrDocString)
7614 *pBstrDocString=SysAllocString(TLB_get_bstr(This->DocString));
7615 if(pdwHelpContext)
7616 *pdwHelpContext=This->dwHelpContext;
7617 if(pBstrHelpFile)
7618 *pBstrHelpFile=SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7619 return S_OK;
7620 }else {/* for a member */
7621 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7622 if(pFDesc){
7623 if(pBstrName)
7624 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Name));
7625 if(pBstrDocString)
7626 *pBstrDocString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
7627 if(pdwHelpContext)
7628 *pdwHelpContext=pFDesc->helpcontext;
7629 if(pBstrHelpFile)
7630 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7631 return S_OK;
7633 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
7634 if(pVDesc){
7635 if(pBstrName)
7636 *pBstrName = SysAllocString(TLB_get_bstr(pVDesc->Name));
7637 if(pBstrDocString)
7638 *pBstrDocString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
7639 if(pdwHelpContext)
7640 *pdwHelpContext=pVDesc->HelpContext;
7641 if(pBstrHelpFile)
7642 *pBstrHelpFile = SysAllocString(TLB_get_bstr(This->pTypeLib->HelpFile));
7643 return S_OK;
7647 if(This->impltypes &&
7648 (This->typeattr.typekind == TKIND_INTERFACE || This->typeattr.typekind == TKIND_DISPATCH)) {
7649 /* recursive search */
7650 ITypeInfo *pTInfo;
7651 HRESULT result;
7652 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
7653 if(SUCCEEDED(result)) {
7654 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
7655 pBstrDocString, pdwHelpContext, pBstrHelpFile);
7656 ITypeInfo_Release(pTInfo);
7657 return result;
7659 WARN("Could not search inherited interface!\n");
7662 WARN("member %d not found\n", memid);
7663 return TYPE_E_ELEMENTNOTFOUND;
7666 /* ITypeInfo::GetDllEntry
7668 * Retrieves a description or specification of an entry point for a function
7669 * in a DLL.
7671 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
7672 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
7673 WORD *pwOrdinal)
7675 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7676 const TLBFuncDesc *pFDesc;
7678 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
7680 if (pBstrDllName) *pBstrDllName = NULL;
7681 if (pBstrName) *pBstrName = NULL;
7682 if (pwOrdinal) *pwOrdinal = 0;
7684 if (This->typeattr.typekind != TKIND_MODULE)
7685 return TYPE_E_BADMODULEKIND;
7687 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
7688 if(pFDesc){
7689 dump_TypeInfo(This);
7690 if (TRACE_ON(ole))
7691 dump_TLBFuncDescOne(pFDesc);
7693 if (pBstrDllName)
7694 *pBstrDllName = SysAllocString(TLB_get_bstr(This->DllName));
7696 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
7697 if (pBstrName)
7698 *pBstrName = SysAllocString(TLB_get_bstr(pFDesc->Entry));
7699 if (pwOrdinal)
7700 *pwOrdinal = -1;
7701 return S_OK;
7703 if (pBstrName)
7704 *pBstrName = NULL;
7705 if (pwOrdinal)
7706 *pwOrdinal = LOWORD(pFDesc->Entry);
7707 return S_OK;
7709 return TYPE_E_ELEMENTNOTFOUND;
7712 /* internal function to make the inherited interfaces' methods appear
7713 * part of the interface */
7714 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
7715 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
7717 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
7718 HRESULT hr;
7720 TRACE("%p, 0x%x\n", iface, *hRefType);
7722 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7724 ITypeInfo *pSubTypeInfo;
7726 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7727 if (FAILED(hr))
7728 return hr;
7730 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7731 hRefType, ppTInfo);
7732 ITypeInfo_Release(pSubTypeInfo);
7733 if (SUCCEEDED(hr))
7734 return hr;
7736 *hRefType -= DISPATCH_HREF_OFFSET;
7738 if (!(*hRefType & DISPATCH_HREF_MASK))
7739 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7740 else
7741 return E_FAIL;
7744 struct search_res_tlb_params
7746 const GUID *guid;
7747 ITypeLib *pTLib;
7750 static BOOL CALLBACK search_res_tlb(HMODULE hModule, LPCWSTR lpszType, LPWSTR lpszName, LONG_PTR lParam)
7752 struct search_res_tlb_params *params = (LPVOID)lParam;
7753 static const WCHAR formatW[] = {'\\','%','d',0};
7754 WCHAR szPath[MAX_PATH+1];
7755 ITypeLib *pTLib = NULL;
7756 HRESULT ret;
7757 DWORD len;
7759 if (IS_INTRESOURCE(lpszName) == FALSE)
7760 return TRUE;
7762 if (!(len = GetModuleFileNameW(hModule, szPath, MAX_PATH)))
7763 return TRUE;
7765 if (snprintfW(szPath + len, ARRAY_SIZE(szPath) - len, formatW, LOWORD(lpszName)) < 0)
7766 return TRUE;
7768 ret = LoadTypeLibEx(szPath, REGKIND_NONE, &pTLib);
7769 if (SUCCEEDED(ret))
7771 ITypeLibImpl *impl = impl_from_ITypeLib(pTLib);
7772 if (IsEqualGUID(params->guid, impl->guid))
7774 params->pTLib = pTLib;
7775 return FALSE; /* stop enumeration */
7777 ITypeLib_Release(pTLib);
7780 return TRUE;
7783 /* ITypeInfo::GetRefTypeInfo
7785 * If a type description references other type descriptions, it retrieves
7786 * the referenced type descriptions.
7788 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7789 ITypeInfo2 *iface,
7790 HREFTYPE hRefType,
7791 ITypeInfo **ppTInfo)
7793 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7794 HRESULT result = E_FAIL;
7796 if(!ppTInfo)
7797 return E_INVALIDARG;
7799 if ((INT)hRefType < 0) {
7800 ITypeInfoImpl *pTypeInfoImpl;
7802 if (!(This->typeattr.wTypeFlags & TYPEFLAG_FDUAL) ||
7803 !(This->typeattr.typekind == TKIND_INTERFACE ||
7804 This->typeattr.typekind == TKIND_DISPATCH))
7805 return TYPE_E_ELEMENTNOTFOUND;
7807 /* when we meet a DUAL typeinfo, we must create the alternate
7808 * version of it.
7810 pTypeInfoImpl = ITypeInfoImpl_Constructor();
7812 *pTypeInfoImpl = *This;
7813 pTypeInfoImpl->ref = 0;
7814 list_init(&pTypeInfoImpl->custdata_list);
7816 if (This->typeattr.typekind == TKIND_INTERFACE)
7817 pTypeInfoImpl->typeattr.typekind = TKIND_DISPATCH;
7818 else
7819 pTypeInfoImpl->typeattr.typekind = TKIND_INTERFACE;
7821 *ppTInfo = (ITypeInfo *)&pTypeInfoImpl->ITypeInfo2_iface;
7822 /* the AddRef implicitly adds a reference to the parent typelib, which
7823 * stops the copied data from being destroyed until the new typeinfo's
7824 * refcount goes to zero, but we need to signal to the new instance to
7825 * not free its data structures when it is destroyed */
7826 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7828 ITypeInfo_AddRef(*ppTInfo);
7830 result = S_OK;
7831 } else if ((hRefType & DISPATCH_HREF_MASK) &&
7832 (This->typeattr.typekind == TKIND_DISPATCH))
7834 HREFTYPE href_dispatch = hRefType;
7835 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7836 } else {
7837 TLBRefType *ref_type;
7838 ITypeLib *pTLib = NULL;
7839 UINT i;
7841 if(!(hRefType & 0x1)){
7842 for(i = 0; i < This->pTypeLib->TypeInfoCount; ++i)
7844 if (This->pTypeLib->typeinfos[i]->hreftype == (hRefType&(~0x3)))
7846 result = S_OK;
7847 *ppTInfo = (ITypeInfo*)&This->pTypeLib->typeinfos[i]->ITypeInfo2_iface;
7848 ITypeInfo_AddRef(*ppTInfo);
7849 goto end;
7854 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7856 if(ref_type->reference == (hRefType & (~0x3)))
7857 break;
7859 if(&ref_type->entry == &This->pTypeLib->ref_list)
7861 FIXME("Can't find pRefType for ref %x\n", hRefType);
7862 goto end;
7865 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7866 UINT Index;
7867 TRACE("internal reference\n");
7868 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7869 } else {
7870 if(ref_type->pImpTLInfo->pImpTypeLib) {
7871 TRACE("typeinfo in imported typelib that is already loaded\n");
7872 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7873 ITypeLib_AddRef(pTLib);
7874 result = S_OK;
7875 } else {
7876 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
7877 struct search_res_tlb_params params;
7878 BSTR libnam;
7880 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7882 /* Search in resource table */
7883 params.guid = TLB_get_guid_null(ref_type->pImpTLInfo->guid);
7884 params.pTLib = NULL;
7885 EnumResourceNamesW(NULL, TYPELIBW, search_res_tlb, (LONG_PTR)&params);
7886 pTLib = params.pTLib;
7887 result = S_OK;
7889 if (!pTLib)
7891 /* Search on disk */
7892 result = query_typelib_path(TLB_get_guid_null(ref_type->pImpTLInfo->guid),
7893 ref_type->pImpTLInfo->wVersionMajor,
7894 ref_type->pImpTLInfo->wVersionMinor,
7895 This->pTypeLib->syskind,
7896 ref_type->pImpTLInfo->lcid, &libnam, TRUE);
7897 if (FAILED(result))
7898 libnam = SysAllocString(ref_type->pImpTLInfo->name);
7900 result = LoadTypeLib(libnam, &pTLib);
7901 SysFreeString(libnam);
7904 if(SUCCEEDED(result)) {
7905 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7906 ITypeLib_AddRef(pTLib);
7910 if(SUCCEEDED(result)) {
7911 if(ref_type->index == TLB_REF_USE_GUID)
7912 result = ITypeLib_GetTypeInfoOfGuid(pTLib, TLB_get_guid_null(ref_type->guid), ppTInfo);
7913 else
7914 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7916 if (pTLib != NULL)
7917 ITypeLib_Release(pTLib);
7920 end:
7921 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7922 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7923 return result;
7926 /* ITypeInfo::AddressOfMember
7928 * Retrieves the addresses of static functions or variables, such as those
7929 * defined in a DLL.
7931 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7932 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7934 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7935 HRESULT hr;
7936 BSTR dll, entry;
7937 WORD ordinal;
7938 HMODULE module;
7940 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7942 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7943 if (FAILED(hr))
7944 return hr;
7946 module = LoadLibraryW(dll);
7947 if (!module)
7949 ERR("couldn't load %s\n", debugstr_w(dll));
7950 SysFreeString(dll);
7951 SysFreeString(entry);
7952 return STG_E_FILENOTFOUND;
7954 /* FIXME: store library somewhere where we can free it */
7956 if (entry)
7958 LPSTR entryA;
7959 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7960 entryA = heap_alloc(len);
7961 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7963 *ppv = GetProcAddress(module, entryA);
7964 if (!*ppv)
7965 ERR("function not found %s\n", debugstr_a(entryA));
7967 heap_free(entryA);
7969 else
7971 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7972 if (!*ppv)
7973 ERR("function not found %d\n", ordinal);
7976 SysFreeString(dll);
7977 SysFreeString(entry);
7979 if (!*ppv)
7980 return TYPE_E_DLLFUNCTIONNOTFOUND;
7982 return S_OK;
7985 /* ITypeInfo::CreateInstance
7987 * Creates a new instance of a type that describes a component object class
7988 * (coclass).
7990 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7991 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7993 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7994 HRESULT hr;
7995 TYPEATTR *pTA;
7997 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7999 *ppvObj = NULL;
8001 if(pOuterUnk)
8003 WARN("Not able to aggregate\n");
8004 return CLASS_E_NOAGGREGATION;
8007 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
8008 if(FAILED(hr)) return hr;
8010 if(pTA->typekind != TKIND_COCLASS)
8012 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
8013 hr = E_INVALIDARG;
8014 goto end;
8017 hr = S_FALSE;
8018 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
8020 IUnknown *pUnk;
8021 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
8022 TRACE("GetActiveObject rets %08x\n", hr);
8023 if(hr == S_OK)
8025 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
8026 IUnknown_Release(pUnk);
8030 if(hr != S_OK)
8031 hr = CoCreateInstance(&pTA->guid, NULL,
8032 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
8033 riid, ppvObj);
8035 end:
8036 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
8037 return hr;
8040 /* ITypeInfo::GetMops
8042 * Retrieves marshalling information.
8044 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
8045 BSTR *pBstrMops)
8047 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8048 FIXME("(%p %d) stub!\n", This, memid);
8049 *pBstrMops = NULL;
8050 return S_OK;
8053 /* ITypeInfo::GetContainingTypeLib
8055 * Retrieves the containing type library and the index of the type description
8056 * within that type library.
8058 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
8059 ITypeLib * *ppTLib, UINT *pIndex)
8061 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8063 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8064 if (pIndex) {
8065 *pIndex=This->index;
8066 TRACE("returning pIndex=%d\n", *pIndex);
8069 if (ppTLib) {
8070 *ppTLib = (ITypeLib *)&This->pTypeLib->ITypeLib2_iface;
8071 ITypeLib_AddRef(*ppTLib);
8072 TRACE("returning ppTLib=%p\n", *ppTLib);
8075 return S_OK;
8078 /* ITypeInfo::ReleaseTypeAttr
8080 * Releases a TYPEATTR previously returned by Get
8083 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
8084 TYPEATTR* pTypeAttr)
8086 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8087 TRACE("(%p)->(%p)\n", This, pTypeAttr);
8088 heap_free(pTypeAttr);
8091 /* ITypeInfo::ReleaseFuncDesc
8093 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8095 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
8096 ITypeInfo2 *iface,
8097 FUNCDESC *pFuncDesc)
8099 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8100 SHORT i;
8102 TRACE("(%p)->(%p)\n", This, pFuncDesc);
8104 for (i = 0; i < pFuncDesc->cParams; i++)
8105 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
8106 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
8108 SysFreeString((BSTR)pFuncDesc);
8111 /* ITypeInfo::ReleaseVarDesc
8113 * Releases a VARDESC previously returned by GetVarDesc.
8115 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
8116 VARDESC *pVarDesc)
8118 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8119 TRACE("(%p)->(%p)\n", This, pVarDesc);
8121 TLB_FreeVarDesc(pVarDesc);
8124 /* ITypeInfo2::GetTypeKind
8126 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8129 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
8130 TYPEKIND *pTypeKind)
8132 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8133 *pTypeKind = This->typeattr.typekind;
8134 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
8135 return S_OK;
8138 /* ITypeInfo2::GetTypeFlags
8140 * Returns the type flags without any allocations. This returns a DWORD type
8141 * flag, which expands the type flags without growing the TYPEATTR (type
8142 * attribute).
8145 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
8147 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8148 *pTypeFlags=This->typeattr.wTypeFlags;
8149 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
8150 return S_OK;
8153 /* ITypeInfo2::GetFuncIndexOfMemId
8154 * Binds to a specific member based on a known DISPID, where the member name
8155 * is not known (for example, when binding to a default member).
8158 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
8159 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
8161 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8162 UINT fdc;
8163 HRESULT result;
8165 for (fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8166 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
8167 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
8168 break;
8170 if(fdc < This->typeattr.cFuncs) {
8171 *pFuncIndex = fdc;
8172 result = S_OK;
8173 } else
8174 result = TYPE_E_ELEMENTNOTFOUND;
8176 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
8177 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
8178 return result;
8181 /* TypeInfo2::GetVarIndexOfMemId
8183 * Binds to a specific member based on a known DISPID, where the member name
8184 * is not known (for example, when binding to a default member).
8187 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
8188 MEMBERID memid, UINT *pVarIndex)
8190 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8191 TLBVarDesc *pVarInfo;
8193 TRACE("%p %d %p\n", iface, memid, pVarIndex);
8195 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8196 if(!pVarInfo)
8197 return TYPE_E_ELEMENTNOTFOUND;
8199 *pVarIndex = (pVarInfo - This->vardescs);
8201 return S_OK;
8204 /* ITypeInfo2::GetCustData
8206 * Gets the custom data
8208 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
8209 ITypeInfo2 * iface,
8210 REFGUID guid,
8211 VARIANT *pVarVal)
8213 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8214 TLBCustData *pCData;
8216 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8218 if(!guid || !pVarVal)
8219 return E_INVALIDARG;
8221 pCData = TLB_get_custdata_by_guid(This->pcustdata_list, guid);
8223 VariantInit( pVarVal);
8224 if (pCData)
8225 VariantCopy( pVarVal, &pCData->data);
8226 else
8227 VariantClear( pVarVal );
8228 return S_OK;
8231 /* ITypeInfo2::GetFuncCustData
8233 * Gets the custom data
8235 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
8236 ITypeInfo2 * iface,
8237 UINT index,
8238 REFGUID guid,
8239 VARIANT *pVarVal)
8241 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8242 TLBCustData *pCData;
8243 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8245 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8247 if(index >= This->typeattr.cFuncs)
8248 return TYPE_E_ELEMENTNOTFOUND;
8250 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
8251 if(!pCData)
8252 return TYPE_E_ELEMENTNOTFOUND;
8254 VariantInit(pVarVal);
8255 VariantCopy(pVarVal, &pCData->data);
8257 return S_OK;
8260 /* ITypeInfo2::GetParamCustData
8262 * Gets the custom data
8264 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
8265 ITypeInfo2 * iface,
8266 UINT indexFunc,
8267 UINT indexParam,
8268 REFGUID guid,
8269 VARIANT *pVarVal)
8271 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8272 TLBCustData *pCData;
8273 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8275 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
8276 debugstr_guid(guid), pVarVal);
8278 if(indexFunc >= This->typeattr.cFuncs)
8279 return TYPE_E_ELEMENTNOTFOUND;
8281 if(indexParam >= pFDesc->funcdesc.cParams)
8282 return TYPE_E_ELEMENTNOTFOUND;
8284 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
8285 if(!pCData)
8286 return TYPE_E_ELEMENTNOTFOUND;
8288 VariantInit(pVarVal);
8289 VariantCopy(pVarVal, &pCData->data);
8291 return S_OK;
8294 /* ITypeInfo2::GetVarCustData
8296 * Gets the custom data
8298 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
8299 ITypeInfo2 * iface,
8300 UINT index,
8301 REFGUID guid,
8302 VARIANT *pVarVal)
8304 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8305 TLBCustData *pCData;
8306 TLBVarDesc *pVDesc = &This->vardescs[index];
8308 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
8310 if(index >= This->typeattr.cVars)
8311 return TYPE_E_ELEMENTNOTFOUND;
8313 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
8314 if(!pCData)
8315 return TYPE_E_ELEMENTNOTFOUND;
8317 VariantInit(pVarVal);
8318 VariantCopy(pVarVal, &pCData->data);
8320 return S_OK;
8323 /* ITypeInfo2::GetImplCustData
8325 * Gets the custom data
8327 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
8328 ITypeInfo2 * iface,
8329 UINT index,
8330 REFGUID guid,
8331 VARIANT *pVarVal)
8333 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8334 TLBCustData *pCData;
8335 TLBImplType *pRDesc = &This->impltypes[index];
8337 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
8339 if(index >= This->typeattr.cImplTypes)
8340 return TYPE_E_ELEMENTNOTFOUND;
8342 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
8343 if(!pCData)
8344 return TYPE_E_ELEMENTNOTFOUND;
8346 VariantInit(pVarVal);
8347 VariantCopy(pVarVal, &pCData->data);
8349 return S_OK;
8352 /* ITypeInfo2::GetDocumentation2
8354 * Retrieves the documentation string, the complete Help file name and path,
8355 * the localization context to use, and the context ID for the library Help
8356 * topic in the Help file.
8359 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
8360 ITypeInfo2 * iface,
8361 MEMBERID memid,
8362 LCID lcid,
8363 BSTR *pbstrHelpString,
8364 DWORD *pdwHelpStringContext,
8365 BSTR *pbstrHelpStringDll)
8367 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8368 const TLBFuncDesc *pFDesc;
8369 const TLBVarDesc *pVDesc;
8370 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8371 "HelpStringContext(%p) HelpStringDll(%p)\n",
8372 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
8373 pbstrHelpStringDll );
8374 /* the help string should be obtained from the helpstringdll,
8375 * using the _DLLGetDocumentation function, based on the supplied
8376 * lcid. Nice to do sometime...
8378 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
8379 if(pbstrHelpString)
8380 *pbstrHelpString=SysAllocString(TLB_get_bstr(This->Name));
8381 if(pdwHelpStringContext)
8382 *pdwHelpStringContext=This->dwHelpStringContext;
8383 if(pbstrHelpStringDll)
8384 *pbstrHelpStringDll=
8385 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8386 return S_OK;
8387 }else {/* for a member */
8388 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->typeattr.cFuncs, memid);
8389 if(pFDesc){
8390 if(pbstrHelpString)
8391 *pbstrHelpString=SysAllocString(TLB_get_bstr(pFDesc->HelpString));
8392 if(pdwHelpStringContext)
8393 *pdwHelpStringContext=pFDesc->HelpStringContext;
8394 if(pbstrHelpStringDll)
8395 *pbstrHelpStringDll=
8396 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8397 return S_OK;
8399 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->typeattr.cVars, memid);
8400 if(pVDesc){
8401 if(pbstrHelpString)
8402 *pbstrHelpString=SysAllocString(TLB_get_bstr(pVDesc->HelpString));
8403 if(pdwHelpStringContext)
8404 *pdwHelpStringContext=pVDesc->HelpStringContext;
8405 if(pbstrHelpStringDll)
8406 *pbstrHelpStringDll=
8407 SysAllocString(TLB_get_bstr(This->pTypeLib->HelpStringDll));/* FIXME */
8408 return S_OK;
8411 return TYPE_E_ELEMENTNOTFOUND;
8414 /* ITypeInfo2::GetAllCustData
8416 * Gets all custom data items for the Type info.
8419 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
8420 ITypeInfo2 * iface,
8421 CUSTDATA *pCustData)
8423 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8425 TRACE("%p %p\n", This, pCustData);
8427 return TLB_copy_all_custdata(This->pcustdata_list, pCustData);
8430 /* ITypeInfo2::GetAllFuncCustData
8432 * Gets all custom data items for the specified Function
8435 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
8436 ITypeInfo2 * iface,
8437 UINT index,
8438 CUSTDATA *pCustData)
8440 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8441 TLBFuncDesc *pFDesc = &This->funcdescs[index];
8443 TRACE("%p %u %p\n", This, index, pCustData);
8445 if(index >= This->typeattr.cFuncs)
8446 return TYPE_E_ELEMENTNOTFOUND;
8448 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
8451 /* ITypeInfo2::GetAllParamCustData
8453 * Gets all custom data items for the Functions
8456 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
8457 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
8459 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8460 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
8462 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
8464 if(indexFunc >= This->typeattr.cFuncs)
8465 return TYPE_E_ELEMENTNOTFOUND;
8467 if(indexParam >= pFDesc->funcdesc.cParams)
8468 return TYPE_E_ELEMENTNOTFOUND;
8470 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
8473 /* ITypeInfo2::GetAllVarCustData
8475 * Gets all custom data items for the specified Variable
8478 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
8479 UINT index, CUSTDATA *pCustData)
8481 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8482 TLBVarDesc * pVDesc = &This->vardescs[index];
8484 TRACE("%p %u %p\n", This, index, pCustData);
8486 if(index >= This->typeattr.cVars)
8487 return TYPE_E_ELEMENTNOTFOUND;
8489 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
8492 /* ITypeInfo2::GetAllImplCustData
8494 * Gets all custom data items for the specified implementation type
8497 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
8498 ITypeInfo2 * iface,
8499 UINT index,
8500 CUSTDATA *pCustData)
8502 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
8503 TLBImplType *pRDesc = &This->impltypes[index];
8505 TRACE("%p %u %p\n", This, index, pCustData);
8507 if(index >= This->typeattr.cImplTypes)
8508 return TYPE_E_ELEMENTNOTFOUND;
8510 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
8513 static const ITypeInfo2Vtbl tinfvt =
8516 ITypeInfo_fnQueryInterface,
8517 ITypeInfo_fnAddRef,
8518 ITypeInfo_fnRelease,
8520 ITypeInfo_fnGetTypeAttr,
8521 ITypeInfo_fnGetTypeComp,
8522 ITypeInfo_fnGetFuncDesc,
8523 ITypeInfo_fnGetVarDesc,
8524 ITypeInfo_fnGetNames,
8525 ITypeInfo_fnGetRefTypeOfImplType,
8526 ITypeInfo_fnGetImplTypeFlags,
8527 ITypeInfo_fnGetIDsOfNames,
8528 ITypeInfo_fnInvoke,
8529 ITypeInfo_fnGetDocumentation,
8530 ITypeInfo_fnGetDllEntry,
8531 ITypeInfo_fnGetRefTypeInfo,
8532 ITypeInfo_fnAddressOfMember,
8533 ITypeInfo_fnCreateInstance,
8534 ITypeInfo_fnGetMops,
8535 ITypeInfo_fnGetContainingTypeLib,
8536 ITypeInfo_fnReleaseTypeAttr,
8537 ITypeInfo_fnReleaseFuncDesc,
8538 ITypeInfo_fnReleaseVarDesc,
8540 ITypeInfo2_fnGetTypeKind,
8541 ITypeInfo2_fnGetTypeFlags,
8542 ITypeInfo2_fnGetFuncIndexOfMemId,
8543 ITypeInfo2_fnGetVarIndexOfMemId,
8544 ITypeInfo2_fnGetCustData,
8545 ITypeInfo2_fnGetFuncCustData,
8546 ITypeInfo2_fnGetParamCustData,
8547 ITypeInfo2_fnGetVarCustData,
8548 ITypeInfo2_fnGetImplTypeCustData,
8549 ITypeInfo2_fnGetDocumentation2,
8550 ITypeInfo2_fnGetAllCustData,
8551 ITypeInfo2_fnGetAllFuncCustData,
8552 ITypeInfo2_fnGetAllParamCustData,
8553 ITypeInfo2_fnGetAllVarCustData,
8554 ITypeInfo2_fnGetAllImplTypeCustData,
8557 /******************************************************************************
8558 * CreateDispTypeInfo [OLEAUT32.31]
8560 * Build type information for an object so it can be called through an
8561 * IDispatch interface.
8563 * RETURNS
8564 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8565 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8567 * NOTES
8568 * This call allows an objects methods to be accessed through IDispatch, by
8569 * building an ITypeInfo object that IDispatch can use to call through.
8571 HRESULT WINAPI CreateDispTypeInfo(
8572 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
8573 LCID lcid, /* [I] Locale Id */
8574 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
8576 ITypeInfoImpl *pTIClass, *pTIIface;
8577 ITypeLibImpl *pTypeLibImpl;
8578 unsigned int param, func;
8579 TLBFuncDesc *pFuncDesc;
8580 TLBRefType *ref;
8582 TRACE("\n");
8583 pTypeLibImpl = TypeLibImpl_Constructor();
8584 if (!pTypeLibImpl) return E_FAIL;
8586 pTypeLibImpl->TypeInfoCount = 2;
8587 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
8589 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
8590 pTIIface->pTypeLib = pTypeLibImpl;
8591 pTIIface->index = 0;
8592 pTIIface->Name = NULL;
8593 pTIIface->dwHelpContext = -1;
8594 pTIIface->guid = NULL;
8595 pTIIface->typeattr.lcid = lcid;
8596 pTIIface->typeattr.typekind = TKIND_INTERFACE;
8597 pTIIface->typeattr.wMajorVerNum = 0;
8598 pTIIface->typeattr.wMinorVerNum = 0;
8599 pTIIface->typeattr.cbAlignment = 2;
8600 pTIIface->typeattr.cbSizeInstance = -1;
8601 pTIIface->typeattr.cbSizeVft = -1;
8602 pTIIface->typeattr.cFuncs = 0;
8603 pTIIface->typeattr.cImplTypes = 0;
8604 pTIIface->typeattr.cVars = 0;
8605 pTIIface->typeattr.wTypeFlags = 0;
8606 pTIIface->hreftype = 0;
8608 pTIIface->funcdescs = TLBFuncDesc_Alloc(pidata->cMembers);
8609 pFuncDesc = pTIIface->funcdescs;
8610 for(func = 0; func < pidata->cMembers; func++) {
8611 METHODDATA *md = pidata->pmethdata + func;
8612 pFuncDesc->Name = TLB_append_str(&pTypeLibImpl->name_list, md->szName);
8613 pFuncDesc->funcdesc.memid = md->dispid;
8614 pFuncDesc->funcdesc.lprgscode = NULL;
8615 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
8616 pFuncDesc->funcdesc.invkind = md->wFlags;
8617 pFuncDesc->funcdesc.callconv = md->cc;
8618 pFuncDesc->funcdesc.cParams = md->cArgs;
8619 pFuncDesc->funcdesc.cParamsOpt = 0;
8620 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
8621 pFuncDesc->funcdesc.cScodes = 0;
8622 pFuncDesc->funcdesc.wFuncFlags = 0;
8623 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
8624 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
8625 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
8626 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
8627 md->cArgs * sizeof(ELEMDESC));
8628 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
8629 for(param = 0; param < md->cArgs; param++) {
8630 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
8631 pFuncDesc->pParamDesc[param].Name = TLB_append_str(&pTypeLibImpl->name_list, md->ppdata[param].szName);
8633 pFuncDesc->helpcontext = 0;
8634 pFuncDesc->HelpStringContext = 0;
8635 pFuncDesc->HelpString = NULL;
8636 pFuncDesc->Entry = NULL;
8637 list_init(&pFuncDesc->custdata_list);
8638 pTIIface->typeattr.cFuncs++;
8639 ++pFuncDesc;
8642 dump_TypeInfo(pTIIface);
8644 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
8645 pTIClass->pTypeLib = pTypeLibImpl;
8646 pTIClass->index = 1;
8647 pTIClass->Name = NULL;
8648 pTIClass->dwHelpContext = -1;
8649 pTIClass->guid = NULL;
8650 pTIClass->typeattr.lcid = lcid;
8651 pTIClass->typeattr.typekind = TKIND_COCLASS;
8652 pTIClass->typeattr.wMajorVerNum = 0;
8653 pTIClass->typeattr.wMinorVerNum = 0;
8654 pTIClass->typeattr.cbAlignment = 2;
8655 pTIClass->typeattr.cbSizeInstance = -1;
8656 pTIClass->typeattr.cbSizeVft = -1;
8657 pTIClass->typeattr.cFuncs = 0;
8658 pTIClass->typeattr.cImplTypes = 1;
8659 pTIClass->typeattr.cVars = 0;
8660 pTIClass->typeattr.wTypeFlags = 0;
8661 pTIClass->hreftype = sizeof(MSFT_TypeInfoBase);
8663 pTIClass->impltypes = TLBImplType_Alloc(1);
8665 ref = heap_alloc_zero(sizeof(*ref));
8666 ref->pImpTLInfo = TLB_REF_INTERNAL;
8667 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
8669 dump_TypeInfo(pTIClass);
8671 *pptinfo = (ITypeInfo *)&pTIClass->ITypeInfo2_iface;
8673 ITypeInfo_AddRef(*pptinfo);
8674 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
8676 return S_OK;
8680 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
8682 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8684 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, ppv);
8687 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
8689 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8691 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
8694 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
8696 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8698 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
8701 static HRESULT WINAPI ITypeComp_fnBind(
8702 ITypeComp * iface,
8703 OLECHAR * szName,
8704 ULONG lHash,
8705 WORD wFlags,
8706 ITypeInfo ** ppTInfo,
8707 DESCKIND * pDescKind,
8708 BINDPTR * pBindPtr)
8710 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
8711 const TLBFuncDesc *pFDesc;
8712 const TLBVarDesc *pVDesc;
8713 HRESULT hr = DISP_E_MEMBERNOTFOUND;
8714 UINT fdc;
8716 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8718 *pDescKind = DESCKIND_NONE;
8719 pBindPtr->lpfuncdesc = NULL;
8720 *ppTInfo = NULL;
8722 for(fdc = 0; fdc < This->typeattr.cFuncs; ++fdc){
8723 pFDesc = &This->funcdescs[fdc];
8724 if (!lstrcmpiW(TLB_get_bstr(pFDesc->Name), szName)) {
8725 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
8726 break;
8727 else
8728 /* name found, but wrong flags */
8729 hr = TYPE_E_TYPEMISMATCH;
8733 if (fdc < This->typeattr.cFuncs)
8735 HRESULT hr = TLB_AllocAndInitFuncDesc(
8736 &pFDesc->funcdesc,
8737 &pBindPtr->lpfuncdesc,
8738 This->typeattr.typekind == TKIND_DISPATCH);
8739 if (FAILED(hr))
8740 return hr;
8741 *pDescKind = DESCKIND_FUNCDESC;
8742 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8743 ITypeInfo_AddRef(*ppTInfo);
8744 return S_OK;
8745 } else {
8746 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->typeattr.cVars, szName);
8747 if(pVDesc){
8748 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
8749 if (FAILED(hr))
8750 return hr;
8751 *pDescKind = DESCKIND_VARDESC;
8752 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
8753 ITypeInfo_AddRef(*ppTInfo);
8754 return S_OK;
8758 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
8759 /* recursive search */
8760 ITypeInfo *pTInfo;
8761 ITypeComp *pTComp;
8762 HRESULT hr;
8763 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
8764 if (SUCCEEDED(hr))
8766 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
8767 ITypeInfo_Release(pTInfo);
8769 if (SUCCEEDED(hr))
8771 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
8772 ITypeComp_Release(pTComp);
8773 if (SUCCEEDED(hr) && *pDescKind == DESCKIND_FUNCDESC &&
8774 This->typeattr.typekind == TKIND_DISPATCH)
8776 FUNCDESC *tmp = pBindPtr->lpfuncdesc;
8777 hr = TLB_AllocAndInitFuncDesc(tmp, &pBindPtr->lpfuncdesc, TRUE);
8778 SysFreeString((BSTR)tmp);
8780 return hr;
8782 WARN("Could not search inherited interface!\n");
8784 if (hr == DISP_E_MEMBERNOTFOUND)
8785 hr = S_OK;
8786 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
8787 return hr;
8790 static HRESULT WINAPI ITypeComp_fnBindType(
8791 ITypeComp * iface,
8792 OLECHAR * szName,
8793 ULONG lHash,
8794 ITypeInfo ** ppTInfo,
8795 ITypeComp ** ppTComp)
8797 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8799 /* strange behaviour (does nothing) but like the
8800 * original */
8802 if (!ppTInfo || !ppTComp)
8803 return E_POINTER;
8805 *ppTInfo = NULL;
8806 *ppTComp = NULL;
8808 return S_OK;
8811 static const ITypeCompVtbl tcompvt =
8814 ITypeComp_fnQueryInterface,
8815 ITypeComp_fnAddRef,
8816 ITypeComp_fnRelease,
8818 ITypeComp_fnBind,
8819 ITypeComp_fnBindType
8822 HRESULT WINAPI CreateTypeLib2(SYSKIND syskind, LPCOLESTR szFile,
8823 ICreateTypeLib2** ppctlib)
8825 ITypeLibImpl *This;
8826 HRESULT hres;
8828 TRACE("(%d,%s,%p)\n", syskind, debugstr_w(szFile), ppctlib);
8830 if (!szFile) return E_INVALIDARG;
8832 This = TypeLibImpl_Constructor();
8833 if (!This)
8834 return E_OUTOFMEMORY;
8836 This->lcid = GetSystemDefaultLCID();
8837 This->syskind = syskind;
8838 This->ptr_size = get_ptr_size(syskind);
8840 This->path = heap_alloc((lstrlenW(szFile) + 1) * sizeof(WCHAR));
8841 if (!This->path) {
8842 ITypeLib2_Release(&This->ITypeLib2_iface);
8843 return E_OUTOFMEMORY;
8845 lstrcpyW(This->path, szFile);
8847 hres = ITypeLib2_QueryInterface(&This->ITypeLib2_iface, &IID_ICreateTypeLib2, (LPVOID*)ppctlib);
8848 ITypeLib2_Release(&This->ITypeLib2_iface);
8849 return hres;
8852 static HRESULT WINAPI ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2 *iface,
8853 REFIID riid, void **object)
8855 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8857 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, object);
8860 static ULONG WINAPI ICreateTypeLib2_fnAddRef(ICreateTypeLib2 *iface)
8862 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8864 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
8867 static ULONG WINAPI ICreateTypeLib2_fnRelease(ICreateTypeLib2 *iface)
8869 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8871 return ITypeLib2_Release(&This->ITypeLib2_iface);
8874 static HRESULT WINAPI ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2 *iface,
8875 LPOLESTR name, TYPEKIND kind, ICreateTypeInfo **ctinfo)
8877 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8878 ITypeInfoImpl *info;
8879 HRESULT hres;
8881 TRACE("%p %s %d %p\n", This, wine_dbgstr_w(name), kind, ctinfo);
8883 if (!ctinfo || !name)
8884 return E_INVALIDARG;
8886 info = TLB_get_typeinfo_by_name(This->typeinfos, This->TypeInfoCount, name);
8887 if (info)
8888 return TYPE_E_NAMECONFLICT;
8890 if (This->typeinfos)
8891 This->typeinfos = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->typeinfos,
8892 sizeof(ITypeInfoImpl*) * (This->TypeInfoCount + 1));
8893 else
8894 This->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*));
8896 info = This->typeinfos[This->TypeInfoCount] = ITypeInfoImpl_Constructor();
8898 info->pTypeLib = This;
8899 info->Name = TLB_append_str(&This->name_list, name);
8900 info->index = This->TypeInfoCount;
8901 info->typeattr.typekind = kind;
8902 info->typeattr.cbAlignment = 4;
8904 switch (info->typeattr.typekind) {
8905 case TKIND_ENUM:
8906 case TKIND_INTERFACE:
8907 case TKIND_DISPATCH:
8908 case TKIND_COCLASS:
8909 info->typeattr.cbSizeInstance = This->ptr_size;
8910 break;
8911 case TKIND_RECORD:
8912 case TKIND_UNION:
8913 info->typeattr.cbSizeInstance = 0;
8914 break;
8915 case TKIND_MODULE:
8916 info->typeattr.cbSizeInstance = 2;
8917 break;
8918 case TKIND_ALIAS:
8919 info->typeattr.cbSizeInstance = -0x75;
8920 break;
8921 default:
8922 FIXME("unrecognized typekind %d\n", info->typeattr.typekind);
8923 info->typeattr.cbSizeInstance = 0xdeadbeef;
8924 break;
8927 hres = ITypeInfo2_QueryInterface(&info->ITypeInfo2_iface,
8928 &IID_ICreateTypeInfo, (void **)ctinfo);
8929 if (FAILED(hres)) {
8930 ITypeInfo2_Release(&info->ITypeInfo2_iface);
8931 return hres;
8934 info->hreftype = info->index * sizeof(MSFT_TypeInfoBase);
8936 ++This->TypeInfoCount;
8938 return S_OK;
8941 static HRESULT WINAPI ICreateTypeLib2_fnSetName(ICreateTypeLib2 *iface,
8942 LPOLESTR name)
8944 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8946 TRACE("%p %s\n", This, wine_dbgstr_w(name));
8948 if (!name)
8949 return E_INVALIDARG;
8951 This->Name = TLB_append_str(&This->name_list, name);
8953 return S_OK;
8956 static HRESULT WINAPI ICreateTypeLib2_fnSetVersion(ICreateTypeLib2 *iface,
8957 WORD majorVerNum, WORD minorVerNum)
8959 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8961 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
8963 This->ver_major = majorVerNum;
8964 This->ver_minor = minorVerNum;
8966 return S_OK;
8969 static HRESULT WINAPI ICreateTypeLib2_fnSetGuid(ICreateTypeLib2 *iface,
8970 REFGUID guid)
8972 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8974 TRACE("%p %s\n", This, debugstr_guid(guid));
8976 This->guid = TLB_append_guid(&This->guid_list, guid, -2);
8978 return S_OK;
8981 static HRESULT WINAPI ICreateTypeLib2_fnSetDocString(ICreateTypeLib2 *iface,
8982 LPOLESTR doc)
8984 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
8986 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
8988 if (!doc)
8989 return E_INVALIDARG;
8991 This->DocString = TLB_append_str(&This->string_list, doc);
8993 return S_OK;
8996 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2 *iface,
8997 LPOLESTR helpFileName)
8999 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9001 TRACE("%p %s\n", This, wine_dbgstr_w(helpFileName));
9003 if (!helpFileName)
9004 return E_INVALIDARG;
9006 This->HelpFile = TLB_append_str(&This->string_list, helpFileName);
9008 return S_OK;
9011 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2 *iface,
9012 DWORD helpContext)
9014 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9016 TRACE("%p %d\n", This, helpContext);
9018 This->dwHelpContext = helpContext;
9020 return S_OK;
9023 static HRESULT WINAPI ICreateTypeLib2_fnSetLcid(ICreateTypeLib2 *iface,
9024 LCID lcid)
9026 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9028 TRACE("%p %x\n", This, lcid);
9030 This->set_lcid = lcid;
9032 return S_OK;
9035 static HRESULT WINAPI ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2 *iface,
9036 UINT libFlags)
9038 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
9040 TRACE("%p %x\n", This, libFlags);
9042 This->libflags = libFlags;
9044 return S_OK;
9047 typedef struct tagWMSFT_SegContents {
9048 DWORD len;
9049 void *data;
9050 } WMSFT_SegContents;
9052 typedef struct tagWMSFT_TLBFile {
9053 MSFT_Header header;
9054 WMSFT_SegContents typeinfo_seg;
9055 WMSFT_SegContents impfile_seg;
9056 WMSFT_SegContents impinfo_seg;
9057 WMSFT_SegContents ref_seg;
9058 WMSFT_SegContents guidhash_seg;
9059 WMSFT_SegContents guid_seg;
9060 WMSFT_SegContents namehash_seg;
9061 WMSFT_SegContents name_seg;
9062 WMSFT_SegContents string_seg;
9063 WMSFT_SegContents typdesc_seg;
9064 WMSFT_SegContents arraydesc_seg;
9065 WMSFT_SegContents custdata_seg;
9066 WMSFT_SegContents cdguids_seg;
9067 MSFT_SegDir segdir;
9068 WMSFT_SegContents aux_seg;
9069 } WMSFT_TLBFile;
9071 static HRESULT WMSFT_compile_strings(ITypeLibImpl *This,
9072 WMSFT_TLBFile *file)
9074 TLBString *str;
9075 UINT last_offs;
9076 char *data;
9078 file->string_seg.len = 0;
9079 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9080 int size;
9082 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str), NULL, 0, NULL, NULL);
9083 if (size == 0)
9084 return E_UNEXPECTED;
9086 size += sizeof(INT16);
9087 if (size % 4)
9088 size = (size + 4) & ~0x3;
9089 if (size < 8)
9090 size = 8;
9092 file->string_seg.len += size;
9094 /* temporarily use str->offset to store the length of the aligned,
9095 * converted string */
9096 str->offset = size;
9099 file->string_seg.data = data = heap_alloc(file->string_seg.len);
9101 last_offs = 0;
9102 LIST_FOR_EACH_ENTRY(str, &This->string_list, TLBString, entry) {
9103 int size;
9105 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9106 data + sizeof(INT16), file->string_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9107 if (size == 0) {
9108 heap_free(file->string_seg.data);
9109 return E_UNEXPECTED;
9112 *((INT16*)data) = size;
9114 memset(data + sizeof(INT16) + size, 0x57, str->offset - size - sizeof(INT16));
9116 size = str->offset;
9117 data += size;
9118 str->offset = last_offs;
9119 last_offs += size;
9122 return S_OK;
9125 static HRESULT WMSFT_compile_names(ITypeLibImpl *This,
9126 WMSFT_TLBFile *file)
9128 TLBString *str;
9129 UINT last_offs;
9130 char *data;
9131 MSFT_NameIntro *last_intro = NULL;
9133 file->header.nametablecount = 0;
9134 file->header.nametablechars = 0;
9136 file->name_seg.len = 0;
9137 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9138 int size;
9140 size = strlenW(str->str);
9141 file->header.nametablechars += size;
9142 file->header.nametablecount++;
9144 size = WideCharToMultiByte(CP_ACP, 0, str->str, size, NULL, 0, NULL, NULL);
9145 if (size == 0)
9146 return E_UNEXPECTED;
9148 size += sizeof(MSFT_NameIntro);
9149 if (size % 4)
9150 size = (size + 4) & ~0x3;
9151 if (size < 8)
9152 size = 8;
9154 file->name_seg.len += size;
9156 /* temporarily use str->offset to store the length of the aligned,
9157 * converted string */
9158 str->offset = size;
9161 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9162 file->name_seg.data = data = heap_alloc(file->name_seg.len+1);
9164 last_offs = 0;
9165 LIST_FOR_EACH_ENTRY(str, &This->name_list, TLBString, entry) {
9166 int size, hash;
9167 MSFT_NameIntro *intro = (MSFT_NameIntro*)data;
9169 size = WideCharToMultiByte(CP_ACP, 0, str->str, strlenW(str->str),
9170 data + sizeof(MSFT_NameIntro),
9171 file->name_seg.len - last_offs - sizeof(MSFT_NameIntro), NULL, NULL);
9172 if (size == 0) {
9173 heap_free(file->name_seg.data);
9174 return E_UNEXPECTED;
9176 data[sizeof(MSFT_NameIntro) + size] = '\0';
9178 intro->hreftype = -1; /* TODO? */
9179 intro->namelen = size & 0xFF;
9180 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9181 hash = LHashValOfNameSysA(This->syskind, This->lcid, data + sizeof(MSFT_NameIntro));
9182 intro->namelen |= hash << 16;
9183 intro->next_hash = ((DWORD*)file->namehash_seg.data)[hash & 0x7f];
9184 ((DWORD*)file->namehash_seg.data)[hash & 0x7f] = last_offs;
9186 memset(data + sizeof(MSFT_NameIntro) + size, 0x57,
9187 str->offset - size - sizeof(MSFT_NameIntro));
9189 /* update str->offset to actual value to use in other
9190 * compilation functions that require positions within
9191 * the string table */
9192 last_intro = intro;
9193 size = str->offset;
9194 data += size;
9195 str->offset = last_offs;
9196 last_offs += size;
9199 if(last_intro)
9200 last_intro->hreftype = 0; /* last one is 0? */
9202 return S_OK;
9205 static inline int hash_guid(GUID *guid)
9207 int i, hash = 0;
9209 for (i = 0; i < 8; i ++)
9210 hash ^= ((const short *)guid)[i];
9212 return hash & 0x1f;
9215 static HRESULT WMSFT_compile_guids(ITypeLibImpl *This, WMSFT_TLBFile *file)
9217 TLBGuid *guid;
9218 MSFT_GuidEntry *entry;
9219 DWORD offs;
9220 int hash_key, *guidhashtab;
9222 file->guid_seg.len = sizeof(MSFT_GuidEntry) * list_count(&This->guid_list);
9223 file->guid_seg.data = heap_alloc(file->guid_seg.len);
9225 entry = file->guid_seg.data;
9226 offs = 0;
9227 guidhashtab = file->guidhash_seg.data;
9228 LIST_FOR_EACH_ENTRY(guid, &This->guid_list, TLBGuid, entry){
9229 memcpy(&entry->guid, &guid->guid, sizeof(GUID));
9230 entry->hreftype = guid->hreftype;
9232 hash_key = hash_guid(&guid->guid);
9233 entry->next_hash = guidhashtab[hash_key];
9234 guidhashtab[hash_key] = offs;
9236 guid->offset = offs;
9237 offs += sizeof(MSFT_GuidEntry);
9238 ++entry;
9241 return S_OK;
9244 static DWORD WMSFT_encode_variant(VARIANT *value, WMSFT_TLBFile *file)
9246 VARIANT v = *value;
9247 VARTYPE arg_type = V_VT(value);
9248 int mask = 0;
9249 HRESULT hres;
9250 DWORD ret = file->custdata_seg.len;
9252 if(arg_type == VT_INT)
9253 arg_type = VT_I4;
9254 if(arg_type == VT_UINT)
9255 arg_type = VT_UI4;
9257 v = *value;
9258 if(V_VT(value) != arg_type) {
9259 hres = VariantChangeType(&v, value, 0, arg_type);
9260 if(FAILED(hres)){
9261 ERR("VariantChangeType failed: %08x\n", hres);
9262 return -1;
9266 /* Check if default value can be stored in-place */
9267 switch(arg_type){
9268 case VT_I4:
9269 case VT_UI4:
9270 mask = 0x3ffffff;
9271 if(V_UI4(&v) > 0x3ffffff)
9272 break;
9273 /* fall through */
9274 case VT_I1:
9275 case VT_UI1:
9276 case VT_BOOL:
9277 if(!mask)
9278 mask = 0xff;
9279 /* fall through */
9280 case VT_I2:
9281 case VT_UI2:
9282 if(!mask)
9283 mask = 0xffff;
9284 return ((0x80 + 0x4 * V_VT(value)) << 24) | (V_UI4(&v) & mask);
9287 /* have to allocate space in custdata_seg */
9288 switch(arg_type) {
9289 case VT_I4:
9290 case VT_R4:
9291 case VT_UI4:
9292 case VT_INT:
9293 case VT_UINT:
9294 case VT_HRESULT:
9295 case VT_PTR: {
9296 /* Construct the data to be allocated */
9297 int *data;
9299 if(file->custdata_seg.data){
9300 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + sizeof(int) * 2);
9301 data = (int *)(((char *)file->custdata_seg.data) + file->custdata_seg.len);
9302 file->custdata_seg.len += sizeof(int) * 2;
9303 }else{
9304 file->custdata_seg.len = sizeof(int) * 2;
9305 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9308 data[0] = V_VT(value) + (V_UI4(&v) << 16);
9309 data[1] = (V_UI4(&v) >> 16) + 0x57570000;
9311 /* TODO: Check if the encoded data is already present in custdata_seg */
9313 return ret;
9316 case VT_BSTR: {
9317 int i, len = (6+SysStringLen(V_BSTR(&v))+3) & ~0x3;
9318 char *data;
9320 if(file->custdata_seg.data){
9321 file->custdata_seg.data = heap_realloc(file->custdata_seg.data, file->custdata_seg.len + len);
9322 data = ((char *)file->custdata_seg.data) + file->custdata_seg.len;
9323 file->custdata_seg.len += len;
9324 }else{
9325 file->custdata_seg.len = len;
9326 data = file->custdata_seg.data = heap_alloc(file->custdata_seg.len);
9329 *((unsigned short *)data) = V_VT(value);
9330 *((unsigned int *)(data+2)) = SysStringLen(V_BSTR(&v));
9331 for(i=0; i<SysStringLen(V_BSTR(&v)); i++) {
9332 if(V_BSTR(&v)[i] <= 0x7f)
9333 data[i+6] = V_BSTR(&v)[i];
9334 else
9335 data[i+6] = '?';
9337 WideCharToMultiByte(CP_ACP, 0, V_BSTR(&v), SysStringLen(V_BSTR(&v)), &data[6], len-6, NULL, NULL);
9338 for(i=6+SysStringLen(V_BSTR(&v)); i<len; i++)
9339 data[i] = 0x57;
9341 /* TODO: Check if the encoded data is already present in custdata_seg */
9343 return ret;
9345 default:
9346 FIXME("Argument type not yet handled\n");
9347 return -1;
9351 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size);
9353 static DWORD WMSFT_append_arraydesc(ARRAYDESC *desc, WMSFT_TLBFile *file)
9355 DWORD offs = file->arraydesc_seg.len;
9356 DWORD *encoded;
9357 USHORT i;
9359 /* TODO: we should check for duplicates, but that's harder because each
9360 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9361 * at the library-level) */
9363 file->arraydesc_seg.len += (2 + desc->cDims * 2) * sizeof(DWORD);
9364 if(!file->arraydesc_seg.data)
9365 file->arraydesc_seg.data = heap_alloc(file->arraydesc_seg.len);
9366 else
9367 file->arraydesc_seg.data = heap_realloc(file->arraydesc_seg.data, file->arraydesc_seg.len);
9368 encoded = (DWORD*)((char *)file->arraydesc_seg.data + offs);
9370 encoded[0] = WMSFT_append_typedesc(&desc->tdescElem, file, NULL, NULL);
9371 encoded[1] = desc->cDims | ((desc->cDims * 2 * sizeof(DWORD)) << 16);
9372 for(i = 0; i < desc->cDims; ++i){
9373 encoded[2 + i * 2] = desc->rgbounds[i].cElements;
9374 encoded[2 + i * 2 + 1] = desc->rgbounds[i].lLbound;
9377 return offs;
9380 static DWORD WMSFT_append_typedesc(TYPEDESC *desc, WMSFT_TLBFile *file, DWORD *out_mix, INT16 *out_size)
9382 DWORD junk;
9383 INT16 junk2;
9384 DWORD offs = 0;
9385 DWORD encoded[2];
9386 VARTYPE vt, subtype;
9387 char *data;
9389 if(!desc)
9390 return -1;
9392 if(!out_mix)
9393 out_mix = &junk;
9394 if(!out_size)
9395 out_size = &junk2;
9397 vt = desc->vt & VT_TYPEMASK;
9399 if(vt == VT_PTR || vt == VT_SAFEARRAY){
9400 DWORD mix;
9401 encoded[1] = WMSFT_append_typedesc(desc->u.lptdesc, file, &mix, out_size);
9402 encoded[0] = desc->vt | ((mix | VT_BYREF) << 16);
9403 *out_mix = 0x7FFF;
9404 *out_size += 2 * sizeof(DWORD);
9405 }else if(vt == VT_CARRAY){
9406 encoded[0] = desc->vt | (0x7FFE << 16);
9407 encoded[1] = WMSFT_append_arraydesc(desc->u.lpadesc, file);
9408 *out_mix = 0x7FFE;
9409 }else if(vt == VT_USERDEFINED){
9410 encoded[0] = desc->vt | (0x7FFF << 16);
9411 encoded[1] = desc->u.hreftype;
9412 *out_mix = 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9413 }else{
9414 TRACE("Mixing in-place, VT: 0x%x\n", desc->vt);
9416 switch(vt){
9417 case VT_INT:
9418 subtype = VT_I4;
9419 break;
9420 case VT_UINT:
9421 subtype = VT_UI4;
9422 break;
9423 case VT_VOID:
9424 subtype = VT_EMPTY;
9425 break;
9426 default:
9427 subtype = vt;
9428 break;
9431 *out_mix = subtype;
9432 return 0x80000000 | (subtype << 16) | desc->vt;
9435 data = file->typdesc_seg.data;
9436 while(offs < file->typdesc_seg.len){
9437 if(!memcmp(&data[offs], encoded, sizeof(encoded)))
9438 return offs;
9439 offs += sizeof(encoded);
9442 file->typdesc_seg.len += sizeof(encoded);
9443 if(!file->typdesc_seg.data)
9444 data = file->typdesc_seg.data = heap_alloc(file->typdesc_seg.len);
9445 else
9446 data = file->typdesc_seg.data = heap_realloc(file->typdesc_seg.data, file->typdesc_seg.len);
9448 memcpy(&data[offs], encoded, sizeof(encoded));
9450 return offs;
9453 static DWORD WMSFT_compile_custdata(struct list *custdata_list, WMSFT_TLBFile *file)
9455 WMSFT_SegContents *cdguids_seg = &file->cdguids_seg;
9456 DWORD ret = cdguids_seg->len, offs;
9457 MSFT_CDGuid *cdguid;
9458 TLBCustData *cd;
9460 if(list_empty(custdata_list))
9461 return -1;
9463 cdguids_seg->len += sizeof(MSFT_CDGuid) * list_count(custdata_list);
9464 if(!cdguids_seg->data){
9465 cdguid = cdguids_seg->data = heap_alloc(cdguids_seg->len);
9466 }else {
9467 cdguids_seg->data = heap_realloc(cdguids_seg->data, cdguids_seg->len);
9468 cdguid = (MSFT_CDGuid*)((char*)cdguids_seg->data + ret);
9471 offs = ret + sizeof(MSFT_CDGuid);
9472 LIST_FOR_EACH_ENTRY(cd, custdata_list, TLBCustData, entry){
9473 cdguid->GuidOffset = cd->guid->offset;
9474 cdguid->DataOffset = WMSFT_encode_variant(&cd->data, file);
9475 cdguid->next = offs;
9476 offs += sizeof(MSFT_CDGuid);
9477 ++cdguid;
9480 --cdguid;
9481 cdguid->next = -1;
9483 return ret;
9486 static DWORD WMSFT_compile_typeinfo_aux(ITypeInfoImpl *info,
9487 WMSFT_TLBFile *file)
9489 WMSFT_SegContents *aux_seg = &file->aux_seg;
9490 DWORD ret = aux_seg->len, i, j, recorded_size = 0, extra_size = 0;
9491 MSFT_VarRecord *varrecord;
9492 MSFT_FuncRecord *funcrecord;
9493 MEMBERID *memid;
9494 DWORD *name, *offsets, offs;
9496 for(i = 0; i < info->typeattr.cFuncs; ++i){
9497 TLBFuncDesc *desc = &info->funcdescs[i];
9499 recorded_size += 6 * sizeof(INT); /* mandatory fields */
9501 /* optional fields */
9502 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9503 if(!list_empty(&desc->custdata_list))
9504 recorded_size += 7 * sizeof(INT);
9505 else if(desc->HelpStringContext != 0)
9506 recorded_size += 6 * sizeof(INT);
9507 /* res9? resA? */
9508 else if(desc->Entry)
9509 recorded_size += 3 * sizeof(INT);
9510 else if(desc->HelpString)
9511 recorded_size += 2 * sizeof(INT);
9512 else if(desc->helpcontext)
9513 recorded_size += sizeof(INT);
9515 recorded_size += desc->funcdesc.cParams * sizeof(MSFT_ParameterInfo);
9517 for(j = 0; j < desc->funcdesc.cParams; ++j){
9518 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9519 recorded_size += desc->funcdesc.cParams * sizeof(INT);
9520 break;
9524 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9527 for(i = 0; i < info->typeattr.cVars; ++i){
9528 TLBVarDesc *desc = &info->vardescs[i];
9530 recorded_size += 5 * sizeof(INT); /* mandatory fields */
9532 /* optional fields */
9533 if(desc->HelpStringContext != 0)
9534 recorded_size += 5 * sizeof(INT);
9535 else if(!list_empty(&desc->custdata_list))
9536 recorded_size += 4 * sizeof(INT);
9537 /* res9? */
9538 else if(desc->HelpString)
9539 recorded_size += 2 * sizeof(INT);
9540 else if(desc->HelpContext != 0)
9541 recorded_size += sizeof(INT);
9543 extra_size += 2 * sizeof(INT); /* memberid, name offs */
9546 if(!recorded_size && !extra_size)
9547 return ret;
9549 extra_size += sizeof(INT); /* total aux size for this typeinfo */
9551 aux_seg->len += recorded_size + extra_size;
9553 aux_seg->len += sizeof(INT) * (info->typeattr.cVars + info->typeattr.cFuncs); /* offsets at the end */
9555 if(aux_seg->data)
9556 aux_seg->data = heap_realloc(aux_seg->data, aux_seg->len);
9557 else
9558 aux_seg->data = heap_alloc(aux_seg->len);
9560 *((DWORD*)((char *)aux_seg->data + ret)) = recorded_size;
9562 offsets = (DWORD*)((char *)aux_seg->data + ret + recorded_size + extra_size);
9563 offs = 0;
9565 funcrecord = (MSFT_FuncRecord*)(((char *)aux_seg->data) + ret + sizeof(INT));
9566 for(i = 0; i < info->typeattr.cFuncs; ++i){
9567 TLBFuncDesc *desc = &info->funcdescs[i];
9568 DWORD size = 6 * sizeof(INT), paramdefault_size = 0, *paramdefault;
9570 funcrecord->funcdescsize = sizeof(desc->funcdesc) + desc->funcdesc.cParams * sizeof(ELEMDESC);
9571 funcrecord->DataType = WMSFT_append_typedesc(&desc->funcdesc.elemdescFunc.tdesc, file, NULL, &funcrecord->funcdescsize);
9572 funcrecord->Flags = desc->funcdesc.wFuncFlags;
9573 funcrecord->VtableOffset = desc->funcdesc.oVft;
9575 /* FKCCIC:
9576 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9577 * ^^^funckind
9578 * ^^^ ^invkind
9579 * ^has_cust_data
9580 * ^^^^callconv
9581 * ^has_param_defaults
9582 * ^oEntry_is_intresource
9584 funcrecord->FKCCIC =
9585 desc->funcdesc.funckind |
9586 (desc->funcdesc.invkind << 3) |
9587 (list_empty(&desc->custdata_list) ? 0 : 0x80) |
9588 (desc->funcdesc.callconv << 8);
9590 if(desc->Entry && desc->Entry != (TLBString*)-1 && IS_INTRESOURCE(desc->Entry))
9591 funcrecord->FKCCIC |= 0x2000;
9593 for(j = 0; j < desc->funcdesc.cParams; ++j){
9594 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT){
9595 paramdefault_size = sizeof(INT) * desc->funcdesc.cParams;
9596 funcrecord->funcdescsize += sizeof(PARAMDESCEX);
9599 if(paramdefault_size > 0)
9600 funcrecord->FKCCIC |= 0x1000;
9602 funcrecord->nrargs = desc->funcdesc.cParams;
9603 funcrecord->nroargs = desc->funcdesc.cParamsOpt;
9605 /* optional fields */
9606 /* res9? resA? */
9607 if(!list_empty(&desc->custdata_list)){
9608 size += 7 * sizeof(INT);
9609 funcrecord->HelpContext = desc->helpcontext;
9610 if(desc->HelpString)
9611 funcrecord->oHelpString = desc->HelpString->offset;
9612 else
9613 funcrecord->oHelpString = -1;
9614 if(!desc->Entry)
9615 funcrecord->oEntry = -1;
9616 else if(IS_INTRESOURCE(desc->Entry))
9617 funcrecord->oEntry = LOWORD(desc->Entry);
9618 else
9619 funcrecord->oEntry = desc->Entry->offset;
9620 funcrecord->res9 = -1;
9621 funcrecord->resA = -1;
9622 funcrecord->HelpStringContext = desc->HelpStringContext;
9623 funcrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9624 }else if(desc->HelpStringContext != 0){
9625 size += 6 * sizeof(INT);
9626 funcrecord->HelpContext = desc->helpcontext;
9627 if(desc->HelpString)
9628 funcrecord->oHelpString = desc->HelpString->offset;
9629 else
9630 funcrecord->oHelpString = -1;
9631 if(!desc->Entry)
9632 funcrecord->oEntry = -1;
9633 else if(IS_INTRESOURCE(desc->Entry))
9634 funcrecord->oEntry = LOWORD(desc->Entry);
9635 else
9636 funcrecord->oEntry = desc->Entry->offset;
9637 funcrecord->res9 = -1;
9638 funcrecord->resA = -1;
9639 funcrecord->HelpStringContext = desc->HelpStringContext;
9640 }else if(desc->Entry){
9641 size += 3 * sizeof(INT);
9642 funcrecord->HelpContext = desc->helpcontext;
9643 if(desc->HelpString)
9644 funcrecord->oHelpString = desc->HelpString->offset;
9645 else
9646 funcrecord->oHelpString = -1;
9647 if(!desc->Entry)
9648 funcrecord->oEntry = -1;
9649 else if(IS_INTRESOURCE(desc->Entry))
9650 funcrecord->oEntry = LOWORD(desc->Entry);
9651 else
9652 funcrecord->oEntry = desc->Entry->offset;
9653 }else if(desc->HelpString){
9654 size += 2 * sizeof(INT);
9655 funcrecord->HelpContext = desc->helpcontext;
9656 funcrecord->oHelpString = desc->HelpString->offset;
9657 }else if(desc->helpcontext){
9658 size += sizeof(INT);
9659 funcrecord->HelpContext = desc->helpcontext;
9662 paramdefault = (DWORD*)((char *)funcrecord + size);
9663 size += paramdefault_size;
9665 for(j = 0; j < desc->funcdesc.cParams; ++j){
9666 MSFT_ParameterInfo *info = (MSFT_ParameterInfo*)(((char *)funcrecord) + size);
9668 info->DataType = WMSFT_append_typedesc(&desc->funcdesc.lprgelemdescParam[j].tdesc, file, NULL, &funcrecord->funcdescsize);
9669 if(desc->pParamDesc[j].Name)
9670 info->oName = desc->pParamDesc[j].Name->offset;
9671 else
9672 info->oName = -1;
9673 info->Flags = desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags;
9675 if(paramdefault_size){
9676 if(desc->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
9677 *paramdefault = WMSFT_encode_variant(&desc->funcdesc.lprgelemdescParam[j].u.paramdesc.pparamdescex->varDefaultValue, file);
9678 else if(paramdefault_size)
9679 *paramdefault = -1;
9680 ++paramdefault;
9683 size += sizeof(MSFT_ParameterInfo);
9686 funcrecord->Info = size | (i << 16); /* is it just the index? */
9688 *offsets = offs;
9689 offs += size;
9690 ++offsets;
9692 funcrecord = (MSFT_FuncRecord*)(((char*)funcrecord) + size);
9695 varrecord = (MSFT_VarRecord*)funcrecord;
9696 for(i = 0; i < info->typeattr.cVars; ++i){
9697 TLBVarDesc *desc = &info->vardescs[i];
9698 DWORD size = 5 * sizeof(INT);
9700 varrecord->vardescsize = sizeof(desc->vardesc);
9701 varrecord->DataType = WMSFT_append_typedesc(&desc->vardesc.elemdescVar.tdesc, file, NULL, &varrecord->vardescsize);
9702 varrecord->Flags = desc->vardesc.wVarFlags;
9703 varrecord->VarKind = desc->vardesc.varkind;
9705 if(desc->vardesc.varkind == VAR_CONST){
9706 varrecord->vardescsize += sizeof(VARIANT);
9707 varrecord->OffsValue = WMSFT_encode_variant(desc->vardesc.u.lpvarValue, file);
9708 }else
9709 varrecord->OffsValue = desc->vardesc.u.oInst;
9711 /* res9? */
9712 if(desc->HelpStringContext != 0){
9713 size += 5 * sizeof(INT);
9714 varrecord->HelpContext = desc->HelpContext;
9715 if(desc->HelpString)
9716 varrecord->HelpString = desc->HelpString->offset;
9717 else
9718 varrecord->HelpString = -1;
9719 varrecord->res9 = -1;
9720 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9721 varrecord->HelpStringContext = desc->HelpStringContext;
9722 }else if(!list_empty(&desc->custdata_list)){
9723 size += 4 * sizeof(INT);
9724 varrecord->HelpContext = desc->HelpContext;
9725 if(desc->HelpString)
9726 varrecord->HelpString = desc->HelpString->offset;
9727 else
9728 varrecord->HelpString = -1;
9729 varrecord->res9 = -1;
9730 varrecord->oCustData = WMSFT_compile_custdata(&desc->custdata_list, file);
9731 }else if(desc->HelpString){
9732 size += 2 * sizeof(INT);
9733 varrecord->HelpContext = desc->HelpContext;
9734 if(desc->HelpString)
9735 varrecord->HelpString = desc->HelpString->offset;
9736 else
9737 varrecord->HelpString = -1;
9738 }else if(desc->HelpContext != 0){
9739 size += sizeof(INT);
9740 varrecord->HelpContext = desc->HelpContext;
9743 varrecord->Info = size | (i << 16);
9745 *offsets = offs;
9746 offs += size;
9747 ++offsets;
9749 varrecord = (MSFT_VarRecord*)(((char*)varrecord) + size);
9752 memid = (MEMBERID*)varrecord;
9753 for(i = 0; i < info->typeattr.cFuncs; ++i){
9754 TLBFuncDesc *desc = &info->funcdescs[i];
9755 *memid = desc->funcdesc.memid;
9756 ++memid;
9758 for(i = 0; i < info->typeattr.cVars; ++i){
9759 TLBVarDesc *desc = &info->vardescs[i];
9760 *memid = desc->vardesc.memid;
9761 ++memid;
9764 name = (UINT*)memid;
9765 for(i = 0; i < info->typeattr.cFuncs; ++i){
9766 TLBFuncDesc *desc = &info->funcdescs[i];
9767 if(desc->Name)
9768 *name = desc->Name->offset;
9769 else
9770 *name = -1;
9771 ++name;
9773 for(i = 0; i < info->typeattr.cVars; ++i){
9774 TLBVarDesc *desc = &info->vardescs[i];
9775 if(desc->Name)
9776 *name = desc->Name->offset;
9777 else
9778 *name = -1;
9779 ++name;
9782 return ret;
9785 typedef struct tagWMSFT_RefChunk {
9786 DWORD href;
9787 DWORD res04;
9788 DWORD res08;
9789 DWORD next;
9790 } WMSFT_RefChunk;
9792 static DWORD WMSFT_compile_typeinfo_ref(ITypeInfoImpl *info, WMSFT_TLBFile *file)
9794 DWORD offs = file->ref_seg.len, i;
9795 WMSFT_RefChunk *chunk;
9797 file->ref_seg.len += info->typeattr.cImplTypes * sizeof(WMSFT_RefChunk);
9798 if(!file->ref_seg.data)
9799 file->ref_seg.data = heap_alloc(file->ref_seg.len);
9800 else
9801 file->ref_seg.data = heap_realloc(file->ref_seg.data, file->ref_seg.len);
9803 chunk = (WMSFT_RefChunk*)((char*)file->ref_seg.data + offs);
9805 for(i = 0; i < info->typeattr.cImplTypes; ++i){
9806 chunk->href = info->impltypes[i].hRef;
9807 chunk->res04 = info->impltypes[i].implflags;
9808 chunk->res08 = -1;
9809 if(i < info->typeattr.cImplTypes - 1)
9810 chunk->next = offs + sizeof(WMSFT_RefChunk) * (i + 1);
9811 else
9812 chunk->next = -1;
9813 ++chunk;
9816 return offs;
9819 static DWORD WMSFT_compile_typeinfo(ITypeInfoImpl *info, INT16 index, WMSFT_TLBFile *file, char *data)
9821 DWORD size;
9823 size = sizeof(MSFT_TypeInfoBase);
9825 if(data){
9826 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase*)data;
9827 if(info->typeattr.wTypeFlags & TYPEFLAG_FDUAL)
9828 base->typekind = TKIND_DISPATCH;
9829 else
9830 base->typekind = info->typeattr.typekind;
9831 base->typekind |= index << 16; /* TODO: There are some other flags here */
9832 base->typekind |= (info->typeattr.cbAlignment << 11) | (info->typeattr.cbAlignment << 6);
9833 base->memoffset = WMSFT_compile_typeinfo_aux(info, file);
9834 base->res2 = 0;
9835 base->res3 = 0;
9836 base->res4 = 3;
9837 base->res5 = 0;
9838 base->cElement = (info->typeattr.cVars << 16) | info->typeattr.cFuncs;
9839 base->res7 = 0;
9840 base->res8 = 0;
9841 base->res9 = 0;
9842 base->resA = 0;
9843 if(info->guid)
9844 base->posguid = info->guid->offset;
9845 else
9846 base->posguid = -1;
9847 base->flags = info->typeattr.wTypeFlags;
9848 if(info->Name) {
9849 base->NameOffset = info->Name->offset;
9851 ((unsigned char*)file->name_seg.data)[info->Name->offset+9] = 0x38;
9852 *(HREFTYPE*)((unsigned char*)file->name_seg.data+info->Name->offset) = info->hreftype;
9853 }else {
9854 base->NameOffset = -1;
9856 base->version = (info->typeattr.wMinorVerNum << 16) | info->typeattr.wMajorVerNum;
9857 if(info->DocString)
9858 base->docstringoffs = info->DocString->offset;
9859 else
9860 base->docstringoffs = -1;
9861 base->helpstringcontext = info->dwHelpStringContext;
9862 base->helpcontext = info->dwHelpContext;
9863 base->oCustData = WMSFT_compile_custdata(info->pcustdata_list, file);
9864 base->cImplTypes = info->typeattr.cImplTypes;
9865 base->cbSizeVft = info->typeattr.cbSizeVft;
9866 base->size = info->typeattr.cbSizeInstance;
9867 if(info->typeattr.typekind == TKIND_COCLASS){
9868 base->datatype1 = WMSFT_compile_typeinfo_ref(info, file);
9869 }else if(info->typeattr.typekind == TKIND_ALIAS){
9870 base->datatype1 = WMSFT_append_typedesc(info->tdescAlias, file, NULL, NULL);
9871 }else if(info->typeattr.typekind == TKIND_MODULE){
9872 if(info->DllName)
9873 base->datatype1 = info->DllName->offset;
9874 else
9875 base->datatype1 = -1;
9876 }else{
9877 if(info->typeattr.cImplTypes > 0)
9878 base->datatype1 = info->impltypes[0].hRef;
9879 else
9880 base->datatype1 = -1;
9882 base->datatype2 = index; /* FIXME: i think there's more here */
9883 base->res18 = 0;
9884 base->res19 = -1;
9887 return size;
9890 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl *This, WMSFT_TLBFile *file, DWORD *junk)
9892 UINT i;
9894 file->typeinfo_seg.len = 0;
9895 for(i = 0; i < This->TypeInfoCount; ++i){
9896 ITypeInfoImpl *info = This->typeinfos[i];
9897 *junk = file->typeinfo_seg.len;
9898 ++junk;
9899 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, NULL, NULL);
9902 file->typeinfo_seg.data = heap_alloc(file->typeinfo_seg.len);
9903 memset(file->typeinfo_seg.data, 0x96, file->typeinfo_seg.len);
9905 file->aux_seg.len = 0;
9906 file->aux_seg.data = NULL;
9908 file->typeinfo_seg.len = 0;
9909 for(i = 0; i < This->TypeInfoCount; ++i){
9910 ITypeInfoImpl *info = This->typeinfos[i];
9911 file->typeinfo_seg.len += WMSFT_compile_typeinfo(info, i, file,
9912 ((char *)file->typeinfo_seg.data) + file->typeinfo_seg.len);
9916 typedef struct tagWMSFT_ImpFile {
9917 INT guid_offs;
9918 LCID lcid;
9919 DWORD version;
9920 } WMSFT_ImpFile;
9922 static void WMSFT_compile_impfile(ITypeLibImpl *This, WMSFT_TLBFile *file)
9924 TLBImpLib *implib;
9925 WMSFT_ImpFile *impfile;
9926 char *data;
9927 DWORD last_offs = 0;
9929 file->impfile_seg.len = 0;
9930 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9931 int size = 0;
9933 if(implib->name){
9934 WCHAR *path = strrchrW(implib->name, '\\');
9935 if(path)
9936 ++path;
9937 else
9938 path = implib->name;
9939 size = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path), NULL, 0, NULL, NULL);
9940 if (size == 0)
9941 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9944 size += sizeof(INT16);
9945 if (size % 4)
9946 size = (size + 4) & ~0x3;
9947 if (size < 8)
9948 size = 8;
9950 file->impfile_seg.len += sizeof(WMSFT_ImpFile) + size;
9953 data = file->impfile_seg.data = heap_alloc(file->impfile_seg.len);
9955 LIST_FOR_EACH_ENTRY(implib, &This->implib_list, TLBImpLib, entry){
9956 int strlen = 0, size;
9958 impfile = (WMSFT_ImpFile*)data;
9959 impfile->guid_offs = implib->guid->offset;
9960 impfile->lcid = implib->lcid;
9961 impfile->version = (implib->wVersionMinor << 16) | implib->wVersionMajor;
9963 data += sizeof(WMSFT_ImpFile);
9965 if(implib->name){
9966 WCHAR *path= strrchrW(implib->name, '\\');
9967 if(path)
9968 ++path;
9969 else
9970 path = implib->name;
9971 strlen = WideCharToMultiByte(CP_ACP, 0, path, strlenW(path),
9972 data + sizeof(INT16), file->impfile_seg.len - last_offs - sizeof(INT16), NULL, NULL);
9973 if (strlen == 0)
9974 ERR("failed to convert wide string: %s\n", debugstr_w(path));
9977 *((INT16*)data) = (strlen << 2) | 1; /* FIXME: is that a flag, or what? */
9979 size = strlen + sizeof(INT16);
9980 if (size % 4)
9981 size = (size + 4) & ~0x3;
9982 if (size < 8)
9983 size = 8;
9984 memset(data + sizeof(INT16) + strlen, 0x57, size - strlen - sizeof(INT16));
9986 data += size;
9987 implib->offset = last_offs;
9988 last_offs += size + sizeof(WMSFT_ImpFile);
9992 static void WMSFT_compile_impinfo(ITypeLibImpl *This, WMSFT_TLBFile *file)
9994 MSFT_ImpInfo *info;
9995 TLBRefType *ref_type;
9996 UINT i = 0;
9998 WMSFT_compile_impfile(This, file);
10000 file->impinfo_seg.len = sizeof(MSFT_ImpInfo) * list_count(&This->ref_list);
10001 info = file->impinfo_seg.data = heap_alloc(file->impinfo_seg.len);
10003 LIST_FOR_EACH_ENTRY(ref_type, &This->ref_list, TLBRefType, entry){
10004 info->flags = i | ((ref_type->tkind & 0xFF) << 24);
10005 if(ref_type->index == TLB_REF_USE_GUID){
10006 info->flags |= MSFT_IMPINFO_OFFSET_IS_GUID;
10007 info->oGuid = ref_type->guid->offset;
10008 }else
10009 info->oGuid = ref_type->index;
10010 info->oImpFile = ref_type->pImpTLInfo->offset;
10011 ++i;
10012 ++info;
10016 static void WMSFT_compile_guidhash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10018 file->guidhash_seg.len = 0x80;
10019 file->guidhash_seg.data = heap_alloc(file->guidhash_seg.len);
10020 memset(file->guidhash_seg.data, 0xFF, file->guidhash_seg.len);
10023 static void WMSFT_compile_namehash(ITypeLibImpl *This, WMSFT_TLBFile *file)
10025 file->namehash_seg.len = 0x200;
10026 file->namehash_seg.data = heap_alloc(file->namehash_seg.len);
10027 memset(file->namehash_seg.data, 0xFF, file->namehash_seg.len);
10030 static void tmp_fill_segdir_seg(MSFT_pSeg *segdir, WMSFT_SegContents *contents, DWORD *running_offset)
10032 if(contents && contents->len){
10033 segdir->offset = *running_offset;
10034 segdir->length = contents->len;
10035 *running_offset += segdir->length;
10036 }else{
10037 segdir->offset = -1;
10038 segdir->length = 0;
10041 /* TODO: do these ever change? */
10042 segdir->res08 = -1;
10043 segdir->res0c = 0xf;
10046 static void WMSFT_write_segment(HANDLE outfile, WMSFT_SegContents *segment)
10048 DWORD written;
10049 if(segment)
10050 WriteFile(outfile, segment->data, segment->len, &written, NULL);
10053 static HRESULT WMSFT_fixup_typeinfos(ITypeLibImpl *This, WMSFT_TLBFile *file,
10054 DWORD file_len)
10056 DWORD i;
10057 MSFT_TypeInfoBase *base = (MSFT_TypeInfoBase *)file->typeinfo_seg.data;
10059 for(i = 0; i < This->TypeInfoCount; ++i){
10060 base->memoffset += file_len;
10061 ++base;
10064 return S_OK;
10067 static void WMSFT_free_file(WMSFT_TLBFile *file)
10069 HeapFree(GetProcessHeap(), 0, file->typeinfo_seg.data);
10070 HeapFree(GetProcessHeap(), 0, file->guidhash_seg.data);
10071 HeapFree(GetProcessHeap(), 0, file->guid_seg.data);
10072 HeapFree(GetProcessHeap(), 0, file->ref_seg.data);
10073 HeapFree(GetProcessHeap(), 0, file->impinfo_seg.data);
10074 HeapFree(GetProcessHeap(), 0, file->impfile_seg.data);
10075 HeapFree(GetProcessHeap(), 0, file->namehash_seg.data);
10076 HeapFree(GetProcessHeap(), 0, file->name_seg.data);
10077 HeapFree(GetProcessHeap(), 0, file->string_seg.data);
10078 HeapFree(GetProcessHeap(), 0, file->typdesc_seg.data);
10079 HeapFree(GetProcessHeap(), 0, file->arraydesc_seg.data);
10080 HeapFree(GetProcessHeap(), 0, file->custdata_seg.data);
10081 HeapFree(GetProcessHeap(), 0, file->cdguids_seg.data);
10082 HeapFree(GetProcessHeap(), 0, file->aux_seg.data);
10085 static HRESULT WINAPI ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2 *iface)
10087 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10088 WMSFT_TLBFile file;
10089 DWORD written, junk_size, junk_offs, running_offset;
10090 BOOL br;
10091 HANDLE outfile;
10092 HRESULT hres;
10093 DWORD *junk;
10094 UINT i;
10096 TRACE("%p\n", This);
10098 for(i = 0; i < This->TypeInfoCount; ++i)
10099 if(This->typeinfos[i]->needs_layout)
10100 ICreateTypeInfo2_LayOut(&This->typeinfos[i]->ICreateTypeInfo2_iface);
10102 memset(&file, 0, sizeof(file));
10104 file.header.magic1 = 0x5446534D;
10105 file.header.magic2 = 0x00010002;
10106 file.header.lcid = This->set_lcid ? This->set_lcid : MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
10107 file.header.lcid2 = This->set_lcid;
10108 file.header.varflags = 0x40 | This->syskind;
10109 if (This->HelpFile)
10110 file.header.varflags |= 0x10;
10111 if (This->HelpStringDll)
10112 file.header.varflags |= HELPDLLFLAG;
10113 file.header.version = (This->ver_minor << 16) | This->ver_major;
10114 file.header.flags = This->libflags;
10115 file.header.helpstringcontext = 0; /* TODO - SetHelpStringContext not implemented yet */
10116 file.header.helpcontext = This->dwHelpContext;
10117 file.header.res44 = 0x20;
10118 file.header.res48 = 0x80;
10119 file.header.dispatchpos = This->dispatch_href;
10121 WMSFT_compile_namehash(This, &file);
10122 /* do name and string compilation to get offsets for other compilations */
10123 hres = WMSFT_compile_names(This, &file);
10124 if (FAILED(hres)){
10125 WMSFT_free_file(&file);
10126 return hres;
10129 hres = WMSFT_compile_strings(This, &file);
10130 if (FAILED(hres)){
10131 WMSFT_free_file(&file);
10132 return hres;
10135 WMSFT_compile_guidhash(This, &file);
10136 hres = WMSFT_compile_guids(This, &file);
10137 if (FAILED(hres)){
10138 WMSFT_free_file(&file);
10139 return hres;
10142 if(This->HelpFile)
10143 file.header.helpfile = This->HelpFile->offset;
10144 else
10145 file.header.helpfile = -1;
10147 if(This->DocString)
10148 file.header.helpstring = This->DocString->offset;
10149 else
10150 file.header.helpstring = -1;
10152 /* do some more segment compilation */
10153 file.header.nimpinfos = list_count(&This->ref_list);
10154 file.header.nrtypeinfos = This->TypeInfoCount;
10156 if(This->Name)
10157 file.header.NameOffset = This->Name->offset;
10158 else
10159 file.header.NameOffset = -1;
10161 file.header.CustomDataOffset = WMSFT_compile_custdata(&This->custdata_list, &file);
10163 if(This->guid)
10164 file.header.posguid = This->guid->offset;
10165 else
10166 file.header.posguid = -1;
10168 junk_size = file.header.nrtypeinfos * sizeof(DWORD);
10169 if(file.header.varflags & HELPDLLFLAG)
10170 junk_size += sizeof(DWORD);
10171 if(junk_size){
10172 junk = heap_alloc_zero(junk_size);
10173 if(file.header.varflags & HELPDLLFLAG){
10174 *junk = This->HelpStringDll->offset;
10175 junk_offs = 1;
10176 }else
10177 junk_offs = 0;
10178 }else{
10179 junk = NULL;
10180 junk_offs = 0;
10183 WMSFT_compile_typeinfo_seg(This, &file, junk + junk_offs);
10184 WMSFT_compile_impinfo(This, &file);
10186 running_offset = 0;
10188 TRACE("header at: 0x%x\n", running_offset);
10189 running_offset += sizeof(file.header);
10191 TRACE("junk at: 0x%x\n", running_offset);
10192 running_offset += junk_size;
10194 TRACE("segdir at: 0x%x\n", running_offset);
10195 running_offset += sizeof(file.segdir);
10197 TRACE("typeinfo at: 0x%x\n", running_offset);
10198 tmp_fill_segdir_seg(&file.segdir.pTypeInfoTab, &file.typeinfo_seg, &running_offset);
10200 TRACE("guidhashtab at: 0x%x\n", running_offset);
10201 tmp_fill_segdir_seg(&file.segdir.pGuidHashTab, &file.guidhash_seg, &running_offset);
10203 TRACE("guidtab at: 0x%x\n", running_offset);
10204 tmp_fill_segdir_seg(&file.segdir.pGuidTab, &file.guid_seg, &running_offset);
10206 TRACE("reftab at: 0x%x\n", running_offset);
10207 tmp_fill_segdir_seg(&file.segdir.pRefTab, &file.ref_seg, &running_offset);
10209 TRACE("impinfo at: 0x%x\n", running_offset);
10210 tmp_fill_segdir_seg(&file.segdir.pImpInfo, &file.impinfo_seg, &running_offset);
10212 TRACE("impfiles at: 0x%x\n", running_offset);
10213 tmp_fill_segdir_seg(&file.segdir.pImpFiles, &file.impfile_seg, &running_offset);
10215 TRACE("namehashtab at: 0x%x\n", running_offset);
10216 tmp_fill_segdir_seg(&file.segdir.pNameHashTab, &file.namehash_seg, &running_offset);
10218 TRACE("nametab at: 0x%x\n", running_offset);
10219 tmp_fill_segdir_seg(&file.segdir.pNametab, &file.name_seg, &running_offset);
10221 TRACE("stringtab at: 0x%x\n", running_offset);
10222 tmp_fill_segdir_seg(&file.segdir.pStringtab, &file.string_seg, &running_offset);
10224 TRACE("typdesc at: 0x%x\n", running_offset);
10225 tmp_fill_segdir_seg(&file.segdir.pTypdescTab, &file.typdesc_seg, &running_offset);
10227 TRACE("arraydescriptions at: 0x%x\n", running_offset);
10228 tmp_fill_segdir_seg(&file.segdir.pArrayDescriptions, &file.arraydesc_seg, &running_offset);
10230 TRACE("custdata at: 0x%x\n", running_offset);
10231 tmp_fill_segdir_seg(&file.segdir.pCustData, &file.custdata_seg, &running_offset);
10233 TRACE("cdguids at: 0x%x\n", running_offset);
10234 tmp_fill_segdir_seg(&file.segdir.pCDGuids, &file.cdguids_seg, &running_offset);
10236 TRACE("res0e at: 0x%x\n", running_offset);
10237 tmp_fill_segdir_seg(&file.segdir.res0e, NULL, &running_offset);
10239 TRACE("res0f at: 0x%x\n", running_offset);
10240 tmp_fill_segdir_seg(&file.segdir.res0f, NULL, &running_offset);
10242 TRACE("aux_seg at: 0x%x\n", running_offset);
10244 WMSFT_fixup_typeinfos(This, &file, running_offset);
10246 outfile = CreateFileW(This->path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
10247 FILE_ATTRIBUTE_NORMAL, 0);
10248 if (outfile == INVALID_HANDLE_VALUE){
10249 WMSFT_free_file(&file);
10250 heap_free(junk);
10251 return TYPE_E_IOERROR;
10254 br = WriteFile(outfile, &file.header, sizeof(file.header), &written, NULL);
10255 if (!br) {
10256 WMSFT_free_file(&file);
10257 CloseHandle(outfile);
10258 heap_free(junk);
10259 return TYPE_E_IOERROR;
10262 br = WriteFile(outfile, junk, junk_size, &written, NULL);
10263 heap_free(junk);
10264 if (!br) {
10265 WMSFT_free_file(&file);
10266 CloseHandle(outfile);
10267 return TYPE_E_IOERROR;
10270 br = WriteFile(outfile, &file.segdir, sizeof(file.segdir), &written, NULL);
10271 if (!br) {
10272 WMSFT_free_file(&file);
10273 CloseHandle(outfile);
10274 return TYPE_E_IOERROR;
10277 WMSFT_write_segment(outfile, &file.typeinfo_seg);
10278 WMSFT_write_segment(outfile, &file.guidhash_seg);
10279 WMSFT_write_segment(outfile, &file.guid_seg);
10280 WMSFT_write_segment(outfile, &file.ref_seg);
10281 WMSFT_write_segment(outfile, &file.impinfo_seg);
10282 WMSFT_write_segment(outfile, &file.impfile_seg);
10283 WMSFT_write_segment(outfile, &file.namehash_seg);
10284 WMSFT_write_segment(outfile, &file.name_seg);
10285 WMSFT_write_segment(outfile, &file.string_seg);
10286 WMSFT_write_segment(outfile, &file.typdesc_seg);
10287 WMSFT_write_segment(outfile, &file.arraydesc_seg);
10288 WMSFT_write_segment(outfile, &file.custdata_seg);
10289 WMSFT_write_segment(outfile, &file.cdguids_seg);
10290 WMSFT_write_segment(outfile, &file.aux_seg);
10292 WMSFT_free_file(&file);
10294 CloseHandle(outfile);
10296 return S_OK;
10299 static HRESULT WINAPI ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2 *iface,
10300 LPOLESTR name)
10302 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10303 FIXME("%p %s - stub\n", This, wine_dbgstr_w(name));
10304 return E_NOTIMPL;
10307 static HRESULT WINAPI ICreateTypeLib2_fnSetCustData(ICreateTypeLib2 *iface,
10308 REFGUID guid, VARIANT *varVal)
10310 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10311 TLBGuid *tlbguid;
10313 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
10315 if (!guid || !varVal)
10316 return E_INVALIDARG;
10318 tlbguid = TLB_append_guid(&This->guid_list, guid, -1);
10320 return TLB_set_custdata(&This->custdata_list, tlbguid, varVal);
10323 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2 *iface,
10324 ULONG helpStringContext)
10326 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10327 FIXME("%p %u - stub\n", This, helpStringContext);
10328 return E_NOTIMPL;
10331 static HRESULT WINAPI ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2 *iface,
10332 LPOLESTR filename)
10334 ITypeLibImpl *This = impl_from_ICreateTypeLib2(iface);
10335 TRACE("%p %s\n", This, wine_dbgstr_w(filename));
10337 if (!filename)
10338 return E_INVALIDARG;
10340 This->HelpStringDll = TLB_append_str(&This->string_list, filename);
10342 return S_OK;
10345 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl = {
10346 ICreateTypeLib2_fnQueryInterface,
10347 ICreateTypeLib2_fnAddRef,
10348 ICreateTypeLib2_fnRelease,
10349 ICreateTypeLib2_fnCreateTypeInfo,
10350 ICreateTypeLib2_fnSetName,
10351 ICreateTypeLib2_fnSetVersion,
10352 ICreateTypeLib2_fnSetGuid,
10353 ICreateTypeLib2_fnSetDocString,
10354 ICreateTypeLib2_fnSetHelpFileName,
10355 ICreateTypeLib2_fnSetHelpContext,
10356 ICreateTypeLib2_fnSetLcid,
10357 ICreateTypeLib2_fnSetLibFlags,
10358 ICreateTypeLib2_fnSaveAllChanges,
10359 ICreateTypeLib2_fnDeleteTypeInfo,
10360 ICreateTypeLib2_fnSetCustData,
10361 ICreateTypeLib2_fnSetHelpStringContext,
10362 ICreateTypeLib2_fnSetHelpStringDll
10365 static HRESULT WINAPI ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2 *iface,
10366 REFIID riid, void **object)
10368 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10370 return ITypeInfo2_QueryInterface(&This->ITypeInfo2_iface, riid, object);
10373 static ULONG WINAPI ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2 *iface)
10375 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10377 return ITypeInfo2_AddRef(&This->ITypeInfo2_iface);
10380 static ULONG WINAPI ICreateTypeInfo2_fnRelease(ICreateTypeInfo2 *iface)
10382 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10384 return ITypeInfo2_Release(&This->ITypeInfo2_iface);
10387 static HRESULT WINAPI ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2 *iface,
10388 REFGUID guid)
10390 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10392 TRACE("%p %s\n", This, debugstr_guid(guid));
10394 This->guid = TLB_append_guid(&This->pTypeLib->guid_list, guid, This->hreftype);
10396 return S_OK;
10399 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2 *iface,
10400 UINT typeFlags)
10402 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10403 WORD old_flags;
10404 HRESULT hres;
10406 TRACE("%p %x\n", This, typeFlags);
10408 if (typeFlags & TYPEFLAG_FDUAL) {
10409 static const WCHAR stdole2tlb[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10410 ITypeLib *stdole;
10411 ITypeInfo *dispatch;
10412 HREFTYPE hreftype;
10413 HRESULT hres;
10415 hres = LoadTypeLib(stdole2tlb, &stdole);
10416 if(FAILED(hres))
10417 return hres;
10419 hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
10420 ITypeLib_Release(stdole);
10421 if(FAILED(hres))
10422 return hres;
10424 hres = ICreateTypeInfo2_AddRefTypeInfo(iface, dispatch, &hreftype);
10425 ITypeInfo_Release(dispatch);
10426 if(FAILED(hres))
10427 return hres;
10430 old_flags = This->typeattr.wTypeFlags;
10431 This->typeattr.wTypeFlags = typeFlags;
10433 hres = ICreateTypeInfo2_LayOut(iface);
10434 if (FAILED(hres)) {
10435 This->typeattr.wTypeFlags = old_flags;
10436 return hres;
10439 return S_OK;
10442 static HRESULT WINAPI ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2 *iface,
10443 LPOLESTR doc)
10445 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10447 TRACE("%p %s\n", This, wine_dbgstr_w(doc));
10449 if (!doc)
10450 return E_INVALIDARG;
10452 This->DocString = TLB_append_str(&This->pTypeLib->string_list, doc);
10454 return S_OK;
10457 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2 *iface,
10458 DWORD helpContext)
10460 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10462 TRACE("%p %d\n", This, helpContext);
10464 This->dwHelpContext = helpContext;
10466 return S_OK;
10469 static HRESULT WINAPI ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2 *iface,
10470 WORD majorVerNum, WORD minorVerNum)
10472 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10474 TRACE("%p %d %d\n", This, majorVerNum, minorVerNum);
10476 This->typeattr.wMajorVerNum = majorVerNum;
10477 This->typeattr.wMinorVerNum = minorVerNum;
10479 return S_OK;
10482 static HRESULT WINAPI ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2 *iface,
10483 ITypeInfo *typeInfo, HREFTYPE *refType)
10485 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10486 UINT index;
10487 ITypeLib *container;
10488 TLBRefType *ref_type;
10489 TLBImpLib *implib;
10490 TYPEATTR *typeattr;
10491 TLIBATTR *libattr;
10492 HRESULT hres;
10494 TRACE("%p %p %p\n", This, typeInfo, refType);
10496 if (!typeInfo || !refType)
10497 return E_INVALIDARG;
10499 hres = ITypeInfo_GetContainingTypeLib(typeInfo, &container, &index);
10500 if (FAILED(hres))
10501 return hres;
10503 if (container == (ITypeLib*)&This->pTypeLib->ITypeLib2_iface) {
10504 ITypeInfoImpl *target = impl_from_ITypeInfo(typeInfo);
10506 ITypeLib_Release(container);
10508 *refType = target->hreftype;
10510 return S_OK;
10513 hres = ITypeLib_GetLibAttr(container, &libattr);
10514 if (FAILED(hres)) {
10515 ITypeLib_Release(container);
10516 return hres;
10519 LIST_FOR_EACH_ENTRY(implib, &This->pTypeLib->implib_list, TLBImpLib, entry){
10520 if(IsEqualGUID(&implib->guid->guid, &libattr->guid) &&
10521 implib->lcid == libattr->lcid &&
10522 implib->wVersionMajor == libattr->wMajorVerNum &&
10523 implib->wVersionMinor == libattr->wMinorVerNum)
10524 break;
10527 if(&implib->entry == &This->pTypeLib->implib_list){
10528 implib = heap_alloc_zero(sizeof(TLBImpLib));
10530 if((ITypeLib2Vtbl*)container->lpVtbl == &tlbvt){
10531 const ITypeLibImpl *our_container = impl_from_ITypeLib2((ITypeLib2*)container);
10532 implib->name = SysAllocString(our_container->path);
10533 }else{
10534 hres = QueryPathOfRegTypeLib(&libattr->guid, libattr->wMajorVerNum,
10535 libattr->wMinorVerNum, libattr->lcid, &implib->name);
10536 if(FAILED(hres)){
10537 implib->name = NULL;
10538 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres);
10542 implib->guid = TLB_append_guid(&This->pTypeLib->guid_list, &libattr->guid, 2);
10543 implib->lcid = libattr->lcid;
10544 implib->wVersionMajor = libattr->wMajorVerNum;
10545 implib->wVersionMinor = libattr->wMinorVerNum;
10547 list_add_tail(&This->pTypeLib->implib_list, &implib->entry);
10550 ITypeLib_ReleaseTLibAttr(container, libattr);
10551 ITypeLib_Release(container);
10553 hres = ITypeInfo_GetTypeAttr(typeInfo, &typeattr);
10554 if (FAILED(hres))
10555 return hres;
10557 index = 0;
10558 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry){
10559 if(ref_type->index == TLB_REF_USE_GUID &&
10560 IsEqualGUID(&ref_type->guid->guid, &typeattr->guid) &&
10561 ref_type->tkind == typeattr->typekind)
10562 break;
10563 ++index;
10566 if(&ref_type->entry == &This->pTypeLib->ref_list){
10567 ref_type = heap_alloc_zero(sizeof(TLBRefType));
10569 ref_type->tkind = typeattr->typekind;
10570 ref_type->pImpTLInfo = implib;
10571 ref_type->reference = index * sizeof(MSFT_ImpInfo);
10573 ref_type->index = TLB_REF_USE_GUID;
10575 ref_type->guid = TLB_append_guid(&This->pTypeLib->guid_list, &typeattr->guid, ref_type->reference+1);
10577 list_add_tail(&This->pTypeLib->ref_list, &ref_type->entry);
10580 ITypeInfo_ReleaseTypeAttr(typeInfo, typeattr);
10582 *refType = ref_type->reference | 0x1;
10584 if(IsEqualGUID(&ref_type->guid->guid, &IID_IDispatch))
10585 This->pTypeLib->dispatch_href = *refType;
10587 return S_OK;
10590 static HRESULT WINAPI ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2 *iface,
10591 UINT index, FUNCDESC *funcDesc)
10593 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10594 TLBFuncDesc tmp_func_desc, *func_desc;
10595 int buf_size, i;
10596 char *buffer;
10597 HRESULT hres;
10599 TRACE("%p %u %p\n", This, index, funcDesc);
10601 if (!funcDesc || funcDesc->oVft & 3)
10602 return E_INVALIDARG;
10604 switch (This->typeattr.typekind) {
10605 case TKIND_MODULE:
10606 if (funcDesc->funckind != FUNC_STATIC)
10607 return TYPE_E_BADMODULEKIND;
10608 break;
10609 case TKIND_DISPATCH:
10610 if (funcDesc->funckind != FUNC_DISPATCH)
10611 return TYPE_E_BADMODULEKIND;
10612 break;
10613 default:
10614 if (funcDesc->funckind != FUNC_PUREVIRTUAL)
10615 return TYPE_E_BADMODULEKIND;
10618 if (index > This->typeattr.cFuncs)
10619 return TYPE_E_ELEMENTNOTFOUND;
10621 if (funcDesc->invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) &&
10622 !funcDesc->cParams)
10623 return TYPE_E_INCONSISTENTPROPFUNCS;
10625 #ifdef _WIN64
10626 if(This->pTypeLib->syskind == SYS_WIN64 &&
10627 funcDesc->oVft % 8 != 0)
10628 return E_INVALIDARG;
10629 #endif
10631 memset(&tmp_func_desc, 0, sizeof(tmp_func_desc));
10632 TLBFuncDesc_Constructor(&tmp_func_desc);
10634 tmp_func_desc.funcdesc = *funcDesc;
10636 if (tmp_func_desc.funcdesc.oVft != 0)
10637 tmp_func_desc.funcdesc.oVft |= 1;
10639 if (funcDesc->cScodes && funcDesc->lprgscode) {
10640 tmp_func_desc.funcdesc.lprgscode = heap_alloc(sizeof(SCODE) * funcDesc->cScodes);
10641 memcpy(tmp_func_desc.funcdesc.lprgscode, funcDesc->lprgscode, sizeof(SCODE) * funcDesc->cScodes);
10642 } else {
10643 tmp_func_desc.funcdesc.lprgscode = NULL;
10644 tmp_func_desc.funcdesc.cScodes = 0;
10647 buf_size = TLB_SizeElemDesc(&funcDesc->elemdescFunc);
10648 for (i = 0; i < funcDesc->cParams; ++i) {
10649 buf_size += sizeof(ELEMDESC);
10650 buf_size += TLB_SizeElemDesc(funcDesc->lprgelemdescParam + i);
10652 tmp_func_desc.funcdesc.lprgelemdescParam = heap_alloc(buf_size);
10653 buffer = (char*)(tmp_func_desc.funcdesc.lprgelemdescParam + funcDesc->cParams);
10655 hres = TLB_CopyElemDesc(&funcDesc->elemdescFunc, &tmp_func_desc.funcdesc.elemdescFunc, &buffer);
10656 if (FAILED(hres)) {
10657 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10658 heap_free(tmp_func_desc.funcdesc.lprgscode);
10659 return hres;
10662 for (i = 0; i < funcDesc->cParams; ++i) {
10663 hres = TLB_CopyElemDesc(funcDesc->lprgelemdescParam + i,
10664 tmp_func_desc.funcdesc.lprgelemdescParam + i, &buffer);
10665 if (FAILED(hres)) {
10666 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10667 heap_free(tmp_func_desc.funcdesc.lprgscode);
10668 return hres;
10670 if (tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT &&
10671 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_VARIANT &&
10672 tmp_func_desc.funcdesc.lprgelemdescParam[i].tdesc.vt != VT_USERDEFINED){
10673 hres = TLB_SanitizeVariant(&tmp_func_desc.funcdesc.lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
10674 if (FAILED(hres)) {
10675 heap_free(tmp_func_desc.funcdesc.lprgelemdescParam);
10676 heap_free(tmp_func_desc.funcdesc.lprgscode);
10677 return hres;
10682 tmp_func_desc.pParamDesc = TLBParDesc_Constructor(funcDesc->cParams);
10684 if (This->funcdescs) {
10685 This->funcdescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->funcdescs,
10686 sizeof(TLBFuncDesc) * (This->typeattr.cFuncs + 1));
10688 if (index < This->typeattr.cFuncs) {
10689 memmove(This->funcdescs + index + 1, This->funcdescs + index,
10690 (This->typeattr.cFuncs - index) * sizeof(TLBFuncDesc));
10691 func_desc = This->funcdescs + index;
10692 } else
10693 func_desc = This->funcdescs + This->typeattr.cFuncs;
10695 /* move custdata lists to the new memory location */
10696 for(i = 0; i < This->typeattr.cFuncs + 1; ++i){
10697 if(index != i){
10698 TLBFuncDesc *fd = &This->funcdescs[i];
10699 if(fd->custdata_list.prev == fd->custdata_list.next)
10700 list_init(&fd->custdata_list);
10701 else{
10702 fd->custdata_list.prev->next = &fd->custdata_list;
10703 fd->custdata_list.next->prev = &fd->custdata_list;
10707 } else
10708 func_desc = This->funcdescs = heap_alloc(sizeof(TLBFuncDesc));
10710 memcpy(func_desc, &tmp_func_desc, sizeof(tmp_func_desc));
10711 list_init(&func_desc->custdata_list);
10713 ++This->typeattr.cFuncs;
10715 This->needs_layout = TRUE;
10717 return S_OK;
10720 static HRESULT WINAPI ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2 *iface,
10721 UINT index, HREFTYPE refType)
10723 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10724 TLBImplType *impl_type;
10725 HRESULT hres;
10727 TRACE("%p %u %d\n", This, index, refType);
10729 switch(This->typeattr.typekind){
10730 case TKIND_COCLASS: {
10731 if (index == -1) {
10732 FIXME("Unhandled index: -1\n");
10733 return E_NOTIMPL;
10736 if(index != This->typeattr.cImplTypes)
10737 return TYPE_E_ELEMENTNOTFOUND;
10739 break;
10741 case TKIND_INTERFACE:
10742 case TKIND_DISPATCH:
10743 if (index != 0 || This->typeattr.cImplTypes)
10744 return TYPE_E_ELEMENTNOTFOUND;
10745 break;
10746 default:
10747 FIXME("Unimplemented typekind: %d\n", This->typeattr.typekind);
10748 return E_NOTIMPL;
10751 if (This->impltypes){
10752 UINT i;
10754 This->impltypes = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->impltypes,
10755 sizeof(TLBImplType) * (This->typeattr.cImplTypes + 1));
10757 if (index < This->typeattr.cImplTypes) {
10758 memmove(This->impltypes + index + 1, This->impltypes + index,
10759 (This->typeattr.cImplTypes - index) * sizeof(TLBImplType));
10760 impl_type = This->impltypes + index;
10761 } else
10762 impl_type = This->impltypes + This->typeattr.cImplTypes;
10764 /* move custdata lists to the new memory location */
10765 for(i = 0; i < This->typeattr.cImplTypes + 1; ++i){
10766 if(index != i){
10767 TLBImplType *it = &This->impltypes[i];
10768 if(it->custdata_list.prev == it->custdata_list.next)
10769 list_init(&it->custdata_list);
10770 else{
10771 it->custdata_list.prev->next = &it->custdata_list;
10772 it->custdata_list.next->prev = &it->custdata_list;
10776 } else
10777 impl_type = This->impltypes = heap_alloc(sizeof(TLBImplType));
10779 memset(impl_type, 0, sizeof(TLBImplType));
10780 TLBImplType_Constructor(impl_type);
10781 impl_type->hRef = refType;
10783 ++This->typeattr.cImplTypes;
10785 if((refType & (~0x3)) == (This->pTypeLib->dispatch_href & (~0x3)))
10786 This->typeattr.wTypeFlags |= TYPEFLAG_FDISPATCHABLE;
10788 hres = ICreateTypeInfo2_LayOut(iface);
10789 if (FAILED(hres))
10790 return hres;
10792 return S_OK;
10795 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2 *iface,
10796 UINT index, INT implTypeFlags)
10798 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10799 TLBImplType *impl_type = &This->impltypes[index];
10801 TRACE("%p %u %x\n", This, index, implTypeFlags);
10803 if (This->typeattr.typekind != TKIND_COCLASS)
10804 return TYPE_E_BADMODULEKIND;
10806 if (index >= This->typeattr.cImplTypes)
10807 return TYPE_E_ELEMENTNOTFOUND;
10809 impl_type->implflags = implTypeFlags;
10811 return S_OK;
10814 static HRESULT WINAPI ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2 *iface,
10815 WORD alignment)
10817 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10819 TRACE("%p %d\n", This, alignment);
10821 This->typeattr.cbAlignment = alignment;
10823 return S_OK;
10826 static HRESULT WINAPI ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2 *iface,
10827 LPOLESTR schema)
10829 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10831 TRACE("%p %s\n", This, wine_dbgstr_w(schema));
10833 if (!schema)
10834 return E_INVALIDARG;
10836 This->Schema = TLB_append_str(&This->pTypeLib->string_list, schema);
10838 This->typeattr.lpstrSchema = This->Schema->str;
10840 return S_OK;
10843 static HRESULT WINAPI ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2 *iface,
10844 UINT index, VARDESC *varDesc)
10846 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10847 TLBVarDesc *var_desc;
10849 TRACE("%p %u %p\n", This, index, varDesc);
10851 if (This->vardescs){
10852 UINT i;
10854 This->vardescs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->vardescs,
10855 sizeof(TLBVarDesc) * (This->typeattr.cVars + 1));
10857 if (index < This->typeattr.cVars) {
10858 memmove(This->vardescs + index + 1, This->vardescs + index,
10859 (This->typeattr.cVars - index) * sizeof(TLBVarDesc));
10860 var_desc = This->vardescs + index;
10861 } else
10862 var_desc = This->vardescs + This->typeattr.cVars;
10864 /* move custdata lists to the new memory location */
10865 for(i = 0; i < This->typeattr.cVars + 1; ++i){
10866 if(index != i){
10867 TLBVarDesc *var = &This->vardescs[i];
10868 if(var->custdata_list.prev == var->custdata_list.next)
10869 list_init(&var->custdata_list);
10870 else{
10871 var->custdata_list.prev->next = &var->custdata_list;
10872 var->custdata_list.next->prev = &var->custdata_list;
10876 } else
10877 var_desc = This->vardescs = heap_alloc_zero(sizeof(TLBVarDesc));
10879 TLBVarDesc_Constructor(var_desc);
10880 TLB_AllocAndInitVarDesc(varDesc, &var_desc->vardesc_create);
10881 var_desc->vardesc = *var_desc->vardesc_create;
10883 ++This->typeattr.cVars;
10885 This->needs_layout = TRUE;
10887 return S_OK;
10890 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2 *iface,
10891 UINT index, LPOLESTR *names, UINT numNames)
10893 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10894 TLBFuncDesc *func_desc = &This->funcdescs[index];
10895 int i;
10897 TRACE("%p %u %p %u\n", This, index, names, numNames);
10899 if (!names)
10900 return E_INVALIDARG;
10902 if (index >= This->typeattr.cFuncs || numNames == 0)
10903 return TYPE_E_ELEMENTNOTFOUND;
10905 if (func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF)){
10906 if(numNames > func_desc->funcdesc.cParams)
10907 return TYPE_E_ELEMENTNOTFOUND;
10908 } else
10909 if(numNames > func_desc->funcdesc.cParams + 1)
10910 return TYPE_E_ELEMENTNOTFOUND;
10912 for(i = 0; i < This->typeattr.cFuncs; ++i) {
10913 TLBFuncDesc *iter = &This->funcdescs[i];
10914 if (iter->Name && !strcmpW(TLB_get_bstr(iter->Name), *names)) {
10915 if (iter->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10916 func_desc->funcdesc.invkind & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF | INVOKE_PROPERTYGET) &&
10917 func_desc->funcdesc.invkind != iter->funcdesc.invkind)
10918 continue;
10919 return TYPE_E_AMBIGUOUSNAME;
10923 func_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *names);
10925 for (i = 1; i < numNames; ++i) {
10926 TLBParDesc *par_desc = func_desc->pParamDesc + i - 1;
10927 par_desc->Name = TLB_append_str(&This->pTypeLib->name_list, *(names + i));
10930 return S_OK;
10933 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2 *iface,
10934 UINT index, LPOLESTR name)
10936 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10938 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(name));
10940 if(!name)
10941 return E_INVALIDARG;
10943 if(index >= This->typeattr.cVars)
10944 return TYPE_E_ELEMENTNOTFOUND;
10946 This->vardescs[index].Name = TLB_append_str(&This->pTypeLib->name_list, name);
10947 return S_OK;
10950 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2 *iface,
10951 TYPEDESC *tdescAlias)
10953 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10954 HRESULT hr;
10956 TRACE("%p %p\n", This, tdescAlias);
10958 if(!tdescAlias)
10959 return E_INVALIDARG;
10961 if(This->typeattr.typekind != TKIND_ALIAS)
10962 return TYPE_E_BADMODULEKIND;
10964 hr = TLB_size_instance(This, This->pTypeLib->syskind, tdescAlias, &This->typeattr.cbSizeInstance, &This->typeattr.cbAlignment);
10965 if(FAILED(hr))
10966 return hr;
10968 heap_free(This->tdescAlias);
10969 This->tdescAlias = heap_alloc(TLB_SizeTypeDesc(tdescAlias, TRUE));
10970 TLB_CopyTypeDesc(NULL, tdescAlias, This->tdescAlias);
10972 return S_OK;
10975 static HRESULT WINAPI ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2 *iface,
10976 UINT index, LPOLESTR dllName, LPOLESTR procName)
10978 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10979 FIXME("%p %u %s %s - stub\n", This, index, wine_dbgstr_w(dllName), wine_dbgstr_w(procName));
10980 return E_NOTIMPL;
10983 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2 *iface,
10984 UINT index, LPOLESTR docString)
10986 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
10987 TLBFuncDesc *func_desc = &This->funcdescs[index];
10989 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
10991 if(!docString)
10992 return E_INVALIDARG;
10994 if(index >= This->typeattr.cFuncs)
10995 return TYPE_E_ELEMENTNOTFOUND;
10997 func_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
10999 return S_OK;
11002 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2 *iface,
11003 UINT index, LPOLESTR docString)
11005 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11006 TLBVarDesc *var_desc = &This->vardescs[index];
11008 TRACE("%p %u %s\n", This, index, wine_dbgstr_w(docString));
11010 if(!docString)
11011 return E_INVALIDARG;
11013 if(index >= This->typeattr.cVars)
11014 return TYPE_E_ELEMENTNOTFOUND;
11016 var_desc->HelpString = TLB_append_str(&This->pTypeLib->string_list, docString);
11018 return S_OK;
11021 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2 *iface,
11022 UINT index, DWORD helpContext)
11024 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11025 TLBFuncDesc *func_desc = &This->funcdescs[index];
11027 TRACE("%p %u %d\n", This, index, helpContext);
11029 if(index >= This->typeattr.cFuncs)
11030 return TYPE_E_ELEMENTNOTFOUND;
11032 func_desc->helpcontext = helpContext;
11034 return S_OK;
11037 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2 *iface,
11038 UINT index, DWORD helpContext)
11040 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11041 TLBVarDesc *var_desc = &This->vardescs[index];
11043 TRACE("%p %u %d\n", This, index, helpContext);
11045 if(index >= This->typeattr.cVars)
11046 return TYPE_E_ELEMENTNOTFOUND;
11048 var_desc->HelpContext = helpContext;
11050 return S_OK;
11053 static HRESULT WINAPI ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2 *iface,
11054 UINT index, BSTR bstrMops)
11056 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11057 FIXME("%p %u %s - stub\n", This, index, wine_dbgstr_w(bstrMops));
11058 return E_NOTIMPL;
11061 static HRESULT WINAPI ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2 *iface,
11062 IDLDESC *idlDesc)
11064 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11066 TRACE("%p %p\n", This, idlDesc);
11068 if (!idlDesc)
11069 return E_INVALIDARG;
11071 This->typeattr.idldescType.dwReserved = idlDesc->dwReserved;
11072 This->typeattr.idldescType.wIDLFlags = idlDesc->wIDLFlags;
11074 return S_OK;
11077 static HRESULT WINAPI ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2 *iface)
11079 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11080 ITypeInfo *tinfo;
11081 TLBFuncDesc *func_desc;
11082 UINT user_vft = 0, i, depth = 0;
11083 HRESULT hres = S_OK;
11085 TRACE("%p\n", This);
11087 This->needs_layout = FALSE;
11089 hres = ICreateTypeInfo2_QueryInterface(iface, &IID_ITypeInfo, (LPVOID*)&tinfo);
11090 if (FAILED(hres))
11091 return hres;
11093 if (This->typeattr.typekind == TKIND_INTERFACE) {
11094 ITypeInfo *inh;
11095 TYPEATTR *attr;
11096 HREFTYPE inh_href;
11098 hres = ITypeInfo_GetRefTypeOfImplType(tinfo, 0, &inh_href);
11100 if (SUCCEEDED(hres)) {
11101 hres = ITypeInfo_GetRefTypeInfo(tinfo, inh_href, &inh);
11103 if (SUCCEEDED(hres)) {
11104 hres = ITypeInfo_GetTypeAttr(inh, &attr);
11105 if (FAILED(hres)) {
11106 ITypeInfo_Release(inh);
11107 ITypeInfo_Release(tinfo);
11108 return hres;
11110 This->typeattr.cbSizeVft = attr->cbSizeVft;
11111 ITypeInfo_ReleaseTypeAttr(inh, attr);
11114 ++depth;
11115 hres = ITypeInfo_GetRefTypeOfImplType(inh, 0, &inh_href);
11116 if(SUCCEEDED(hres)){
11117 ITypeInfo *next;
11118 hres = ITypeInfo_GetRefTypeInfo(inh, inh_href, &next);
11119 if(SUCCEEDED(hres)){
11120 ITypeInfo_Release(inh);
11121 inh = next;
11124 }while(SUCCEEDED(hres));
11125 hres = S_OK;
11127 ITypeInfo_Release(inh);
11128 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11129 This->typeattr.cbSizeVft = 0;
11130 hres = S_OK;
11131 } else {
11132 ITypeInfo_Release(tinfo);
11133 return hres;
11135 } else if (hres == TYPE_E_ELEMENTNOTFOUND) {
11136 This->typeattr.cbSizeVft = 0;
11137 hres = S_OK;
11138 } else {
11139 ITypeInfo_Release(tinfo);
11140 return hres;
11142 } else if (This->typeattr.typekind == TKIND_DISPATCH)
11143 This->typeattr.cbSizeVft = 7 * This->pTypeLib->ptr_size;
11144 else
11145 This->typeattr.cbSizeVft = 0;
11147 func_desc = This->funcdescs;
11148 i = 0;
11149 while (i < This->typeattr.cFuncs) {
11150 if (!(func_desc->funcdesc.oVft & 0x1))
11151 func_desc->funcdesc.oVft = This->typeattr.cbSizeVft;
11153 if ((func_desc->funcdesc.oVft & 0xFFFC) > user_vft)
11154 user_vft = func_desc->funcdesc.oVft & 0xFFFC;
11156 This->typeattr.cbSizeVft += This->pTypeLib->ptr_size;
11158 if (func_desc->funcdesc.memid == MEMBERID_NIL) {
11159 TLBFuncDesc *iter;
11160 UINT j = 0;
11161 BOOL reset = FALSE;
11163 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + i;
11165 iter = This->funcdescs;
11166 while (j < This->typeattr.cFuncs) {
11167 if (iter != func_desc && iter->funcdesc.memid == func_desc->funcdesc.memid) {
11168 if (!reset) {
11169 func_desc->funcdesc.memid = 0x60000000 + (depth << 16) + This->typeattr.cFuncs;
11170 reset = TRUE;
11171 } else
11172 ++func_desc->funcdesc.memid;
11173 iter = This->funcdescs;
11174 j = 0;
11175 } else {
11176 ++iter;
11177 ++j;
11182 ++func_desc;
11183 ++i;
11186 if (user_vft > This->typeattr.cbSizeVft)
11187 This->typeattr.cbSizeVft = user_vft + This->pTypeLib->ptr_size;
11189 for(i = 0; i < This->typeattr.cVars; ++i){
11190 TLBVarDesc *var_desc = &This->vardescs[i];
11191 if(var_desc->vardesc.memid == MEMBERID_NIL){
11192 UINT j = 0;
11193 BOOL reset = FALSE;
11194 TLBVarDesc *iter;
11196 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + i;
11198 iter = This->vardescs;
11199 while (j < This->typeattr.cVars) {
11200 if (iter != var_desc && iter->vardesc.memid == var_desc->vardesc.memid) {
11201 if (!reset) {
11202 var_desc->vardesc.memid = 0x40000000 + (depth << 16) + This->typeattr.cVars;
11203 reset = TRUE;
11204 } else
11205 ++var_desc->vardesc.memid;
11206 iter = This->vardescs;
11207 j = 0;
11208 } else {
11209 ++iter;
11210 ++j;
11216 ITypeInfo_Release(tinfo);
11217 return hres;
11220 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2 *iface,
11221 UINT index)
11223 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11224 FIXME("%p %u - stub\n", This, index);
11225 return E_NOTIMPL;
11228 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2 *iface,
11229 MEMBERID memid, INVOKEKIND invKind)
11231 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11232 FIXME("%p %x %d - stub\n", This, memid, invKind);
11233 return E_NOTIMPL;
11236 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2 *iface,
11237 UINT index)
11239 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11240 FIXME("%p %u - stub\n", This, index);
11241 return E_NOTIMPL;
11244 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2 *iface,
11245 MEMBERID memid)
11247 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11248 FIXME("%p %x - stub\n", This, memid);
11249 return E_NOTIMPL;
11252 static HRESULT WINAPI ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2 *iface,
11253 UINT index)
11255 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11256 FIXME("%p %u - stub\n", This, index);
11257 return E_NOTIMPL;
11260 static HRESULT WINAPI ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2 *iface,
11261 REFGUID guid, VARIANT *varVal)
11263 TLBGuid *tlbguid;
11265 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11267 TRACE("%p %s %p\n", This, debugstr_guid(guid), varVal);
11269 if (!guid || !varVal)
11270 return E_INVALIDARG;
11272 tlbguid = TLB_append_guid(&This->pTypeLib->guid_list, guid, -1);
11274 return TLB_set_custdata(This->pcustdata_list, tlbguid, varVal);
11277 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2 *iface,
11278 UINT index, REFGUID guid, VARIANT *varVal)
11280 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11281 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11282 return E_NOTIMPL;
11285 static HRESULT WINAPI ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2 *iface,
11286 UINT funcIndex, UINT paramIndex, REFGUID guid, VARIANT *varVal)
11288 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11289 FIXME("%p %u %u %s %p - stub\n", This, funcIndex, paramIndex, debugstr_guid(guid), varVal);
11290 return E_NOTIMPL;
11293 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2 *iface,
11294 UINT index, REFGUID guid, VARIANT *varVal)
11296 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11297 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11298 return E_NOTIMPL;
11301 static HRESULT WINAPI ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2 *iface,
11302 UINT index, REFGUID guid, VARIANT *varVal)
11304 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11305 FIXME("%p %u %s %p - stub\n", This, index, debugstr_guid(guid), varVal);
11306 return E_NOTIMPL;
11309 static HRESULT WINAPI ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2 *iface,
11310 ULONG helpStringContext)
11312 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11314 TRACE("%p %u\n", This, helpStringContext);
11316 This->dwHelpStringContext = helpStringContext;
11318 return S_OK;
11321 static HRESULT WINAPI ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2 *iface,
11322 UINT index, ULONG helpStringContext)
11324 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11325 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11326 return E_NOTIMPL;
11329 static HRESULT WINAPI ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2 *iface,
11330 UINT index, ULONG helpStringContext)
11332 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11333 FIXME("%p %u %u - stub\n", This, index, helpStringContext);
11334 return E_NOTIMPL;
11337 static HRESULT WINAPI ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2 *iface)
11339 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11340 FIXME("%p - stub\n", This);
11341 return E_NOTIMPL;
11344 static HRESULT WINAPI ICreateTypeInfo2_fnSetName(ICreateTypeInfo2 *iface,
11345 LPOLESTR name)
11347 ITypeInfoImpl *This = info_impl_from_ICreateTypeInfo2(iface);
11349 TRACE("%p %s\n", This, wine_dbgstr_w(name));
11351 if (!name)
11352 return E_INVALIDARG;
11354 This->Name = TLB_append_str(&This->pTypeLib->name_list, name);
11356 return S_OK;
11359 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl = {
11360 ICreateTypeInfo2_fnQueryInterface,
11361 ICreateTypeInfo2_fnAddRef,
11362 ICreateTypeInfo2_fnRelease,
11363 ICreateTypeInfo2_fnSetGuid,
11364 ICreateTypeInfo2_fnSetTypeFlags,
11365 ICreateTypeInfo2_fnSetDocString,
11366 ICreateTypeInfo2_fnSetHelpContext,
11367 ICreateTypeInfo2_fnSetVersion,
11368 ICreateTypeInfo2_fnAddRefTypeInfo,
11369 ICreateTypeInfo2_fnAddFuncDesc,
11370 ICreateTypeInfo2_fnAddImplType,
11371 ICreateTypeInfo2_fnSetImplTypeFlags,
11372 ICreateTypeInfo2_fnSetAlignment,
11373 ICreateTypeInfo2_fnSetSchema,
11374 ICreateTypeInfo2_fnAddVarDesc,
11375 ICreateTypeInfo2_fnSetFuncAndParamNames,
11376 ICreateTypeInfo2_fnSetVarName,
11377 ICreateTypeInfo2_fnSetTypeDescAlias,
11378 ICreateTypeInfo2_fnDefineFuncAsDllEntry,
11379 ICreateTypeInfo2_fnSetFuncDocString,
11380 ICreateTypeInfo2_fnSetVarDocString,
11381 ICreateTypeInfo2_fnSetFuncHelpContext,
11382 ICreateTypeInfo2_fnSetVarHelpContext,
11383 ICreateTypeInfo2_fnSetMops,
11384 ICreateTypeInfo2_fnSetTypeIdldesc,
11385 ICreateTypeInfo2_fnLayOut,
11386 ICreateTypeInfo2_fnDeleteFuncDesc,
11387 ICreateTypeInfo2_fnDeleteFuncDescByMemId,
11388 ICreateTypeInfo2_fnDeleteVarDesc,
11389 ICreateTypeInfo2_fnDeleteVarDescByMemId,
11390 ICreateTypeInfo2_fnDeleteImplType,
11391 ICreateTypeInfo2_fnSetCustData,
11392 ICreateTypeInfo2_fnSetFuncCustData,
11393 ICreateTypeInfo2_fnSetParamCustData,
11394 ICreateTypeInfo2_fnSetVarCustData,
11395 ICreateTypeInfo2_fnSetImplTypeCustData,
11396 ICreateTypeInfo2_fnSetHelpStringContext,
11397 ICreateTypeInfo2_fnSetFuncHelpStringContext,
11398 ICreateTypeInfo2_fnSetVarHelpStringContext,
11399 ICreateTypeInfo2_fnInvalidate,
11400 ICreateTypeInfo2_fnSetName
11403 /******************************************************************************
11404 * ClearCustData (OLEAUT32.171)
11406 * Clear a custom data type's data.
11408 * PARAMS
11409 * lpCust [I] The custom data type instance
11411 * RETURNS
11412 * Nothing.
11414 void WINAPI ClearCustData(CUSTDATA *lpCust)
11416 if (lpCust && lpCust->cCustData)
11418 if (lpCust->prgCustData)
11420 DWORD i;
11422 for (i = 0; i < lpCust->cCustData; i++)
11423 VariantClear(&lpCust->prgCustData[i].varValue);
11425 CoTaskMemFree(lpCust->prgCustData);
11426 lpCust->prgCustData = NULL;
11428 lpCust->cCustData = 0;